Created
September 30, 2025 16:25
-
-
Save okpedro/ac0bcee4339f41127a779ce871151646 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| [CmdletBinding()] | |
| param( | |
| [string]$RootNamespace = "root", | |
| [string[]]$PathSegments = @("Microsoft", "SqlServer", "ReportServer"), | |
| [switch]$AsJson | |
| ) | |
| Set-StrictMode -Version Latest | |
| function Get-NamespaceChildren { | |
| [CmdletBinding()] | |
| param( | |
| [Parameter(Mandatory)] | |
| [string]$Namespace | |
| ) | |
| try { | |
| $children = Get-CimInstance -Namespace $Namespace -ClassName __NAMESPACE -ErrorAction SilentlyContinue | | |
| Select-Object -ExpandProperty Name -ErrorAction SilentlyContinue | |
| if ($null -eq $children) { | |
| return @() | |
| } | |
| return $children | |
| } | |
| catch { | |
| return @() | |
| } | |
| } | |
| function Resolve-NamespacePath { | |
| [CmdletBinding()] | |
| param( | |
| [Parameter(Mandatory)] | |
| [string]$BaseNamespace, | |
| [Parameter(Mandatory)] | |
| [string[]]$Segments | |
| ) | |
| $current = $BaseNamespace | |
| $traversed = @($current) | |
| foreach ($segment in $Segments) { | |
| $children = Get-NamespaceChildren -Namespace $current | |
| if ($null -ne $children -and $children -contains $segment) { | |
| $current = "$current\$segment" | |
| $traversed += $current | |
| } | |
| else { | |
| $parent = if ($traversed.Count -gt 0) { $traversed[-1] } else { $BaseNamespace } | |
| return [pscustomobject]@{ | |
| Exists = $false | |
| DeepestNamespace = $parent | |
| Traversed = $traversed | |
| MissingSegment = $segment | |
| } | |
| } | |
| } | |
| return [pscustomobject]@{ | |
| Exists = $true | |
| DeepestNamespace = $current | |
| Traversed = $traversed | |
| MissingSegment = $null | |
| } | |
| } | |
| function Get-DeepestBranch { | |
| [CmdletBinding()] | |
| param( | |
| [Parameter(Mandatory)] | |
| [string]$Namespace, | |
| [int]$Depth = 0 | |
| ) | |
| $children = Get-NamespaceChildren -Namespace $Namespace | |
| $childCount = if ($null -eq $children) { 0 } else { @($children).Count } | |
| if ($childCount -eq 0) { | |
| return [pscustomobject]@{ | |
| Namespace = $Namespace | |
| Depth = $Depth | |
| } | |
| } | |
| $best = $null | |
| foreach ($child in $children) { | |
| $childNamespace = "$Namespace\$child" | |
| $candidate = Get-DeepestBranch -Namespace $childNamespace -Depth ($Depth + 1) | |
| if (-not $best -or $candidate.Depth -ge $best.Depth) { | |
| $best = $candidate | |
| } | |
| } | |
| return $best | |
| } | |
| $baseResolution = Resolve-NamespacePath -BaseNamespace $RootNamespace -Segments $PathSegments | |
| Write-Host "Traversed namespaces:" | |
| foreach ($ns in $baseResolution.Traversed) { | |
| Write-Host " $ns" | |
| } | |
| if (-not $baseResolution.Exists) { | |
| $parent = if ($baseResolution.Traversed.Count -gt 1) { $baseResolution.Traversed[-2] } else { $RootNamespace } | |
| Write-Warning ("Namespace segment '{0}' was not found under '{1}'. Deepest existing namespace: {2}" -f ` | |
| $baseResolution.MissingSegment, $parent, $baseResolution.DeepestNamespace) | |
| if ($AsJson) { | |
| [pscustomobject]@{ | |
| PathResolved = $false | |
| DeepestExisting = $baseResolution.DeepestNamespace | |
| Traversed = $baseResolution.Traversed | |
| MissingSegment = $baseResolution.MissingSegment | |
| Children = @() | |
| } | ConvertTo-Json -Depth 5 | |
| } | |
| return | |
| } | |
| $children = Get-NamespaceChildren -Namespace $baseResolution.DeepestNamespace | |
| $childCount = if ($null -eq $children) { 0 } else { @($children).Count } | |
| if ($childCount -eq 0) { | |
| Write-Host ("No child namespaces found under '{0}'." -f $baseResolution.DeepestNamespace) | |
| if ($AsJson) { | |
| [pscustomobject]@{ | |
| PathResolved = $true | |
| DeepestExisting = $baseResolution.DeepestNamespace | |
| Traversed = $baseResolution.Traversed | |
| Children = @() | |
| } | ConvertTo-Json -Depth 5 | |
| } | |
| return | |
| } | |
| $reports = foreach ($child in $children) { | |
| $childNamespace = "$($baseResolution.DeepestNamespace)\$child" | |
| $deepestBranch = Get-DeepestBranch -Namespace $childNamespace | |
| [pscustomobject]@{ | |
| TopLevelChild = $childNamespace | |
| DeepestNamespace = $deepestBranch.Namespace | |
| LevelsBelowTop = $deepestBranch.Depth | |
| } | |
| } | |
| Write-Host "" | |
| Write-Host ("Deepest branches under '{0}':" -f $baseResolution.DeepestNamespace) | |
| $reports | Sort-Object LevelsBelowTop -Descending | | |
| Format-Table TopLevelChild, DeepestNamespace, LevelsBelowTop | |
| if ($AsJson) { | |
| [pscustomobject]@{ | |
| PathResolved = $true | |
| DeepestExisting = $baseResolution.DeepestNamespace | |
| Traversed = $baseResolution.Traversed | |
| Children = $reports | |
| } | ConvertTo-Json -Depth 5 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment