function Get-DFSServers {
<#
.SYNOPSIS
Возвращает имена серверов, чьи шары используются как цели в DFS-пространствах домена.
.PARAMETER DFSRootPath
Корневой UNC-путь DFS, например \\mydep.corporate.ru\
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$DFSRootPath
)
# Нормализация пути
$DFSRootPath = $DFSRootPath.TrimEnd('\')
if ($DFSRootPath -match '^\\\\') {
$DFSRootPath = $DFSRootPath.Substring(2)
}
$domain = ($DFSRootPath -split '\\')[0]
$domainParts = $domain -split '\.'
$dn = ($domainParts | ForEach-Object { "DC=$_" }) -join ','
$dfsConfigDN = "CN=Dfs-Configuration,CN=System,$dn"
Write-Verbose "LDAP://$dfsConfigDN"
try {
$root = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$dfsConfigDN")
$searcher = New-Object System.DirectoryServices.DirectorySearcher($root)
$searcher.Filter = "(|(objectClass=msDFS-Namespacev2)(objectClass=msDFS-Linkv2))"
$searcher.PageSize = 1000
$searcher.SearchScope = [System.DirectoryServices.SearchScope]::Subtree
[void]$searcher.PropertiesToLoad.Add("msDFS-TargetListv2")
[void]$searcher.PropertiesToLoad.Add("name")
[void]$searcher.PropertiesToLoad.Add("distinguishedName")
}
catch {
Write-Error "Не удалось подключиться к AD по пути LDAP://$dfsConfigDN : $_"
return
}
# Регулярка для UNC-пути: \\server\share
$uncRegex = [regex]'\\\\([^\\/<>"\s]+)\\[^\\/<>"\s]+'
$servers = New-Object System.Collections.Generic.HashSet[string]
foreach ($result in $searcher.FindAll()) {
$prop = $result.Properties["msdfs-targetlistv2"]
if (-not $prop -or $prop.Count -eq 0) { continue }
$raw = $prop[0]
if ($null -eq $raw) { continue }
# Собираем возможные строковые представления
$candidates = New-Object System.Collections.Generic.List[string]
if ($raw -is [byte[]]) {
try { $candidates.Add([System.Text.Encoding]::Unicode.GetString($raw)) } catch {}
try { $candidates.Add([System.Text.Encoding]::UTF8.GetString($raw)) } catch {}
try { $candidates.Add([System.Text.Encoding]::ASCII.GetString($raw)) } catch {}
}
else {
$candidates.Add([string]$raw)
}
$found = $false
foreach ($cand in $candidates) {
# Убираем нулевые символы и BOM
$clean = $cand -replace "`0", ''
$clean = $clean.Trim([char]0xFEFF, ' ', "`r", "`n", "`t")
if (-not $clean) { continue }
$m = $uncRegex.Matches($clean)
if ($m.Count -gt 0) {
foreach ($match in $m) {
[void]$servers.Add($match.Groups[1].Value)
}
$found = $true
break
}
}
if (-not $found) {
$objName = $result.Properties['name'] | Select-Object -First 1
Write-Verbose ("Не удалось выделить UNC-пути из объекта '{0}' ({1})" -f `
$objName, $result.Properties['distinguishedName'][0])
}
}
# Возвращаем отсортированный массив
return ($servers | Sort-Object)
}