В проекте PSCX есть замечательная функция Show-Tree , которая послужит основой в решении задачи.
function Show-ADTreeOU { [CmdletBinding()] param( [Parameter(Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [ValidateNotNullOrEmpty()] [alias("DistinguishedName")] [string] $Path = (Get-ADDomain).DistinguishedName, [ValidateRange(0, 256)] [int] $Depth = [int]::MaxValue, [Parameter()] [ValidateRange(1, 100)] [int] $IndentSize = 3, [Parameter()] [ValidateRange(0, 2147483647)] [int] $Width, [Parameter()] [switch] $ShowLeafObject, [Parameter()] [switch] $UseAsciiLineArt ) Begin { Set-StrictMode -Version Latest if ($Width -eq 0) { $Width = $host.UI.RawUI.BufferSize.Width } $asciiChars = @{ EndCap = '\' Junction = '|' HorizontalBar = '-' VerticalBar = '|' } $cp437Chars = @{ EndCap = '└' Junction = '├' HorizontalBar = '─' VerticalBar = '│' } if (($Host.CurrentCulture.TextInfo.OEMCodePage -eq 437) -and !$UseAsciiLineArt) { $lineChars = $cp437Chars } else { $lineChars = $asciiChars } function GetIndentString([bool[]]$IsLast) { $str = '' for ($i=0; $i -lt $IsLast.Count - 1; $i++) { $str += if ($IsLast[$i]) {' '} else {$lineChars.VerticalBar} $str += " " * ($IndentSize - 1) } $str += if ($IsLast[-1]) {$lineChars.EndCap} else {$lineChars.Junction} $str += $lineChars.HorizontalBar * ($IndentSize - 1) $str } function CompactString([string]$String, [int]$MaxWidth = $Width) { $updatedString = $String if ($String.Length -ge $MaxWidth) { $ellipsis = '...' $updatedString = $String.Substring(0, $MaxWidth - $ellipsis.Length - 1) + $ellipsis } $updatedString } function ShowItemText([string]$ItemPath, [string]$ItemName, [bool[]]$IsLast) { if ($IsLast.Count -eq 0) { $String = CompactString $ItemPath } else { $String = CompactString "$(GetIndentString $IsLast)$ItemName " } if($ShowLeafObject) { if($ItemPath) { $Users = $Script:ADO[$ItemPath].Where({$_.ObjectClass -eq "user"}).Count $Computers = $Script:ADO[$ItemPath].Where({$_.ObjectClass -eq "computer"}).Count $GR = $Script:ADO[$ItemPath].Where({$_.ObjectClass -eq "group"}) $DL_GR_SEC = $GR.Where({$_.GroupScope -eq "DomainLocal" -and $_.GroupCategory -eq "Security"}).Count $GL_GR_SEC = $GR.Where({$_.GroupScope -eq "Global" -and $_.GroupCategory -eq "Security"}).Count $UN_GR_SEC = $GR.Where({$_.GroupScope -eq "Universal" -and $_.GroupCategory -eq "Security"}).Count $DL_GR_DIS = $GR.Where({$_.GroupScope -eq "DomainLocal" -and $_.GroupCategory -eq "Distribution"}).Count $GL_GR_DIS = $GR.Where({$_.GroupScope -eq "Global" -and $_.GroupCategory -eq "Distribution"}).Count $UN_GR_DIS = $GR.Where({$_.GroupScope -eq "Universal" -and $_.GroupCategory -eq "Distribution"}).Count [PSCustomObject]@{ Name = $String Users = $Users Computers = $Computers DL_GR_SEC = $DL_GR_SEC GL_GR_SEC = $GL_GR_SEC UN_GR_SEC = $UN_GR_SEC DL_GR_DIS = $DL_GR_DIS GL_GR_DIS = $GL_GR_DIS UN_GR_DIS = $UN_GR_DIS } } } else { $String } } function ShowItem([string]$ItemPath, [string]$ItemName='', [bool[]]$IsLast=@()) { # Show current item ShowItemText $ItemPath $ItemName $IsLast # grab its children. This let's us know if there $childItems = @() if ($IsLast.Count -lt $Depth) { $childItems = @(Get-ADOrganizationalUnit -Filter * -SearchBase $ItemPath -SearchScope OneLevel | Select DistinguishedName, Name) } # Track parent's "last item" status to determine which level gets a vertical bar $IsLast += @($false) # Recurse through child items for ($i=0; $i -lt $childItems.Count; $i++) { $childItemPath = $childItems[$i].DistinguishedName $childItemName = $childItems[$i].Name $IsLast[-1] = ($i -eq $childItems.Count - 1) ShowItem $childItemPath $childItemName $IsLast } } } Process { if($ShowLeafObject) { $ADObjects = @() $ADObjects += Get-ADObject -Filter "ObjectClass -eq 'user' -or ObjectClass -eq 'computers'" -SearchBase $Path $ADObjects += Get-ADGroup -Filter * -SearchBase $Path if($ADObjects) { $Script:ADO = @{} $ADO[$Path] = $ADObjects $ADObjects | Group-Object {$_.DistinguishedName.Split(",",2)[1]} | Foreach-Object { if($_.Name.StartsWith("OU=")) { $ADO[$_.Name] = $_.Group } } } } if($Path) { ShowItem $Path } } }
Файл: show-adtreeou-ps1.doc