Tuesday, April 22, 2014

PowerShell Tips #2 - Working with Multi-Instance or Nested Properties

The objective here is to create reports of objects that contain properties with multiple instances, or nested properties.

Example is Get-DNSServer

Get-DNSServer by itself, with no parameters, produces a very detailed, multiple-heading report with a ton of detail.   The internal code to produce this report will be the subject of another technote.

For this exercise though, see the outout from the command

PS C:\ > Get-DnsServer |gm -MemberType Property

Name                       MemberType Definition
----                       ---------- ----------
PSComputerName             Property   string PSComputerName {get;}
ServerCache                Property   CimInstance#Instance ServerCache {get;set;}
ServerDiagnostics          Property   CimInstance#Instance ServerDiagnostics {get;set;}
ServerDsSetting            Property   CimInstance#Instance ServerDsSetting {get;set;}
ServerEdns                 Property   CimInstance#Instance ServerEdns {get;set;}
ServerForwarder            Property   CimInstance#Instance ServerForwarder {get;set;}
ServerGlobalNameZone       Property   CimInstance#Instance ServerGlobalNameZone {get;set;}
ServerGlobalQueryBlockList Property   CimInstance#Instance ServerGlobalQueryBlockList {get;set;}
ServerRecursion            Property   CimInstance#Instance ServerRecursion {get;set;}
ServerRootHint             Property   CimInstance#InstanceArray ServerRootHint {get;set;}
ServerScavenging           Property   CimInstance#Instance ServerScavenging {get;set;}
ServerSetting              Property   CimInstance#Instance ServerSetting {get;set;}
ServerZone                 Property   CimInstance#InstanceArray ServerZone {get;set;}
ServerZoneAging            Property   CimInstance#InstanceArray ServerZoneAging {get;set;}
ServerZoneScope            Property   CimInstance#InstanceArray ServerZoneScope {get;set;}


What I am interested in reporting is the IP Addresses of the Forwarders, which is contained in the "ServerForwarder" property.


So, we now type "(get-dnsserver).ServerForwarder" and get the following:

UseRootHint        : True
Timeout(s)         : 3
EnableReordering   : True
IPAddress          : {10.1.1.4, 10.2.1.20}
ReorderedIPAddress : {10.1.1.4, 10.2.1.20}


Now type:
PS C:\ > (get-dnsserver).ServerForwarder | GM

Name                      MemberType     Definition
----                      ----------     ----------
EnableReordering          Property       bool EnableReordering {get;set;}
PSComputerName            Property       string PSComputerName {get;}
Timeout                   Property       uint32 Timeout {get;set;}
UseRootHint               Property       bool UseRootHint {get;set;}
IPAddress                 ScriptProperty System.Net.IPAddress[] IPAddress {get=[OutputType([Syste...
ReorderedIPAddress        ScriptProperty System.Net.IPAddress[] ReorderedIPAddress {get=[Outpu...


Notice that a "Property" of the ServerForwarder property is not a Property at all, but rather a ScriptProperty.  It contains multiple values as a sudo-property. 

So lets keep going.   
PS C:\> ((get-dnsserver).ServerForwarder).IPAddress
 

Address            : 67174666
AddressFamily      : InterNetwork
ScopeId            :
IsIPv6Multicast    : False
IsIPv6LinkLocal    : False
IsIPv6SiteLocal    : False
IsIPv6Teredo       : False
IsIPv4MappedToIPv6 : False
IPAddressToString  : 10.1.1.4

Address            : 335610378
AddressFamily      : InterNetwork
ScopeId            :
IsIPv6Multicast    : False
IsIPv6LinkLocal    : False
IsIPv6SiteLocal    : False
IsIPv6Teredo       : False
IsIPv4MappedToIPv6 : False
IPAddressToString  : 10.2.1.20


So how do we query the DNS Server and spit out this magical list of IP Addresses?
Method 1) 
PS C:\ > (((get-dnsserver).ServerForwarder).IPAddress).IPAddressToString
10.1.1.4
10.2.1.20


Method 2)


PS C:\ > Get-DnsServer |%{$_.ServerForwarder | %{($_.IPAddress).IPAddressToString}}

10.1.1.4
10.2.1.20


End of Lesson.