RDP failure triage script
A read-only RDP triage script pattern for DNS, TCP 3389, listener state, firewall evidence, sessions, and event logs.
Good For
RDP outage triage
VPN path checks
Windows Server remote access
firewall evidence
helpdesk escalation
How to Use It
Start from the same network path as the affected user so VPN, VLAN, and firewall differences are visible.
Resolve the hostname and record the address that the client is actually trying to reach.
Test TCP 3389 before changing firewall policy or Remote Desktop settings.
Collect TermService state, listener/session output, Remote Desktop firewall rule state, and recent Terminal Services events.
If TCP fails but the service is healthy, compare network path, VPN split tunnel, NSG/firewall policy, and host profile scope.
Export the evidence to CSV or ticket notes before escalating to server, network, or identity owners.
Execution Modes
- local
- remote-single-host
- remote-host-list
- ad-filtered
Inputs and Outputs
Inputs
- computer name
- CSV or TXT server list
- Active Directory computer scope
- affected client network path
Outputs
- verbose-console
- csv
- operator-notes
Command Starter
Writes local output artifacts: review the output path before running
# ---------------------------------------------------------------------
# Operator inputs
# ---------------------------------------------------------------------
$ComputerNames = @('server01.contoso.com')
$OutputPath = '.\rdp-failure-triage.csv'
# ---------------------------------------------------------------------
# Gather client-path and server-side RDP evidence
# ---------------------------------------------------------------------
$Results = foreach ($ComputerName in $ComputerNames) {
$Dns = Resolve-DnsName -Name $ComputerName -ErrorAction SilentlyContinue
$Tcp3389 = Test-NetConnection -ComputerName $ComputerName -Port 3389 -InformationLevel Quiet -WarningAction SilentlyContinue
try {
$ServerEvidence = Invoke-Command -ComputerName $ComputerName -ErrorAction Stop -ScriptBlock {
$TermService = Get-Service -Name TermService
$RemoteDesktopRules = @(Get-NetFirewallRule -DisplayGroup 'Remote Desktop' -ErrorAction SilentlyContinue |
Select-Object DisplayName, Enabled, Profile, Direction, Action)
$RecentEvents = @(Get-WinEvent -LogName 'Microsoft-Windows-TerminalServices-LocalSessionManager/Operational' -MaxEvents 20 -ErrorAction SilentlyContinue)
[pscustomobject]@{
TermServiceStatus = $TermService.Status
EnabledRdpRuleCount = @($RemoteDesktopRules | Where-Object Enabled -eq 'True').Count
RecentTerminalServicesEventCount = $RecentEvents.Count
}
}
[pscustomobject]@{
ComputerName = $ComputerName
ResolvedAddress = ($Dns.IPAddress -join ', ')
Tcp3389Open = [bool]$Tcp3389
TermService = $ServerEvidence.TermServiceStatus
EnabledRdpRules = $ServerEvidence.EnabledRdpRuleCount
RecentRdpEvents = $ServerEvidence.RecentTerminalServicesEventCount
}
}
catch {
[pscustomobject]@{
ComputerName = $ComputerName
ResolvedAddress = ($Dns.IPAddress -join ', ')
Tcp3389Open = [bool]$Tcp3389
TermService = $null
EnabledRdpRules = $null
RecentRdpEvents = $null
Error = $_.Exception.Message
}
}
}
$Results | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8
$Results | Format-Table -AutoSizeValidation
The target name resolves to the expected address from the affected client path.
TCP 3389 reachability, service state, firewall rule state, and recent session events are all captured.
The escalation note separates client path failure, server listener failure, policy failure, and identity/session failure.
Reporting
export per-server RDP reachability and listener evidence to CSV
attach Terminal Services event snippets to the incident ticket
group failures by DNS, TCP path, service/listener, firewall profile, or session policy
Safety Notes
This triage pass is read-only and should not enable RDP, change firewall rules, or alter user rights.
Do not open TCP 3389 broadly without approval, scope review, and rollback planning.
