Using Square Brackets in Powershell Queries

I don't really intend this blog to be a SCOM-only thing, but it happens to be pretty much all I'm working on right now. I have seen both of these tips in various places, but I thought I would put them together on one page for anyone else who might need them.

When you query class instances in the Operations Manager Shell, you often get property names for associated and parent classes as well. For example, try looking at a class instance of Microsoft.Windows.Computer:

$computerclass = Get-SCOMClass -Name Microsoft.Windows.Computer

(Get-SCOMClassInstance -Class $computerclass)[0] | select *

[Microsoft.Windows.Computer].PrincipalName                   : hostname.contoso.com
[Microsoft.Windows.Computer].DNSName                         : (null)
[Microsoft.Windows.Computer].NetbiosComputerName             : (null)
[Microsoft.Windows.Computer].NetbiosDomainName               : (null)
[Microsoft.Windows.Computer].IPAddress                       : (null)
[Microsoft.Windows.Computer].NetworkName                     : (null)
[Microsoft.Windows.Computer].ActiveDirectoryObjectSid        : (null)
[Microsoft.Windows.Computer].IsVirtualMachine                : (null)
[Microsoft.Windows.Computer].DomainDnsName                   : (null)
[Microsoft.Windows.Computer].OrganizationalUnit              : (null)
[Microsoft.Windows.Computer].ForestDnsName                   : (null)
[Microsoft.Windows.Computer].ActiveDirectorySite             : (null)
[Microsoft.Windows.Computer].LogicalProcessors               : (null)
[Microsoft.Windows.Computer].PhysicalProcessors              : (null)
[Microsoft.Windows.Computer].HostServerName                  : (null)
[Microsoft.Windows.Computer].VirtualMachineName              : (null)
[Microsoft.Windows.Computer].OffsetInMinuteFromGreenwichTime : (null)
[Microsoft.Windows.Computer].LastInventoryDate               : (null)
[Microsoft.Windows.Server.Computer].IsVirtualNode            : (null)
[System.ConfigItem].ObjectStatus                             : System.ConfigItem.ObjectStatusEnum.Active
[System.ConfigItem].AssetStatus                              : (null)
[System.ConfigItem].Notes                                    : (null)
[System.Entity].DisplayName                                  : hostname.contoso.com
IsManaged                                                    : True
HealthState                                                  : Uninitialized
...

And so on.

So if you want to select just the PrincipalName, you might try a simple Select-Object like:

(Get-SCOMClassInstance -Class $computerclass)[0] | Select-Object PrincipalName

PrincipalName
-------------

So, nothing there. Maybe we try the whole property name:

(Get-SCOMClassInstance -Class $computerclass)[0] | select [Microsoft.Windows.Computer].PrincipalName

[Microsoft.Windows.Computer].PrincipalName
------------------------------------------

Nope, that doesn't work, either. You have to escape the square brackets with backticks for this kind of usage, and in fact for this usage you have to double-escape one of the brackets, because of reasons. So you wind up with:

(Get-SCOMClassInstance -Class $computerclass)[0] | select ``[Microsoft.Windows.Computer`].PrincipalName

[Microsoft.Windows.Computer].PrincipalName
------------------------------------------
hostname.contoso.com

Hey, there it is!

On the other hand, sometimes you want to use these property names in a query, such as:

Get-SCOMClassInstance -Class $computerclass | where { $_.PrincipalName -match "hostname.contoso.com" }

No results.

Get-SCOMClassInstance -Class $computerclass | where { $_.[Microsoft.Windows.Computer].PrincipalName -match "hostname.contoso.com" }
Unable to find type [Microsoft.Windows.Computer]. Make sure that the assembly that contains this type is loaded.
At line:1 char:55
+ Get-SCOMClassInstance -Class $computerclass | where { $_.[Microsoft.Windows.Comp ...
+                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (Microsoft.Windows.Computer:TypeName) [], RuntimeException
    + FullyQualifiedErrorId : TypeNotFound

Yikes, that's really not it.

Get-SCOMClassInstance -Class $computerclass | where { $_.``[Microsoft.Windows.Computer`].PrincipalName -match "hostname.contoso.com" }
At line:1 char:58
+ Get-SCOMClassInstance -Class $computerclass | where { $_.``[Microsoft.Windows.Co ...
+                                                          ~
Missing property name after reference operator.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : MissingPropertyName

Ok, so in this case you don't need to backtick-escape these brackets. What you do need is to put single quotes around that entire property name:

Get-SCOMClassInstance -Class $computerclass | where { $_.'[Microsoft.Windows.Computer].PrincipalName' -match "hostname.contoso.com" }

HealthState     InMaintenanceMode  DisplayName
-----------     -----------------  -----------
Uninitialized         False        hostname.contoso.com

I hope this is helpful to someone out there. I tend to always forget which of these approaches I have to use in which situation, so having them in one place will probably help me, at least!

comments powered by Disqus