bin/Public/Get-sqmServersFromOU.ps1
|
<# .SYNOPSIS Ermittelt alle Computer-Objekte aus einer bestimmten AD-OU und gibt sie als pipefaehige Objekte aus. .DESCRIPTION Durchsucht Active Directory (via ADSI, kein ActiveDirectory-Modul erforderlich) nach allen Computer-Objekten unterhalb einer OU mit dem angegebenen Namen. Die Ausgabe-Objekte enthalten eine SqlInstance-Eigenschaft und koennen direkt an beliebige sqmSQLTool-Funktionen weitergeleitet werden: Get-sqmServersFromOU | ForEach-Object { Sync-sqmBackupExcludeTable -SqlInstance $_.SqlInstance } .PARAMETER OUName Name der OU (nicht der vollstaendige LDAP-Pfad). Beispiel: 'srvDatabase' Standard: 'srvDatabase' .PARAMETER Domain FQDN der Domain. Standard: aktuelle Domain des ausfuehrenden Benutzers. .PARAMETER SearchBase Expliziter LDAP-Suchpfad (DistinguishedName der OU). Wenn angegeben, wird OUName ignoriert. Beispiel: 'OU=srvDatabase,OU=Server,DC=contoso,DC=com' .PARAMETER Recurse Sucht auch in untergeordneten OUs (Standard: $true). .PARAMETER EnableException Loest bei Fehlern sofort eine Exception aus. .OUTPUTS PSCustomObject mit: Name, FQDN, SqlInstance, OU, Domain, OperatingSystem .EXAMPLE # Alle SQL-Server ausgeben Get-sqmServersFromOU .EXAMPLE # Andere OU Get-sqmServersFromOU -OUName 'srvApp' .EXAMPLE # Expliziter Domain-Name Get-sqmServersFromOU -OUName 'srvDatabase' -Domain 'contoso.com' .EXAMPLE # Direkt an sqmSQLTool-Funktion weiterleiten Get-sqmServersFromOU | ForEach-Object { Sync-sqmBackupExcludeTable -SqlInstance $_.SqlInstance } .EXAMPLE # Backup-Exclude-Trigger auf allen DB-Servern registrieren Get-sqmServersFromOU | ForEach-Object { Register-sqmBackupExcludeTrigger -SqlInstance $_.SqlInstance } .NOTES Benoetigt keine ActiveDirectory-Modulinstallation. Benoetigt Lesezugriff auf Active Directory. #> function Get-sqmServersFromOU { [CmdletBinding()] [OutputType([PSCustomObject])] param ( [Parameter(Mandatory = $false, Position = 0)] [string]$OUName = 'srvDatabase', [Parameter(Mandatory = $false)] [string]$Domain, [Parameter(Mandatory = $false)] [string]$SearchBase, [Parameter(Mandatory = $false)] [bool]$Recurse = $true, [Parameter(Mandatory = $false)] [switch]$EnableException ) $functionName = $MyInvocation.MyCommand.Name try { # ── Domain ermitteln ───────────────────────────────────────────── if ([string]::IsNullOrWhiteSpace($Domain)) { $Domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().Name } $domainDN = 'DC=' + ($Domain -split '\.' -join ',DC=') Invoke-sqmLogging -Message "[$functionName] Domain: $Domain | DN: $domainDN" -FunctionName $functionName -Level 'INFO' # ── SearchBase ermitteln ───────────────────────────────────────── if ([string]::IsNullOrWhiteSpace($SearchBase)) { # OU per Name suchen $ouSearcher = [System.DirectoryServices.DirectorySearcher]::new( [System.DirectoryServices.DirectoryEntry]::new("LDAP://$domainDN") ) $ouSearcher.Filter = "(&(objectClass=organizationalUnit)(ou=$OUName))" $ouSearcher.SearchScope = [System.DirectoryServices.SearchScope]::Subtree $ouSearcher.PropertiesToLoad.AddRange([string[]]@('distinguishedName', 'ou')) $ouResult = $ouSearcher.FindOne() if (-not $ouResult) { $errMsg = "OU '$OUName' wurde in Domain '$Domain' nicht gefunden." Invoke-sqmLogging -Message "[$functionName] $errMsg" -FunctionName $functionName -Level 'ERROR' if ($EnableException) { throw $errMsg } Write-Error $errMsg return } $SearchBase = $ouResult.Properties['distinguishedname'][0] Invoke-sqmLogging -Message "[$functionName] OU gefunden: $SearchBase" -FunctionName $functionName -Level 'INFO' } Write-Host "Suche Computer in OU: $SearchBase" -ForegroundColor Cyan # ── Computer-Objekte laden ─────────────────────────────────────── $scope = if ($Recurse) { [System.DirectoryServices.SearchScope]::Subtree } else { [System.DirectoryServices.SearchScope]::OneLevel } $compSearcher = [System.DirectoryServices.DirectorySearcher]::new( [System.DirectoryServices.DirectoryEntry]::new("LDAP://$SearchBase") ) $compSearcher.Filter = '(objectClass=computer)' $compSearcher.SearchScope = $scope $compSearcher.PageSize = 1000 $compSearcher.PropertiesToLoad.AddRange([string[]]@( 'name', 'dnshostname', 'distinguishedname', 'operatingsystem', 'description' )) $results = $compSearcher.FindAll() if ($results.Count -eq 0) { Write-Warning "Keine Computer in OU '$SearchBase' gefunden." return } Write-Host "$($results.Count) Server gefunden:" -ForegroundColor Green $servers = [System.Collections.Generic.List[PSCustomObject]]::new() foreach ($r in $results) { $name = $r.Properties['name'][0] $fqdn = if ($r.Properties['dnshostname'].Count -gt 0) { $r.Properties['dnshostname'][0] } else { "$name.$Domain" } # OU aus DistinguishedName extrahieren (erster OU=-Teil) $dn = $r.Properties['distinguishedname'][0] $ouPart = ($dn -split ',' | Where-Object { $_ -match '^OU=' } | Select-Object -First 1) -replace '^OU=', '' $os = if ($r.Properties['operatingsystem'].Count -gt 0) { $r.Properties['operatingsystem'][0] } else { '' } $desc = if ($r.Properties['description'].Count -gt 0) { $r.Properties['description'][0] } else { '' } $obj = [PSCustomObject]@{ Name = $name FQDN = $fqdn SqlInstance = $fqdn # direkt an -SqlInstance verwendbar OU = $ouPart Domain = $Domain OperatingSystem = $os Description = $desc } Write-Host " - $name [$os]" -ForegroundColor White $servers.Add($obj) } Write-Host "" Invoke-sqmLogging -Message "[$functionName] $($servers.Count) Server aus OU '$OUName' ermittelt." -FunctionName $functionName -Level 'INFO' return $servers.ToArray() } catch { $errMsg = "Fehler in $functionName`: $($_.Exception.Message)" Invoke-sqmLogging -Message $errMsg -FunctionName $functionName -Level 'ERROR' if ($EnableException) { throw } Write-Error $errMsg } finally { if ($results) { $results.Dispose() } } } |