The PowerShell script is designed to extract information about Remote Desktop Protocol (RDP) local session manager events from the Windows event logs on a RDS host and save it to a CSV file.
Script: Get events with EventID 40 from Microsoft-Windows-TerminalServices-LocalSessionManager/Operational Event Log
$RDPAuths = Get-WinEvent -LogName 'Microsoft-Windows-TerminalServices-LocalSessionManager/Operational'-FilterXPath '<QueryList><Query Id="0"><Select>*[System[EventID=40]]</Select></Query></QueryList>'
[xml[]]$xml = $RDPAuths | ForEach-Object { $_.ToXml() }
$EventData = $xml.Event | ForEach-Object {
[PSCustomObject]@{
TimeCreated = (Get-Date $_.System.TimeCreated.SystemTime -Format 'yyyy-MM-dd hh:mm:ss K')
Session = $_.UserData.EventXML.Session
Reason = $_.UserData.EventXML.Reason
EventID = $_.System.EventID
User = $_.UserData.EventXML.User
SessionID = $_.UserData.EventXML.SessionID
Address = $_.UserData.EventXML.Address
}
}
$EventData | Export-Csv -Path c:\rdlog-LSM-Operational.csv -Encoding ASCII
Here is an explanation of how the code works.
- First, the script uses the
Get-WinEventcmdlet to retrieve events from the ‘Microsoft-Windows-TerminalServices-LocalSessionManager/Operational’ log. This log contains information about RDP disconnections. The events are stored in the$RDPAuthsvariable. - The
$RDPAuthsvariable is then piped to theForEach-Objectcmdlet to convert each event to XML format using theToXml()method. The resulting array of XML objects is stored in the$xmlvariable. - Next, the script uses the
ForEach-Objectcmdlet again to iterate over the$xml.Eventarray. For each event, a new custom object is created using the[PSCustomObject]@{}syntax. This custom object contains the following properties:TimeCreated,Session,Reason,EventID,User,SessionID, andAddress. These properties are extracted from the event XML data using dot notation. - Finally, the custom objects are piped to the
Export-Csvcmdlet, which saves the objects as a CSV file at the specified path (c:\rdlog-LSM-Operational.csv) with ASCII encoding.
This PowerShell script is useful for extracting and analyzing RDP local session manager events, such as monitoring for disconnect reasons. The resulting CSV file provides a simple, convenient way to view and analyze the RDP events.
RDS Session Host Server Disconnect Codes
| RDS server client disconnect code | Disconnect reason |
|---|---|
| 0x00000001 | The disconnection was initiated by an administrative tool on the server in another session. |
| 0x00000002 | The disconnection was due to a forced logoff initiated by an administrative tool on the server in another session. |
| 0x00000003 | The idle session limit timer on the server has elapsed. |
| 0x00000004 | The active session limit timer on the server has elapsed. |
| 0x00000005 | Another user connected to the server, forcing the disconnection of the current connection. |
| 0x00000006 | The server ran out of available memory resources. |
| 0x00000007 | The server denied the connection. |
| 0x00000009 | The user cannot connect to the server due to insufficient access privileges. |
| 0x0000000A (10) | The server does not accept saved user credentials and requires that the user enter their credentials for each connection. |
| 0x0000000B (11) | The disconnection was initiated by the user disconnecting his or her session on the server or by an administrative tool on the server. |
| 0x0000000C (12) | The disconnection was initiated by the user logging off his or her session on the server. |
Extended Disconnect Reason Codes
Reference: https://learn.microsoft.com/en-us/windows/win32/termserv/extendeddisconnectreasoncode
| Extended Reason | Code |
|---|---|
| NoInfo | 0 |
| APIInitiatedDisconnect | 1 |
| APIInitiatedLogoff | 2 |
| ServerIdleTimeout | 3 |
| ServerLogonTimeout | 4 |
| ReplacedByOtherConnection | 5 |
| OutOfMemory | 6 |
| ServerDeniedConnection | 7 |
| ServerDeniedConnectionFips | 8 |
| ServerInsufficientPrivileges | 9 |
| ServerFreshCredsRequired | 10 |
| RpcInitiatedDisconnectByUser | 11 |
| LogoffByUser | 2 |
| LicenseInternal | 256 |
| LicenseNoLicenseServer | 257 |
| LicenseNoLicense | 258 |
| LicenseErrClientMsg | 259 |
| LicenseHwidDoesntMatchLicense | 260 |
| LicenseErrClientLicense | 261 |
| LicenseCantFinishProtocol | 262 |
| LicenseClientEndedProtocol | 263 |
| LicenseErrClientEncryption | 264 |
| LicenseCantUpgradeLicense | 265 |
| LicenseNoRemoteConnections | 266 |
| LicenseCreatingLicStoreAccDenied | 267 |
| RdpEncInvalidCredentials | 768 |
| ProtocolRangeStart | 4096 |
| ProtocolRangeEnd | 32767 |