Filtering Based on Hash Table Contents

I have a bunch of Custom Properties in Virtual Machine Manager (VMM). I am trying to filter based on those values (which are stored as a hashtable) and am struggling figuring out how to do this. I want to be able to run a command that does something like this:

Get-SCVirtualMachine -VMMServer Blah -All | Select-Object Name | Where MyCustomProperty -ne “”

Here is what I have figured out so far:

$props = Get-SCVirtualMachine -VMMServer Blah -Name Comp | Select CustomProperty

$props
CustomProperty

{Application Owner, Update Time, Last Updated, Infrastructure Owner…

$props | gm
TypeName: Selected.Microsoft.SystemCenter.VirtualMachineManager.VM

Name MemberType Definition


Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
CustomProperty NoteProperty System.Collections.Hashtable CustomProperty=System.Collections.Hashtable

$props.CustomProperty
Name Value


Application Owner Someone
Update Time 1:00 AM
Last Updated 03/28/2013
Infrastructure Owner Jacob Benson
Day To Be Updated 3rd Saturday - DEV

$props.CustomProperty.‘Application Owner’ -ne “”
True

However, I have no idea how to work this into a Where-Object (if that’s what I even want to do) to Filter based on the contents of a value in the hash table.

If I export all of the VMM properties to Excel, all it shows me is that the values for CustomProperty are part of a hash table, it doesn’t display any of the values.

I answered my own question, but now I have another question.

This is the command that I run to get my list (as an example).

Get-SCVirtualMachine -VMMServer Blah -All | Select Name | Where-Object {$_.CustomProperty.‘ApplicationOwner’ -ne “”}

However, now the question is how do I select the objects in the hash table like this (this obviously doesn’t work):

Get-SCVirtualMachine -VMMServer Blah -All | Select Name,CustomProperty.‘Application Owner’ | Where-Object {$_.CustomProperty.‘ApplicationOwner’ -ne “”}

This is closer, but just gives me the hash table, not the values inside:

Get-SCVirtualMachine -VMMServer Blah -All | Select-Object Name,CustomProperty | Where-Object {$_.CustomProperty.‘ApplicationOwner’ -ne “”}

So you’re trying to basically unwrap the CustomProperty hashtable and produce an object which has those properties? For that, I’d probably try this:

Get-SCVirtualMachine -VMMServer Blah -All |
ForEach-Object {
    $obj = $_
    New-Object psobject -Property $obj.CustomProperty |
    Add-Member -NotePropertyName 'Name' -NotePropertyValue $obj.Name -Passthru
} |
Where-Object { $_.'Application Owner' -ne '' }

Here I just used the hashtable to pass to New-Object, which is a lazy but convenient way of getting the job done, if you want the property names to match what’s already in $_.CustomProperty. If you wanted to do some transformation on those names (such as changing “Application Owner” with a space to just ApplicationOwner), you’d have to hard-code the possible from / to values.

Edit: Note that the -NotePropertyName and -NotePropertyValue parameters to Add-Member were added in PowerShell 3.0. For 2.0 compatibility, you’d use -MemberType NoteProperty -Name ‘Name’ -Value $obj.Name

That will work. Thanks Dave!

I spoke too soon. All that ends up giving me is a column with one of the Custom Properties (Last Updated) and the Name of the VM. How/Where do I add the select-object so that I can get the Name,CustomProperty1,CustomProperty2, etc etc. Right now it’s giving the last of the 4 Custom Properties in the hash table.

PS. I had no idea this would be this complicated.

Hmm… I’ll need to know more about the objects that are in play here. It doesn’t seem like that CustomProperty field is really a HashTable, based on what you’ve said. Try this, and paste the output here:

Get-SCVirtualMachine -VMMServer Blah -All |
Select-Object -First 1 |
ForEach-Object {
    Get-Member -InputObject $_ | Out-Host
    Get-Member -InputObject $_.CustomProperty | Out-Host
}

Turns out I was making this much more complicated than I needed it to. I was confused because Intellisense wasn’t giving me what I thought should be there. Turns out I just need to run the command like this.

Get-SCVirtualMachine -VMMServer Blah -All | Where-Object {$.CustomProperty.‘ApplicationOwner’ -ne “”} | Select-Object Name,{$.CustomProperty.‘Application Owner’},{$_.CustomProperty.‘Last Updated’}