I had a need to recursively iterate my Central Management Server, yet always return the topmost GroupName. The function takes an array of strings to return that correlate to the names of the first level groups. Use at your own risk.
#requires -Module SqlPS #requires -Version 5 Import-Module SqlPS -DisableNameChecking function Get-CMSServers{ param( [string[]]$CMSGroup = @('Group1', 'Group2') #default groups... ) function Get-RegisteredServers{ param( $ServerGroup, $ParentGroup ) $ServerGroup.RegisteredServers | %{ $objects.Add([PSCustomObject]@{ ServerName = $_.ServerName GroupName = $ParentGroup GroupDescription = $_.Description ParentName = $ServerGroup.Name }) | Out-Null } if($ServerGroup.ServerGroups.Count -gt 0){ $ServerGroup.ServerGroups | %{ Get-RegisteredServers -ServerGroup $_ -ParentGroup $ParentGroup } } } $objects = New-Object System.Collections.ArrayList Set-Variable -Name objects -Option AllScope try{ $srvConn = New-Object Microsoft.SqlServer.Management.Common.ServerConnection "ServerName" $ServerStore = New-Object Microsoft.SqlServer.Management.RegisteredServers.RegisteredServersStore $srvConn $ServerStore.DatabaseEngineServerGroup.ServerGroups | where{$_.Name -in $CMSGroup} | %{ Get-RegisteredServers -ServerGroup $_ -ParentGroup $_.Name } return $objects; } catch{ $_ | fl -Force } finally{ $srvConn.Disconnect(); } } Get-CMSServers -CMSGroup @('Production', 'Reporting')