Private/Get-EscDirectoryContext.ps1
|
function Get-EscConfigNamingContext { <# .SYNOPSIS Returns the Configuration naming context DN from RootDSE (read-only). .DESCRIPTION Binds to LDAP://<Server>/RootDSE and reads configurationNamingContext. Returns $null on failure (never throws). .PARAMETER Server Optional domain controller / server name. Default: current domain. .OUTPUTS System.String (config NC DN) or $null. #> [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory = $false)] [string] $Server ) $path = 'LDAP://RootDSE' if (-not [string]::IsNullOrWhiteSpace($Server)) { $path = 'LDAP://{0}/RootDSE' -f $Server } $root = $null try { $root = New-Object System.DirectoryServices.DirectoryEntry($path) $configNc = [string] $root.Properties['configurationNamingContext'].Value if ([string]::IsNullOrWhiteSpace($configNc)) { return $null } return $configNc } catch { Write-EscLog -Component 'Directory' -Level Warning -Message ("Failed to read RootDSE: {0}" -f $_.Exception.Message) return $null } finally { if ($null -ne $root) { try { $root.Dispose() } catch { } } } } function Get-EscDefaultNamingContext { <# .SYNOPSIS Returns the Default (domain) naming context DN from RootDSE (read-only). .DESCRIPTION Binds to LDAP://<Server>/RootDSE and reads defaultNamingContext. Returns $null on failure (never throws). .PARAMETER Server Optional server name. Default: current domain. .OUTPUTS System.String or $null. #> [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory = $false)] [string] $Server ) $path = 'LDAP://RootDSE' if (-not [string]::IsNullOrWhiteSpace($Server)) { $path = 'LDAP://{0}/RootDSE' -f $Server } $root = $null try { $root = New-Object System.DirectoryServices.DirectoryEntry($path) $dnc = [string] $root.Properties['defaultNamingContext'].Value if ([string]::IsNullOrWhiteSpace($dnc)) { return $null } return $dnc } catch { Write-EscLog -Component 'Directory' -Level Warning -Message ("Failed to read RootDSE defaultNamingContext: {0}" -f $_.Exception.Message) return $null } finally { if ($null -ne $root) { try { $root.Dispose() } catch { } } } } function Invoke-EscLdapSearch { <# .SYNOPSIS Runs a read-only LDAP subtree search and returns SearchResult objects. .DESCRIPTION Thin, safe wrapper around System.DirectoryServices.DirectorySearcher. Read-only (search only). Returns an empty array on any failure. .PARAMETER SearchRoot Distinguished name of the container to search under. .PARAMETER Filter LDAP filter (default '(objectClass=*)'). .PARAMETER Server Optional server / DC to bind to. .PARAMETER PropertiesToLoad Optional list of attributes to load. Empty = all. .PARAMETER SearchScope 'Base', 'OneLevel', or 'Subtree' (default 'Subtree'). .OUTPUTS System.DirectoryServices.SearchResult[] (possibly empty). #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string] $SearchRoot, [Parameter(Mandatory = $false)] [string] $Filter = '(objectClass=*)', [Parameter(Mandatory = $false)] [string] $Server, [Parameter(Mandatory = $false)] [string[]] $PropertiesToLoad = @(), [Parameter(Mandatory = $false)] [ValidateSet('Base', 'OneLevel', 'Subtree')] [string] $SearchScope = 'Subtree' ) $prefix = 'LDAP://' if (-not [string]::IsNullOrWhiteSpace($Server)) { $prefix = 'LDAP://{0}/' -f $Server } $path = '{0}{1}' -f $prefix, $SearchRoot $entry = $null $searcher = $null try { $entry = New-Object System.DirectoryServices.DirectoryEntry($path) $searcher = New-Object System.DirectoryServices.DirectorySearcher($entry) $searcher.Filter = $Filter $searcher.SearchScope = [System.DirectoryServices.SearchScope]::$SearchScope $searcher.PageSize = 1000 try { $searcher.SecurityMasks = [System.DirectoryServices.SecurityMasks]::Dacl -bor ` [System.DirectoryServices.SecurityMasks]::Owner -bor ` [System.DirectoryServices.SecurityMasks]::Group } catch { } foreach ($p in $PropertiesToLoad) { if (-not [string]::IsNullOrWhiteSpace($p)) { [void]$searcher.PropertiesToLoad.Add($p) } } $found = $searcher.FindAll() $list = @() foreach ($r in $found) { $list += $r } return @($list) } catch { Write-EscLog -Component 'Directory' -Level Warning -Message ("LDAP search failed under '{0}': {1}" -f $SearchRoot, $_.Exception.Message) return @() } finally { if ($null -ne $searcher) { try { $searcher.Dispose() } catch { } } if ($null -ne $entry) { try { $entry.Dispose() } catch { } } } } |