Загрузка данных
# Paste this entire block into Windows PowerShell (Run as Administrator).
# Standalone, no downloads; fixes the installer task without restarting RDP.
& {
# Windows Installer Builder 2026.9.18: repair existing installations.
# Run in an elevated Windows PowerShell. -WhatIf only inspects the change.
# Keeps the current listener port, NLA and security settings; never restarts RDP.
[CmdletBinding(SupportsShouldProcess=$true)]
param()
function Test-BuilderRdpTask {
param($Task, [string]$ScriptPath)
$actions = @($Task.Actions)
if ($actions.Count -ne 1) { return $false }
$exe = [Environment]::ExpandEnvironmentVariables([string]$actions[0].Execute).Trim('"')
if ([IO.Path]::GetFileName($exe) -notmatch '^powershell(?:\.exe)?$') { return $false }
$arguments = [Environment]::ExpandEnvironmentVariables([string]$actions[0].Arguments)
$match = [regex]::Match($arguments, '(?i)^\s*(?:-(?:NoProfile|NonInteractive|WindowStyle\s+Hidden|ExecutionPolicy\s+Bypass)\s+)*-File\s+(?:"([^"]+)"|([^\s"]+))\s*$')
if (-not $match.Success) { return $false }
$file = $match.Groups[1].Value
if (-not $file) { $file = $match.Groups[2].Value }
if ($file -ine $ScriptPath -or -not (Test-Path -LiteralPath $ScriptPath)) { return $false }
$content = Get-Content -LiteralPath $ScriptPath -Raw -ErrorAction Stop
# Identify the legacy builder script as well as its exact task action.
return ($content -match 'fDenyTSConnections\s+0\s+-Type\s+DWord' -and
$content -match 'UserAuthentication\s+0\s+-Type\s+DWord' -and
$content -match 'A509B1A7-37EF-4b3f-8CFC-4F3A74704073' -and
$content -match 'Restart-Service\s+(?:-Name\s+)?TermService\s+-Force')
}
function Get-BuilderRdpSnapshot {
$listener = 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp'
$server = 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server'
$policy = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services'
$result = @{}
foreach ($path in @($listener, $server, $policy)) {
$values = @{}
if (Test-Path -LiteralPath $path) {
$key = Get-ItemProperty -LiteralPath $path -ErrorAction Stop
foreach ($name in @('PortNumber', 'UserAuthentication', 'SecurityLayer', 'fDenyTSConnections')) {
if ($null -ne $key.PSObject.Properties[$name]) { $values[$name] = $key.$name }
}
}
$result[$path] = $values
}
return $result
}
function Test-BuilderRdpAdministrator {
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object Security.Principal.WindowsPrincipal($identity)
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
function Invoke-BuilderRdpRepair {
[CmdletBinding(SupportsShouldProcess=$true)]
param()
$ErrorActionPreference = 'Stop'
$task = @(Get-ScheduledTask -TaskPath '\' -ErrorAction Stop |
Where-Object { $_.TaskName -eq 'WinRdpNla' })
if ($task.Count -eq 0) {
Write-Output 'WinRdpNla not found. No changes made; inspect domain policies or provider agents if settings still reset.'
return
}
$scriptPath = Join-Path $env:SystemRoot 'Setup\Scripts\DisableNla.ps1'
if ($task.Count -ne 1 -or -not (Test-BuilderRdpTask $task[0] $scriptPath)) {
throw 'WinRdpNla does not match the known installer task. Nothing changed; inspect it manually.'
}
$before = Get-BuilderRdpSnapshot
$policyPath = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services'
$policyNames = @()
$standalone = $false
try { $standalone = -not (Get-CimInstance Win32_ComputerSystem -ErrorAction Stop).PartOfDomain }
catch { Write-Warning 'Domain membership could not be checked. Policy values will be preserved.' }
if ($standalone) {
foreach ($name in @('UserAuthentication', 'SecurityLayer')) {
$legacy = if ($name -eq 'UserAuthentication') { 0 } else { 1 }
if ($before[$policyPath].ContainsKey($name) -and $before[$policyPath][$name] -eq $legacy) {
$policyNames += $name
}
}
} else {
Write-Warning 'Policy overrides are preserved on domain/unknown machines. Check the domain RDP policy separately.'
}
if (-not $task[0].Settings.Enabled -and $policyNames.Count -eq 0) {
Write-Output 'Legacy RDP reset task is already disabled. No changes needed.'
return
}
if (-not $PSCmdlet.ShouldProcess($env:COMPUTERNAME,
'Back up and disable the installer RDP reset task; remove its legacy policy overrides on standalone Windows')) { return }
if (-not (Test-BuilderRdpAdministrator)) {
throw 'Run this patch from Windows PowerShell as Administrator.'
}
$backupRoot = Join-Path $env:ProgramData 'WinInstallBuilder\Backups'
$backup = Join-Path $backupRoot ('Rdp-' + (Get-Date -Format 'yyyyMMdd-HHmmss') + '-' + [guid]::NewGuid().ToString('N'))
New-Item -ItemType Directory -Path $backup -Force | Out-Null
Export-ScheduledTask -TaskName 'WinRdpNla' -TaskPath '\' -ErrorAction Stop |
Set-Content -LiteralPath (Join-Path $backup 'WinRdpNla.xml') -Encoding Unicode
$before | Export-Clixml -LiteralPath (Join-Path $backup 'registry-before.xml')
Copy-Item -LiteralPath $scriptPath -Destination (Join-Path $backup 'DisableNla.ps1')
Disable-ScheduledTask -TaskName 'WinRdpNla' -TaskPath '\' -ErrorAction Stop | Out-Null
$currentTask = Get-ScheduledTask -TaskName 'WinRdpNla' -TaskPath '\' -ErrorAction Stop
if ($currentTask.State -eq 'Running') {
Stop-ScheduledTask -TaskName 'WinRdpNla' -TaskPath '\' -ErrorAction Stop
$stopped = $false
for ($attempt = 0; $attempt -lt 20; $attempt++) {
if ((Get-ScheduledTask -TaskName 'WinRdpNla' -TaskPath '\').State -ne 'Running') { $stopped = $true; break }
Start-Sleep -Milliseconds 250
}
if (-not $stopped) { throw "Legacy task did not stop. Backup: $backup" }
}
foreach ($name in $policyNames) {
Remove-ItemProperty -LiteralPath $policyPath -Name $name -ErrorAction Stop
}
if ((Get-ScheduledTask -TaskName 'WinRdpNla' -TaskPath '\').Settings.Enabled) {
throw "Legacy task is still enabled. Backup: $backup"
}
$after = Get-BuilderRdpSnapshot
$after | Export-Clixml -LiteralPath (Join-Path $backup 'registry-after.xml')
foreach ($path in $before.Keys) {
if ($path -eq $policyPath) { continue }
foreach ($name in $before[$path].Keys) {
if ($after[$path][$name] -ne $before[$path][$name]) {
Write-Warning "Listener value changed during repair: $name. A previously running task or another service may have changed it; inspect the saved snapshots."
}
}
}
Write-Output "Patched: WinRdpNla disabled. Current RDP settings preserved; no service restart or reboot. Backup: $backup"
if ($policyNames.Count) { Write-Output ('Removed installer policy overrides: ' + ($policyNames -join ', ')) }
}
try {
if (-not (Test-BuilderRdpAdministrator)) {
throw 'Open Windows PowerShell as Administrator, paste this entire block again, and press Enter.'
}
if ([Environment]::Is64BitOperatingSystem -and -not [Environment]::Is64BitProcess) {
throw 'Use 64-bit Windows PowerShell to patch the Windows RDP configuration.'
}
Invoke-BuilderRdpRepair -Confirm:$false
} catch {
Write-Host ('PATCH ERROR: ' + $_.Exception.Message) -ForegroundColor Red
}
}