{"id":12381,"date":"2011-10-16T00:01:00","date_gmt":"2011-10-16T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2011\/10\/16\/dealing-with-powershell-hash-table-quirks\/"},"modified":"2011-10-16T00:01:00","modified_gmt":"2011-10-16T00:01:00","slug":"dealing-with-powershell-hash-table-quirks","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/dealing-with-powershell-hash-table-quirks\/","title":{"rendered":"Dealing with PowerShell Hash Table Quirks"},"content":{"rendered":"<p><strong>Summary:<\/strong> Microsoft Scripting Guy Ed Wilson shows how to deal with two Windows PowerShell hash table quirks.<\/p>\n<p>&nbsp;<\/p>\n<p>Microsoft Scripting Guy Ed Wilson here. Our week in Ottawa draws to a close. We leave for Montreal today, and are really excited about the Windows PowerShell people we will meet while we are there. I enjoyed working on my Windows PowerShell Quiz scripts this week. The point of the articles was not so much about creating a quiz engine, but the fact that it offered a good exercise for working on function design and with hash tables.<\/p>\n<p>Today, I want to focus in on two aspects of hash tables that came up this week while I was writing the scripts. The first aspect I want talk about is piping a hash table to other cmdlets. This also comes into play when supplying a hash table to a cmdlet as an <b>inputobject<\/b>. As an example, I will use the hash table created in yesterday&rsquo;s post, <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2011\/10\/15\/automatically-create-a-powershell-hash-table-10-15-11.aspx\">Easily Create a PowerShell Hash Table<\/a><i>. <\/i><\/p>\n<p>Here is the DemoHashtableWithProcesses.ps1 script that creates a hash table from process information:<\/p>\n<p style=\"padding-left: 30px\">$hash = $null<\/p>\n<p style=\"padding-left: 30px\">$hash = @{}<\/p>\n<p style=\"padding-left: 30px\">$proc = get-process | Sort-Object -Property name -Unique<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p style=\"padding-left: 30px\">foreach ($p in $proc)<\/p>\n<p style=\"padding-left: 30px\">{<\/p>\n<p style=\"padding-left: 30px\">&nbsp;$hash.add($p.name,$p.id)<\/p>\n<p style=\"padding-left: 30px\">}<\/p>\n<p style=\"padding-left: 30px\">$hash<\/p>\n<p>&nbsp;<\/p>\n<p>The <b>$hash<\/b> variable contains a hash table with a number of key value pairs in it. The <b>count<\/b><i> <\/i>property tells me how many items are in the hash table. When I pipe the hash table to the <b>Get-Random<\/b> cmdlet and tell the <b>Get-Random<\/b> cmdlet to return one random key value pair, the results are confusing. Here is the command I am talking about:<\/p>\n<p style=\"padding-left: 30px\">$hash | Get-Random -Count 1<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/3632.hsg-10-16-11-1.png\"><img decoding=\"async\" style=\"border: 0px\" title=\"Image of command and associated output\" alt=\"Image of command and associated output\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/3632.hsg-10-16-11-1.png\" \/><\/a><\/p>\n<p>As seen in the previous figure, all the key value pairings from the hash table are returned. I was expecting a single, randomly selected pair. I see this same problem when using the <b>Sort-Object <\/b>cmdlet. For example, when I type the following command, I expect to see the processes sorted by name:<\/p>\n<p style=\"padding-left: 30px\">$hash | Sort-Object -Property name<\/p>\n<p>But as shown in the following figure, the sort is not working.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2626.hsg-10-16-11-2.png\"><img decoding=\"async\" style=\"border: 0px\" title=\"Image of sort not working\" alt=\"Image of sort not working\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2626.hsg-10-16-11-2.png\" \/><\/a><\/p>\n<p>The problem extends itself even to the <b>Where-Object<\/b>. The following command returns nothing, even though there is a process with a value of 6108:<\/p>\n<p style=\"padding-left: 30px\">$hash | Where-Object { $_.value -eq 6108}<\/p>\n<p>I solved this problem earlier in the week in <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2011\/10\/12\/create-a-powershell-quiz-script.aspx\">Create a PowerShell Quiz Script<\/a> post by getting a collection of keys, walking through the keys, and using the <b>item<\/b><i> <\/i>method to retrieve the associated value.<\/p>\n<p>The applicable line of code is shown here:<\/p>\n<p style=\"padding-left: 30px\">Function New-Question<\/p>\n<p style=\"padding-left: 30px\">{<\/p>\n<p style=\"padding-left: 30px\">&nbsp;Param(<\/p>\n<p style=\"padding-left: 30px\">&nbsp; [hashtable]$Puzzle<\/p>\n<p style=\"padding-left: 30px\">&nbsp;)<\/p>\n<p style=\"padding-left: 30px\">&nbsp; Foreach ($p in $puzzle.KEYS)<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp; {<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; $rtn = Read-host &#8220;What is the cmdlet name $($puzzle.item($P))&#8221;<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; If($puzzle.contains($rtn))<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp; { &#8220;Correct $($puzzle.item($P)) equals $p&#8221; }<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; ELSE<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp; {&#8220;Sorry. $rtn is not right. $($puzzle.item($P)) is $p&#8221; }<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; } #end foreach $P<\/p>\n<p style=\"padding-left: 30px\">}<br \/>#end function New-Question<\/p>\n<p>Though this methodology works just fine for the Windows PowerShell Quiz script, it is too much trouble to do for a simple pipeline operation. There needs to be an easier way to walk through a hash table. And there is! The secret is to use the <b>getEnumerator<\/b><i> <\/i>method from the <b>hashtable <\/b>object. If I want to choose a random key value pair from a hash table, I call the <b>getenumerator<\/b><i> <\/i>method prior to passing it to the <b>Get-Random<\/b> cmdlet. The command is shown here:<\/p>\n<p style=\"padding-left: 30px\">$hash.getenumerator() | Get-Random -Count 1<\/p>\n<p>The <b>GetEnumerator<\/b><i> <\/i>method works the same way with the <b>Where-Object<\/b> cmdlet. The command is shown here:<\/p>\n<p style=\"padding-left: 30px\">$hash.GetEnumerator() | Where-Object { $_.value -eq 6108}<\/p>\n<p>It also works with the <b>Sort-Object<\/b> cmdlet, as shown here:<\/p>\n<p style=\"padding-left: 30px\">$hash.GetEnumerator() | Sort-Object -Property name<\/p>\n<p>All three of these commands and their associated output are shown in the following figure.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2072.hsg-10-16-11-3.png\"><img decoding=\"async\" style=\"border: 0px\" title=\"Image of commands and associated output\" alt=\"Image of commands and associated output\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2072.hsg-10-16-11-3.png\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>The second topic I want to talk about came up while I was writing <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2011\/10\/14\/create-a-powershell-quiz-by-reading-a-text-file.aspx\">Create a PowerShell Quiz by Reading a Text File<\/a>.<i> <\/i><\/p>\n<p>All the examples of using the <b>ConvertFrom-StringData <\/b>cmdlet illustrate using a <b>Here-String <\/b>or similar hardcoded string data to create a hash table. This technique will not work for me because I wanted to read a text file. My first attempt generated the error shown here:<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; ConvertFrom-StringData C:\\fso\\Questions.txt<\/p>\n<p style=\"padding-left: 30px\">ConvertFrom-StringData : Data line &#8216;C:\\fso\\Questions.txt&#8217; is not in &#8216;name=value&#8217; format.<\/p>\n<p style=\"padding-left: 30px\">At line:1 char:23<\/p>\n<p style=\"padding-left: 30px\">+ ConvertFrom-StringData &lt;&lt;&lt;&lt;&nbsp;C:\\fso\\Questions.txt<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; + CategoryInfo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : InvalidOperation: (:) [ConvertFrom-StringData], PSInvalidOperationException<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; + FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.ConvertFromStringDataCommand<\/p>\n<p>The error basically says that my input file is not in <b>name=value<\/b> format. But as shown in the following figure, that is not true.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/3022.hsg-10-16-11-4.png\"><img decoding=\"async\" style=\"border: 0px\" title=\"Image showing error message is not true\" alt=\"Image showing error message is not true\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/3022.hsg-10-16-11-4.png\" width=\"479\" height=\"284\" \/><\/a><\/p>\n<p>So, I thought I needed to read the content of the file first. This time I got the error shown here:<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; ConvertFrom-StringData (Get-content C:\\fso\\Questions.txt)<\/p>\n<p style=\"padding-left: 30px\">ConvertFrom-StringData : Cannot convert &#8216;System.Object[]&#8217; to the type &#8216;System.String&#8217; required by parameter &#8216;StringData<\/p>\n<p style=\"padding-left: 30px\">&#8216;. Specified method is not supported.<\/p>\n<p style=\"padding-left: 30px\">At line:1 char:23<\/p>\n<p style=\"padding-left: 30px\">+ ConvertFrom-StringData &lt;&lt;&lt;&lt;&nbsp; (Get-content C:\\fso\\Questions.txt)<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; + CategoryInfo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : InvalidArgument: (:) [ConvertFrom-StringData], ParameterBindingException<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.ConvertFromStringDataCommand<\/p>\n<p>Next, I got the idea to pipe the information to the cmdlet. When I did this, it appeared I had hit upon a successful combination:<\/p>\n<p style=\"padding-left: 30px\">PS<br \/>C:\\&gt; Get-Content C:\\fso\\Questions.txt | ConvertFrom-StringData<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p style=\"padding-left: 30px\">Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Value<\/p>\n<p style=\"padding-left: 30px\">&#8212;-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8212;&#8211;<\/p>\n<p style=\"padding-left: 30px\">Canberra&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Australia<\/p>\n<p style=\"padding-left: 30px\">Berlin&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Germany<\/p>\n<p style=\"padding-left: 30px\">Ottawa&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Canada<\/p>\n<p>I then tried to use my hash table. So I stored the hash table in a variable, and attempted to access the <b>keys<\/b><i> <\/i>property, as shown here:<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $hash = Get-Content C:\\fso\\Questions.txt | ConvertFrom-StringData<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $hash.keys<\/p>\n<p>Nothing came back. There are no keys? So, I examined the <b>$hash<\/b> variable by using the <b>Get-Member <\/b>&nbsp;cmdlet (<b>gm<\/b> is an alias). The results of this exploration are shown here:<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $hash | gm<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp; TypeName: System.Collections.Hashtable<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p style=\"padding-left: 30px\"><span style=\"text-decoration: underline\">Name<\/span>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style=\"text-decoration: underline\">MemberType<\/span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style=\"text-decoration: underline\">Definition<\/span><\/p>\n<p style=\"padding-left: 30px\">Add&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Method&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.Void Add(System.Object key, System.Object value)<\/p>\n<p style=\"padding-left: 30px\">Clear&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Method&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.Void Clear()<\/p>\n<p style=\"padding-left: 30px\">Clone&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Method&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.Object Clone()<\/p>\n<p style=\"padding-left: 30px\">Contains&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Method&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool Contains(System.Object key)<\/p>\n<p style=\"padding-left: 30px\">ContainsKey&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Method&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bool ContainsKey(System.Object key)<\/p>\n<p style=\"padding-left: 30px\">ContainsValue&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Method&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool ContainsValue(System.Object value)<\/p>\n<p style=\"padding-left: 30px\">CopyTo &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Method &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Void CopyTo(array array, int arrayIndex)<\/p>\n<p style=\"padding-left: 30px\">Equals&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Method &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool Equals(System.Object obj)<\/p>\n<p style=\"padding-left: 30px\">GetEnumerator&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Method &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Collections.IDictionaryEnumerator GetEnumerator()<\/p>\n<p style=\"padding-left: 30px\">GetHashCode&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Method &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int GetHashCode()<\/p>\n<p style=\"padding-left: 30px\">GetObjectData&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Method &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Void GetObjectData(System.Runtime.Serialization.SerializationInfo inf&#8230;<\/p>\n<p style=\"padding-left: 30px\">GetType&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Method &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type GetType()<\/p>\n<p style=\"padding-left: 30px\">OnDeserialization&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Method &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Void OnDeserialization(System.Object sender)<\/p>\n<p style=\"padding-left: 30px\">Remove &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Method &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Void Remove(System.Object key)<\/p>\n<p style=\"padding-left: 30px\">ToString&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Method &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string ToString()<\/p>\n<p style=\"padding-left: 30px\">Item&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ParameterizedProperty&nbsp;&nbsp; System.Object Item(System.Object key) {get;set;}<\/p>\n<p style=\"padding-left: 30px\">Count&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Property&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Int32 Count {get;}<\/p>\n<p style=\"padding-left: 30px\">IsFixedSize&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Property&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Boolean IsFixedSize {get;}<\/p>\n<p style=\"padding-left: 30px\">IsReadOnly&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Property&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Boolean IsReadOnly {get;}<\/p>\n<p style=\"padding-left: 30px\">IsSynchronized&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Property&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Boolean IsSynchronized {get;}<\/p>\n<p style=\"padding-left: 30px\">Keys&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Property&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Collections.ICollection Keys {get;}<\/p>\n<p style=\"padding-left: 30px\">SyncRoot&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Property&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Object SyncRoot {get;}<\/p>\n<p style=\"padding-left: 30px\">Values&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Property&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Collections.ICollection Values {get;}<\/p>\n<p>&nbsp;<\/p>\n<p>Well, it looks like it is a hash table. So how about looking at the <b>values<\/b><i> <\/i>property? The results are shown here&mdash;nothing. Next, I use the <b>count<\/b><i> <\/i>property, and it tells me I have three items in the hash table.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $hash.values<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $hash.count<\/p>\n<p style=\"padding-left: 30px\">3<\/p>\n<p>This looks really weird. Then I had an idea: I wonder if somehow I obtained an array. I index into the array, and sure enough, I have an array of hash tables. This is shown here:<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $hash[0]<\/p>\n<p style=\"padding-left: 30px\"><span style=\"text-decoration: underline\">Name<\/span>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style=\"text-decoration: underline\">Value<\/span><\/p>\n<p style=\"padding-left: 30px\">Canberra&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Australia<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $hash[1]<\/p>\n<p style=\"padding-left: 30px\"><span style=\"text-decoration: underline\">Name<\/span>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style=\"text-decoration: underline\">Value<\/span><\/p>\n<p style=\"padding-left: 30px\">Berlin&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Germany<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $hash[2]<\/p>\n<p style=\"padding-left: 30px\"><span style=\"text-decoration: underline\">Name<\/span>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style=\"text-decoration: underline\">Value<\/span><\/p>\n<p style=\"padding-left: 30px\">Ottawa&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Canada<\/p>\n<p>I have an array of hash tables because of the way that <b>Get-Content<\/b> returns information. It returns an array. One element for each line of the file is a behavior that is normally fine. But in this example, the behavior causes problems. The easy way around this is to use the <b>ReadAlltext<\/b><i> <\/i>static method from the <b>io.file <\/b>.NET Framework class. This technique is shown here:<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; ConvertFrom-StringData ([io.file]::ReadAllText(&#8220;C:\\fso\\Questions.txt&#8221;))<\/p>\n<p style=\"padding-left: 30px\"><span style=\"text-decoration: underline\">Name<\/span>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style=\"text-decoration: underline\">Value<\/span><\/p>\n<p style=\"padding-left: 30px\">Berlin&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Germany<\/p>\n<p style=\"padding-left: 30px\">Canberra&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Australia<\/p>\n<p style=\"padding-left: 30px\">Ottawa&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Canada<\/p>\n<p>&nbsp;<\/p>\n<p>That&rsquo;s it for today. Join me tomorrow for more Windows PowerShell goodness. See you then.<\/p>\n<p>I invite you to follow me on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"mailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<p>&nbsp;<\/p>\n<p><b>Ed Wilson, Microsoft Scripting Guy<\/b><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Microsoft Scripting Guy Ed Wilson shows how to deal with two Windows PowerShell hash table quirks. &nbsp; Microsoft Scripting Guy Ed Wilson here. Our week in Ottawa draws to a close. We leave for Montreal today, and are really excited about the Windows PowerShell people we will meet while we are there. I enjoyed [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[292,3,4,45],"class_list":["post-12381","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-arrays-hashtables-and-dictionary-objects","tag-scripting-guy","tag-scripting-techniques","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Microsoft Scripting Guy Ed Wilson shows how to deal with two Windows PowerShell hash table quirks. &nbsp; Microsoft Scripting Guy Ed Wilson here. Our week in Ottawa draws to a close. We leave for Montreal today, and are really excited about the Windows PowerShell people we will meet while we are there. I enjoyed [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/12381","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=12381"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/12381\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=12381"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=12381"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=12381"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}