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


# Run in PowerShell as Administrator.
& {
    $ErrorActionPreference = 'Stop'
    $identity = [Security.Principal.WindowsIdentity]::GetCurrent()
    $principal = [Security.Principal.WindowsPrincipal]::new($identity)
    if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
        throw 'Open PowerShell as Administrator and run this code again.'
    }

    $backup = Join-Path $env:USERPROFILE ('rdp-backup-' + (Get-Date -Format 'yyyyMMdd-HHmmss-fff') + '.reg')
    & reg.exe export 'HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server' $backup /y
    if ($LASTEXITCODE -ne 0) { throw 'Registry backup failed; no changes made.' }

    $root = 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server'
    $listener = Join-Path $root 'WinStations\RDP-Tcp'
    $protocol = '{5828227c-20cf-4408-b73f-73ab70b8849f}'
    if (-not (Test-Path "Registry::HKEY_CLASSES_ROOT\CLSID\$protocol\InprocServer32")) {
        throw 'The Windows RDP protocol component is missing; repair Windows first.'
    }
    New-Item -Path $listener -Force | Out-Null
    New-ItemProperty -Path $root -Name fDenyTSConnections -PropertyType DWord -Value 0 -Force | Out-Null
    $policy = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services'
    if (Test-Path $policy) {
        $policyDeny = Get-ItemPropertyValue -Path $policy -Name fDenyTSConnections -ErrorAction SilentlyContinue
        if ($policyDeny -eq 1) {
            throw 'Group Policy prohibits RDP. Enable it in the governing policy, then rerun this code.'
        }
    }
    $values = @{
        PortNumber = 3389
        fEnableWinStation = 1
        LanAdapter = 0
        MinEncryptionLevel = 3
        WdFlag = 0
        PdFlag = 0
        WdPrefix = 0
        PdPrefix = 0
        WdClass = 0
        PdClass = 2
        MaxInstanceCount = [uint32]::MaxValue
        fAllowSecProtocolNegotiation = 1
    }
    foreach ($name in $values.Keys) {
        New-ItemProperty -Path $listener -Name $name -PropertyType DWord -Value $values[$name] -Force | Out-Null
    }
    foreach ($entry in @{
        WdName = 'Microsoft RDP 8.0'
        PdName = 'tcp'
        LoadableProtocol_Object = $protocol
    }.GetEnumerator()) {
        New-ItemProperty -Path $listener -Name $entry.Key -PropertyType String -Value $entry.Value -Force | Out-Null
    }
    # Preserve existing authentication/security settings; supply secure defaults if absent.
    foreach ($entry in @{UserAuthentication = 1; SecurityLayer = 1}.GetEnumerator()) {
        if ($null -eq (Get-ItemProperty -Path $listener).PSObject.Properties[$entry.Key]) {
            New-ItemProperty -Path $listener -Name $entry.Key -PropertyType DWord -Value $entry.Value | Out-Null
        }
    }
    Enable-NetFirewallRule -Name 'RemoteDesktop-UserMode-In-TCP','RemoteDesktop-UserMode-In-UDP'
    Set-Service -Name TermService -StartupType Automatic
    # Restart disconnects any active RDP sessions.
    Restart-Service -Name TermService -Force
    Start-Service -Name UmRdpService
    $ready = $false
    for ($attempt = 0; $attempt -lt 15; $attempt++) {
        if (Get-NetTCPConnection -State Listen -LocalPort 3389 -ErrorAction SilentlyContinue) {
            $ready = $true
            break
        }
        Start-Sleep -Seconds 1
    }
    if (-not $ready) { throw "RDP is not listening. Registry backup: $backup" }
    $client = [Net.Sockets.TcpClient]::new()
    try { $client.Connect('127.0.0.1', 3389) } finally { $client.Dispose() }
    Write-Host 'RDP repaired: TCP 3389 is listening and local connection succeeded.' -ForegroundColor Green
    Write-Host "Registry backup: $backup"
}