I wanted to share a quick hint about a cmdlet, ConvertFrom-StringData, I had the opportunity to put to use recently. ConvertFrom-StringData has been around since version 2.0 I believe but I wasn’t able to confirm that. What it basically does is take a string input and convert any key value pairs (“this = something”) it finds and converts them to a hashtable (i.e. object) that is familiar and consumable by everything PowerShell.
I spend a lot of my time at work integrating, consuming, and otherwise finagling something that doesn’t know about PowerShell and making it work with PowerShell. Until recently I had a lot of code that imported various sundry content with Get-Content then mashed it with various permutations of Select-String or regexp of some variety just to get an object that I could run with. That is the case no more.
For example a file (called “something.conf”) with the following content:
# This is a comment URL=http://example.com HOST=s.example.com USER=bob smith # More comments FILE=somewhere.txt
Could be imported into a PowerShell hashtable as follows:
ConvertFrom-StringData -StringData (Get-Content -Raw -Path .\something.conf)
Will get you the following:
Name Value ---- ----- HOST s.example.com FILE somewhere.txt USER bob smith URL http://example.com
Which is a nice pretty hashtable. It even was smart enough to exclude the lines with comments (“#”). There are a couple of caveats here. If the file you are ingesting uses a comment character other than “#” (say “;”) then you would still have to do some manipulation before ingesting that string with the cmdlet. However ConvertFrom-StringData has cut out and certainly streamlined some of my mashing code. It is always nice to remove regexp stuff with a simple one-liner cmdlet.
In the command above I made sure to use the -Raw switch (new with version 3.0) on Get-Content which just reads the content in as one big string instead of a line by line array. This is helpful otherwise you get an array of hashtables with a key value pair each instead of an single hashtable with all keys and values. It could still work for you without the -raw parameter. Just keep in mind if you try to index the resulting array of hashtables you could make some false assumptions as the comments will occupy “empty” indexes within the array. So in the example above index 0 and 4 would be empty and would not include the contents of “URL” and “FILE” as you might expect.
It goes to show that you should always be looking at the various cmdlets, new and old, that come with PowerShell. You may find something that you can use to your advantage that will save you some labor. Unfortunately the help for ConvertFrom-StringData does not provide a “Get-Content” example which seems like an obvious one to me. Most of the examples use here strings which seem much more contrived. Why would you put that data into a here string only to convert it to a hash table, why not just build a hash table to begin with? Maybe there is a common pattern out there I just haven’t run across yet.
Either way ConvertFrom-StringData has been a real productivity boost for me now that I understand a couple of its gotchas. I can now parse my office compatriots Linux data better, faster, and stronger then they can, ha!
Have you found an equally easy way to write back out to the properties file?
I ended up writing a function, but was still hopeful that there is a better way.
function Set-JavaPropertyFileValue($propFile, $propName, $propValue){
[string]$finalFile=””
if (test-path $propFile){
write-verbose “Found property file $propFile”
write-verbose “Read propfile”
$file = gc $propfile
foreach($line in $file){
if ((!($line.StartsWith(‘#’))) -and
(!($line.StartsWith(‘;’))) -and
(!($line.StartsWith(“;”))) -and
(!($line.StartsWith(‘`’))) -and
(($line.Contains(‘=’)))){
write-verbose “Searching for: $propName”
$property=$line.split(‘=’)[0]
write-verbose “Looking: $property”
#split line, left side if propName right side is value
if ($propName -eq $property){
write-verbose “found property name”
$line=”$propName=$propValue”
}
}
$finalFile+=”$line`n”
}
$finalFile | out-file “$propFile” -encoding “ASCII”
}else
{
write-error “Java Property file: $propFile not found”
}
}
I haven’t specifically build a corollary to what I detail in the post. But it looks like your onto the right path.
The one thing that I have done similarly before was use a Here string “template” that I filled variables with and then output. So it went something like:
$Path = “D:\Temp”
$FrgdColor = “Green”
$BkgdColor = “Black”
$ConfTemplate=@”
# Some Random conf file somewhere
Home=C:\Users\Joel
Path=$($Path)
ForegroundColor=$($FrgdColor)
BackgroundColor=$($BkgdColor)
“@
$ConfTemplate | Out-File -Path ‘D:\Temp\New.conf’
The key piece being the double quoted here-string that will then expand in the variables creating a string blob with all the bits. This method may or may not work depending on the complexity and variability of your conf file. I’ve use this method a couple times. I usually just embed the here-string in a function and then parametrize it to get me the blob I wanted.
Good luck!