Things don’t always go as planned. For example when my wife and I moved from Indiana to Arizona this spring. We were planning on taking three days to drive the dogs from Indianapolis to Phoenix. I was at the PowerShell Summit in Redmond and she was home finishing the packing. I could tell by the way she was sounding on the phone that things were not going well so I jumped on an early flight to come home. Well….I landed in Houston to find the plane was broken and no flights left to Indianapolis. The airline was planning on getting me home around 2:30 PM the next day. Um,…no. So I took a plane to Chicago that night and slept in the USO and got home at 10 AM to help my wife. Sometimes you have to turn a challenge into an opportunity.
Sometimes you need to work with data that was never indented to be used with PowerShell. This can present a challenge. Those of you who have taken my PowerShell classes know that I frown on any variable that has a space in it. Take a look at what you have to do to get a variable with a space in it to work.
PS C:\> ${My Variable} = "No a good way to do things"
${My Variable}
No a good way to do things
To get this to work, we have to encapsulate the variable name inside of curly brackets. This is not at all easy to read so I discourage it.
While working on a Group Policy issue, I needed a way to extract information from the Group Policy Settings Reference for Windows and Windows Server. This is an excel spread sheet. I took the Administrative Templates sheet and saved it as an CSV file. Once I did that, I could import in each record and use PowerShell to present GPO settings that fit my criteria. Well, let’s import this data in and take a look at the property names.
PS C:\> Import-Csv -LiteralPath "C:\Users\JASON\Documents\PowerShell\InDevelopment\GPO\AdminTemplates2012.csv" |
Get-Member -MemberType Properties |
Select-Object -Property Name
Name
----
Active Directory Schema or Domain Requirements
File Name
Help Text
Logoff Required
Policy Path
Policy Setting Name
Reboot Required
Registry Information
Scope
Status
Supported On
Wow, not good. We have a lot of property names with spaces in them. We have two choices here. We can either just use the property names as is or we can modify them.
Using them as is.
PS C:\> Import-Csv –LiteralPath "C:\AdminTemplates2012.csv" |
Where {"$PSItem.Policy Path" -like "*Windows Components\Remote Desktop Service*"}
In the Where-Object line, we used double quotes surrounding the entire call to the object and the Policy Path” property. Not as bad as using the curly brackets that we have to do for variables. This will work. For those of you who prefer to not uses spaces, we simple need to add some new properties to the object while getting ride of the old ones.
PS C:\> Import-Csv -LiteralPath "C:\AdminTemplates2012.csv" |
ForEach-Object -Process {
$Props = $PSItem | Get-Member -MemberType Properties | Select-Object -ExpandProperty Name
$Obj = New-Object -TypeName PSObject
ForEach ($P in $Props)
{
$Hash = @{NotePropertyName = $P.Replace(" ","")
NotePropertyValue = $PSItem.$P}
$Obj | Add-Member @Hash
}
Write-Output $Obj
}
Yes, I know, a bit much. Through this into a function and reuse it with other objects that suffer from spaces in the property names if you need to. Really what we are achieving is creating a whole new object from the object created by Import-CSV. This is one continuous command. We are using ForEach-Object to cycle through one object at a time for processing. The $Props variable stores the property names of each property in the object. We then create a new object to pass out into the pipeline. The NotePropertyName simply takes the name of the property being handled and removes all spaces from it. The NotePropertyValue is the value of the original property. Once all the properties have been renamed, the new object is sent to the pipeline so you can do what ever you need to do without the spaces.
Either way will work, you just need to choose which way you want to handle this “opportunity”.
Comments