Загрузка данных


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)
}