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


# ============================================================
# Скрипт для поиска файлов на серверах, участвующих в DFS
# ============================================================
$DFSroot = "\\mydep.corporate.ru\"

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName System.DirectoryServices

# ---------- Получение серверов DFS через Active Directory ----------
function Get-DFSServersFromAD {
    param([string]$RootPath)
    try {
        # Разбираем корень DFS: \\mydep.corporate.ru\
        $rootTrim = $RootPath.TrimEnd('\')
        if ($rootTrim.StartsWith('\\')) { $rootTrim = $rootTrim.Substring(2) }
        $parts = $rootTrim.Split('\')
        $nsFull = $parts[0]                     # mydep.corporate.ru
        if ($nsFull -match '^([^.]+)\.(.+)$') {
            $nsName = $Matches[1]               # mydep
            $domain = $Matches[2]               # corporate.ru
        } else {
            $nsName = $nsFull
            $domain = $env:USERDNSDOMAIN
        }
        $domainDN = ($domain.Split('.') | ForEach-Object { "DC=$_" }) -join ','
        $searchBase = "CN=Dfs-Configuration,CN=System,$domainDN"

        # 1. Находим объект пространства имён (msDFS-Namespacev2) по cn
        $nsSearcher = New-Object System.DirectoryServices.DirectorySearcher
        $nsSearcher.SearchRoot = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$searchBase")
        $nsSearcher.Filter = "(cn=$nsName)"
        $nsSearcher.PropertiesToLoad.Add("objectGUID") | Out-Null
        $nsResult = $nsSearcher.FindOne()
        if (-not $nsResult) { return @() }
        $nsGuid = $nsResult.Properties["objectguid"][0]

        # 2. Ищем все ссылки (msDFS-Linkv2) и фильтруем по GUID пространства имён
        $linkSearcher = New-Object System.DirectoryServices.DirectorySearcher
        $linkSearcher.SearchRoot = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$searchBase")
        $linkSearcher.Filter = "(objectClass=msDFS-Linkv2)"
        $linkSearcher.PropertiesToLoad.Add("msDFS-TargetListv2") | Out-Null
        $linkSearcher.PropertiesToLoad.Add("msDFS-NamespaceIdentityGUIDv2") | Out-Null
        $servers = @{}
        foreach ($link in $linkSearcher.FindAll()) {
            $linkGuid = $link.Properties["msdfs-namespaceidentityguidv2"][0]
            if ($linkGuid -ne $nsGuid) { continue }
            $targets = $link.Properties["msdfs-targetlistv2"]
            foreach ($target in $targets) {
                if ($target -match '^\\\\?([^\\]+)') {
                    $servers[$Matches[1]] = $true
                }
            }
        }
        return $servers.Keys
    }
    catch {
        [System.Windows.Forms.MessageBox]::Show("Ошибка при чтении DFS из AD:`n$($_.Exception.Message)", "Ошибка", 'OK', 'Error')
        return @()
    }
}

# ---------- Получение списка общих ресурсов на сервере ----------
function Get-ServerShares {
    param([string]$ServerName)
    $shares = @()
    try {
        $cim = New-CimSession -ComputerName $ServerName -ErrorAction Stop
        $shares = Get-SmbShare -CimSession $cim -ErrorAction Stop |
                  Where-Object { $_.Name -notmatch '\$$' } |
                  Select-Object -ExpandProperty Name
        Remove-CimSession -CimSession $cim -ErrorAction SilentlyContinue
    } catch { }
    return $shares
}

# ---------- Поиск файлов на всех серверах и шарах ----------
function Search-Files {
    param(
        [string[]]$Servers,
        [string]$Query,
        [System.Windows.Forms.ListView]$ListView
    )
    $ListView.Items.Clear()
    foreach ($server in $Servers) {
        $shares = Get-ServerShares -ServerName $server
        if (-not $shares) { continue }
        foreach ($share in $shares) {
            $unc = "\\$server\$share"
            try {
                Get-ChildItem -Path $unc -Recurse -Force -ErrorAction SilentlyContinue |
                Where-Object { -not $_.PSIsContainer -and $_.FullName -like "*$Query*" } |
                ForEach-Object {
                    $item = New-Object System.Windows.Forms.ListViewItem($server)
                    $item.SubItems.Add($share) | Out-Null
                    $item.SubItems.Add($_.FullName) | Out-Null
                    $item.SubItems.Add($_.Name) | Out-Null
                    $ListView.Items.Add($item) | Out-Null
                    $ListView.Refresh()
                }
            } catch { }
        }
    }
}

# ---------- Графический интерфейс ----------
$form = New-Object System.Windows.Forms.Form
$form.Text = "Поиск файлов в DFS"
$form.Size = New-Object System.Drawing.Size(900, 600)
$form.StartPosition = "CenterScreen"

$label = New-Object System.Windows.Forms.Label
$label.Text = "Введите имя файла, часть пути или маску:"
$label.Location = New-Object System.Drawing.Point(10, 15)
$label.Size = New-Object System.Drawing.Size(300, 20)
$form.Controls.Add($label)

$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Point(10, 40)
$textBox.Size = New-Object System.Drawing.Size(500, 25)
$form.Controls.Add($textBox)

$button = New-Object System.Windows.Forms.Button
$button.Text = "Найти"
$button.Location = New-Object System.Drawing.Point(520, 38)
$button.Size = New-Object System.Drawing.Size(100, 28)
$form.Controls.Add($button)

$listView = New-Object System.Windows.Forms.ListView
$listView.Location = New-Object System.Drawing.Point(10, 80)
$listView.Size = New-Object System.Drawing.Size(860, 470)
$listView.View = "Details"
$listView.FullRowSelect = $true
$listView.GridLines = $true
$listView.Columns.Add("Сервер", 150) | Out-Null
$listView.Columns.Add("Шара", 150) | Out-Null
$listView.Columns.Add("Полный путь", 400) | Out-Null
$listView.Columns.Add("Имя файла", 150) | Out-Null
$form.Controls.Add($listView)

$button.Add_Click({
    $query = $textBox.Text.Trim()
    if ([string]::IsNullOrEmpty($query)) {
        [System.Windows.Forms.MessageBox]::Show("Введите строку для поиска.", "Предупреждение", 'OK', 'Warning')
        return
    }
    $button.Enabled = $false
    $form.Cursor = [System.Windows.Forms.Cursors]::WaitCursor
    try {
        $servers = Get-DFSServersFromAD -RootPath $DFSroot
        if ($servers.Count -eq 0) {
            [System.Windows.Forms.MessageBox]::Show("Не найдено серверов в указанном DFS-корне.", "Информация", 'OK', 'Information')
            return
        }
        Search-Files -Servers $servers -Query $query -ListView $listView
    } finally {
        $button.Enabled = $true
        $form.Cursor = [System.Windows.Forms.Cursors]::Default
    }
})

[void]$form.ShowDialog()