How to Store a Variable’s Previous Value with the New Value
There was a recent post on the PowerShell Facebook group that said this: “Is there a function or option to check previous $Global:variable -ne Current $Global:variable?” The person that created the post wanted to know if there’s a way to recall the last value a variable stored, once it had already been assigned something new. Here’s my answer, and potential solution.
You have to think about a variable’s previous assignment, as if it never existed, even though you know that variable held something, or was assigned something, previously. Once its value is gone, it’s gone. Now, all that said, I came up with an option. The option, is to use a variable’s description property to store its previous value.
Let’s begin by checking the value of an uninitialized variable, and then assign it something.
PS > $x PS > # No value. PS > $x = 'first value' PS > $x first value
Now that our variable has a value, let’s take a look at all the variable’s properties using the Get-Variable cmdlet. Notice the Description property; we’re going to use this in a less than conventional way.
PS > Get-Variable -Name x | Select-Object -Property * Name : x Description : Value : first value Visibility : Public Module : ModuleName : Options : None Attributes : {}
Using the Set-Variable cmdlet, we’ll make two modifications to our variable, at nearly the same time. First, we’ll update the Description property, so that it’s holding the original variable assignment (the string ‘first value’). In the same, Set-Variable command, we’ll modify the current value of the variable to the string ‘second value.’ Notice in the final below command, that our Description property has a value now, too.
PS > Set-Variable -Name x -Value 'second value' -Description $x PS > $x second value PS > Get-Variable -Name x | Select-Object -Property * Name : x Description : first value Value : second value Visibility : Public Module : ModuleName : Options : None Attributes : {}
In the next example, you’ll see how we can return the original value and the variable’s updated value. Beneath that, I’ve included a couple ways to compare these values. That gets back to what the person on Facebook was trying to determine. Again, this is fairly unconventional use of the Description property, but it does avoid the need for a second variable to hold the first variable’s original value. That said, one of my examples uses a second, comparison variable.
PS > (Get-Variable -Name x).Description first value PS > (Get-Variable -Name x).Value second value PS > $x second value PS > (Get-Variable -Name x).Description -ne (Get-Variable -Name x).Value True PS > (Get-Variable -Name x).Description -ne $x True PS > $y = (Get-Variable -Name x).Description PS > $y -ne $x True
In these last examples, we’re running into a bit of a problem, we are going to have to keep in mind (if anyone even dares use this approach). When we take a value that isn’t a string, and place it into the Description property, it becomes a string. That means, that when we take it back out, we’ll need to cast it back to its proper type. Take a look at the next series of examples for some assistance with this concept.
PS > $z = 5 PS > Set-Variable -Name z -Value 10 -Description $z PS > Get-Variable -Name z | Select-Object -Property * Name : z Description : 5 Value : 10 Visibility : Public Module : ModuleName : Options : None Attributes : {} PS > (Get-Variable -Name z).Description | Get-Member | >>> Select-Object -Property TypeName -Unique TypeName -------- System.String PS > [int](Get-Variable -Name z).Description 5 PS > [int](Get-Variable -Name z).Description | Get-Member | >>> Select-Object -Property TypeName -Unique TypeName -------- System.Int32
This goes for decimals values, too. If you use the Description property to store something that’s not a string, then you’re going to have to properly cast it when you’re taking it out, or you’re going to have a string. In these next examples, I used the GetType method to determine the value’s type, as opposed to Get-Member and Select-Object used above.
PS > $m = 2.5 PS > $m.GetType().Name Double PS > Set-Variable -Name m -Value 3.5 -Description $m PS > $m 3.5 PS > $m.GetType().Name Double PS > (Get-Variable -Name m).Description 2.5 PS > (Get-Variable -Name m).Description.GetType().Name String PS > [double](Get-Variable -Name m).Description 2.5 PS > ([double](Get-Variable -Name m).Description).GetType().Name Double
And that’s it. It’s may not be the first choice for saving a previous variable’s value, but it’s a choice. I rather liked the array option that was recommended; however, like the $Error array, I’d be tempted to put the newest/current value of a variable into index 0 and not at the end of the array. Anyway, back to real life now.