Learn about Windows PowerShell
Summary: Learn how to use an easy-to-use Windows PowerShell cmdlet to simplify creating hash tables.
Hey, Scripting Guy! Good morning, Ed. I have been a Scripting Guy fan for years and although I have not read all the thousands of posts, I have definitely read more than a few of them. This is the first time I have felt compelled to write. Like many others, I have become a Windows PowerShell addict. There is one thing that puzzles me, why is it so difficult to create a hash table? It seems that Windows PowerShell loves hash tables so one would expect it to be easy to do. But no, if I have a text file, or even a string, I have to loop through it, select key / value pairs, and manually add them to the table. That is so VBScript-like it is not even funny. If I wanted to write VBScript code, I would write VBScript and avoid all the curly brackets and dollar signs. Dude, I guess you can figure out that I just wasted several hours on this. Sorry to take it out on you.
Hello MP, Microsoft Scripting Guy Ed Wilson here. It is nice to escape the cold weather for a bit. The Scripting Wife and I headed down to Tampa, Florida for SQL Saturday. I will probably post some pictures later. It is awesome to spend time with people who are so passionate about technology that they are willing to give up their Saturday to learn about SQL Server and about Windows PowerShell. What is really impressive are the people who give up weeks of free time to organize and host the event.
Anyway MP, I can definitely sympathize with you when seemingly simple things end up being a major pain to work with. But you know what? By default, there are 236 Windows PowerShell cmdlets installed on Windows 7. I found this out by using the Get-Command cmdlet (alias is GCM) and piping it to the Measure-Object cmdlet (alias is Measure). Here is the command.
PS C:\> gcm -CommandType cmdlet | measure
Count : 236
Of the 236 Windows PowerShell cmdlets, how many of them do you use regularly? For that matter, how many of them do I use in my daily scripting activities? If you are not sure, you may want to play around with the Windows PowerShell tokenizer. I wrote a really cool post one weekend that was called “Playing around with the Windows PowerShell tokenizer.”
Anyway, the result of such experimentation will probably reveal dozens of Windows PowerShell cmdlets that you do not use. I know that was my case.
So, MP, what does this have to do with you? There is a Windows PowerShell cmdlet called ConvertFrom-StringData that will take string data and convert it into a hash table. It sounds just like the tool that you need to add to your repertoire. Here is an example of how to use it. I use the `n character because it is the new line character in Windows PowerShell. ConvertFrom-StringData needs the string data to be separated by a new line. Note also that the format of the string is key = value.
$string = "item1 = value1 `nitem2 = value2"
$hash = ConvertFrom-StringData -StringData $string
When I run this code, the following figure appears.
Another way to use the ConvertTo-StringData Windows PowerShell cmdlet is to feed it data that is stored in a here-string. I have talked about here-strings on the Hey, Scripting Guy! Blog several times. I love them because they can simplify things. For example, a here-string ignores the need for special formatting rules. I can use a here-string, and ignore things such as escaping quotation marks with other quotation marks. The code shown here uses a here-string to store the string data that will be converted to a hash table.
$hereString = @"
key1 = value1
key2 = value2
#this is a comment
key3 = value3
$hash = ConvertFrom-StringData -StringData $hereString
When I run the code, the results seen in the following figure appear.
To address directly the issue that you are having problems with, I first create a text file that appears in the following figure.
After I have the text file, I use the Get-Content PowerShell cmdlet to read the contents of the text file and I pipeline the results to the ConvertTo-StringData cmdlet. The code to do this is less complicated than that previously examined, and it appears here.
$hash=Get-Content -Path C:\fso\keyValues.txt |
When I run the above code, the output seen in the following figure appears.
One thing that is cool about creating hash tables is many Windows PowerShell cmdlets will accept a hash table for input. For example, a query hash created via a here-string is supplied to the Get-WinEvent Windows PowerShell cmdlet to retrieve status information about the SnapDrive service on my computer. The Script appears here.
$text = @"
LogName = Application
ID = 100
$query = ConvertFrom-StringData -StringData $text
Get-WinEvent -FilterHashtable $query
Of course, this particular example is a bit heavy handed but the example could be easily extended to provide a powerful solution for querying not only online event logs, but stored ETL logs also. This opens up some really exciting solutions for monitoring.
MP, that is all there is to using the ConvertFrom-StringData Windows PowerShell cmdlet. Neglected cmdlet week will continue tomorrow.
I invite you to follow me on Twitter or Facebook. If you have any questions, send email to me at email@example.com or post them on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy
What I dont like about the $herestring / queryapplicationlogwithhashtable.ps1 examples is that you cant indent the code, it has to be all the way to the left of your script page :( otherwise, it really is a cool feature that I've already messed with.
I agree 100% ...
So I used this command:
$setup = get-content .\Config.txt | Convertfrom-StringData
And I didn't get a hash table. I got an array. Why?
The file contains a dozen or so lines in the format of name = value (No quotes in the file, but there are periods, commas and @ in the values
On a few I want to put $True or $Null. I didn't know if Powershell would interpret those
I'm not sure, but I think there might be something quite misleading here.
The following command won't give you a hashtable:
$hash=Get-Content -Path C:\fso\keyValues.txt | ConvertFrom-StringData
unless you read it in as a long character string
$hash=Get-Content -Path C:\fso\keyValues.txt | Out-String | ConvertFrom-StringData
At least, it didn't for me.
Thanks a lot. Quite helpful. Cheers
Convertfrom-stringdata converts to an array indeed, just as sorting a hashtable.
Hi, just noticed that when working with unc paths, e.g. \\servername\path = \\servername\path fails to populate the hash table. The solution is to use the following configuration, e.g. \\servername\path=\\\\servername\\path so although one can convert
to string you can escape special characters and allow the table to be created.