I have been thinking a lot about variables and note properties recently. You know that, if you read A Better Way to Solve the Same Problem. It sets the stage for what we are going to see today. The question that started that post was, whether or not I could add note properties to a single variable, such as PowerShell does with the $PROFILE
variable. I could. I ended up creating a variable that held one URL when you returned the variable but also held four other URLs, one in each additional note property.
I want to take this further, and the best part is that all the things I was worried about trying to do myself, PowerShell just does for me without any thinking about it. Follow along and you will see.
Let’s set up the variable I was using last time to help this recap. Then we will create another variable and work with it to explore some new things I learned. Building this variable is being done a little differently than it was previously. It incorporates some concepts from another recent post, There is a Difference: Arrays Versus Hash Tables. First, we will assign our initial value to the variable.
$PSSites = 'https://docs.microsoft.com/en-us/powershell/scripting/overview'
Next, we will create a hash table that includes four key-value pairs. Each pair includes a website name and an associated URL, because as we learned in that post, a hash table is an associative array.
$Sites = @{ GitHub = 'https://github.com/PowerShell/PowerShell' Docs = 'https://docs.microsoft.com/en-us/powershell/' Gallery = 'https://www.powershellgallery.com/' Reddit = 'https://www.reddit.com/r/PowerShell/' }
Following that, we will use the foreach
statement to loop through the key-value pairs in the hash table, running Add-Member
against each of them, and thusly adding each as a note property on our $PSSites
variable.
foreach ($Site in $Sites.GetEnumerator()) { $PSSites = $PSSites | Add-Member -NotePropertyName $Site.Key -NotePropertyValue $Site.Value -PassThru }
We can use Get-Member
to ensure the previous command added the additional URLs as note properties.
$PSSites | Get-Member -MemberType NoteProperty TypeName: System.String Name MemberType Definition ---- ---------- ---------- Docs NoteProperty string Docs=https://docs.microsoft.com/en-us/powershell/ Gallery NoteProperty string Gallery=https://www.powershellgallery.com/ GitHub NoteProperty string GitHub=https://github.com/PowerShell/PowerShell Reddit NoteProperty string Reddit=https://www.reddit.com/r/PowerShell/
At this point, we have our own variable like the $PROFILE
variable that contains multiple string values. We can access the note properties of $PSSites
using dot notation.
$PSSites.GitHub $PSSites.docs $PSSites.Gallery $PSSites.Reddit https://github.com/PowerShell/PowerShell https://docs.microsoft.com/en-us/powershell/ https://www.powershellgallery.com/ https://www.reddit.com/r/PowerShell/
Now, let’s create another variable and add some members to it, as well. These will be a little different and you will see that momentarily. We will start by assigning a string value to the variable, as we did above.
$TestingVariable = 'A string value' $TestingVariable A string value
Before we add the rest, I suppose I should remind everyone about my end goal written at the bottom of the first post linked above: Save the previous value of a variable to a note property when assigning a new value to the variable itself.
This would be much easier if we could guarantee that every new value assigned to the variable was a string, and therefore, every old value property would also be a string. My worries, as mentioned earlier, were about arrays, hash tables, ordered dictionaries, and other data structures I may have to save to a note property. Can other data structures like those be put in a note property? Let’s work through these data structures and see if we can get them into note properties, to begin with. In this example, we will add two arrays to two separate note properties, as Array01
and Array02
. One of these will and one will not use the array, sub-expression operator (@()
).
$TestingVariable = $TestingVariable | Add-Member -NotePropertyName 'Array01' -NotePropertyValue 1,2,3 -PassThru $TestingVariable = $TestingVariable | Add-Member -NotePropertyName 'Array02' -NotePropertyValue @(4,5,6) -PassThru
Here, we will create a hash table and store it in the $HashTable
variable. We will then use that variable as a part of another Add-Member
command.
$HashTable = @{Dad = 'David'; Mom = 'Betty'; Daughter = 'Janice'; Son = 'Bryan'} $TestingVariable = $TestingVariable | Add-Member -NotePropertyName 'HashTable' -NotePropertyValue $HashTable -PassThru
Finally, we’ll create an ordered dictionary and add it as a note property, as well. If the hash table takes, then it is probably safe to assume this will take, too.
$OrderedDictionary = [ordered]@{ Monday = 'Chipotle' Tuesday = 'Pizza' Wednesday = 'Mahi Mahi'; Thursday = 'Ravioli' Friday = 'Orange Chicken' } $TestingVariable = $TestingVariable | Add-Member -NotePropertyName 'OrderedDictionary' -NotePropertyValue $OrderedDictionary -PassThru
At this point, we should probably see what Get-Member
returns about the note properties we have assigned to our $TestingVariable
. We have yet to test that anything has actually been added so far, although we have not received any errors stating otherwise. In the below example, we can see the four, note properties that we have added. The best part, the definition property indicates it knew the data structure of these when they were added as note properties. The arrays show object[]
, the hash table, hashtable
, and the ordered dictionary, OrderedDictionary
.
$TestingVariable | Get-Member -MemberType NoteProperty TypeName: System.String Name MemberType Definition ---- ---------- ---------- Array01 NoteProperty Object[] Array01=System.Object[] Array02 NoteProperty Object[] Array02=System.Object[] HashTable NoteProperty hashtable Hash Table=System.Collections.Hashtable OrderedDictionary NoteProperty OrderedDictionary Ordered Dictionary=System.Collections.Specialized.OrderedDictionary
Let’s take a closer look at each of our new note properties. For each of them, we will run GetType()
against the note property and then return the value it has stored. When we return a note property that contains an array, it returns that. Same for the others; the data structure was recognized and retained when it was added as a member. And it is respected on the way out, too. I cannot tell you how grateful I am that I do not have to be the one to figure out the underlying data structure of a value going in and then coming back out. This is great news for some of the other things I have planned.
$TestingVariable.Array01.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array $TestingVariable.Array01 1 2 3 $TestingVariable.Array02.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array $TestingVariable.Array02 4 5 6 $TestingVariable.HashTable.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Hashtable System.Object $TestingVariable.HashTable Name Value ---- ----- Daughter Janice Son Bryan Dad David Mom Betty $TestingVariable.OrderedDictionary.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True OrderedDictionary System.Object $TestingVariable.OrderedDictionary Name Value ---- ----- Monday Chipotle Tuesday Pizza Wednesday Mahi Mahi Thursday Ravioli Friday Orange Chicken