Created
April 27, 2017 11:27
-
-
Save JohnLBevan/8173b2b8aeb84b0c0f4b48900e43a478 to your computer and use it in GitHub Desktop.
Find all RDP sessions on servers using a PowerShell function to wrap the Query Session logic.
NB: Alternate Credentials not yet implemented
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Get-RdpSessions { | |
[CmdletBinding()] | |
param ( | |
[Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] | |
$ComputerName | |
, | |
[Parameter()] | |
[switch]$Force | |
<# not yet implememnted | |
, | |
[Parameter()] | |
[System.Management.Automation.Credential()] | |
[System.Management.Automation.PSCredential]$Credential = [System.Management.Automation.PSCredential]::Empty | |
#> | |
) | |
process { | |
#force logic | |
[bool]$forced = $false | |
[string]$previousValue = '' #hold as string in case this property's held as something other than int; i.e. we don't want to cause side effects | |
if ($Force.IsPresent) { | |
try { | |
$previousValue = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $ComputerName).OpenSubKey('SYSTEM\CurrentControlSet\Control\Terminal Server').GetValue('AllowRemoteRPC') | |
write-verbose "$ComputerName's AllowRDP = $previousValue" | |
if($previousValue -ne '1') { | |
[Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $ComputerName).OpenSubKey('SYSTEM\CurrentControlSet\Control\Terminal Server',$true).SetValue('AllowRemoteRPC', 1) | |
$forced = $true | |
write-verbose "$ComputerName's AllowRDP Forced to 1" | |
} | |
} catch { | |
write-verbose "$ComputerName's AllowRDP failed to use the force :(" | |
#even if we fail here, we still proceed; as we may be able to see sessions on the remote machine even if we can't read from its registry | |
} | |
} | |
#query session logic | |
try { | |
#https://ss64.com/nt/query-session.html | |
#pull the results into a variable | |
[string[]]$querySessionResult = (qwinsta "/server:$ComputerName") | |
#it would be nice to figute out the fixed-width column sizes automatically, in case they vary; but as the ID column is right aligned, that's not so easy: | |
#[string]$regex = '^' + (($querySessionResult[0] -split '\s\b' | select -skip 1 | %{"(?<$($_.trim())>.{$($_.Length+1)}"}) -join ')') + '.*)$' | |
#so instead using a fixed defintion: | |
[string]$regex = '^(?<SESSIONNAME>.{18})(?<USERNAME>.{18})(?<ID>.{11})(?<STATE>.{8})(?<TYPE>.{7})(?<DEVICE>.*)$' #column sizes from https://superuser.com/a/1000089/156700 | |
$querySessionResult | select -skip 1 | ?{$_ -match $regex} | %{ | |
$matches.remove(0) | |
$properties = @{} | |
$Matches.Keys | %{$properties[$_] = "$($Matches[$_])".Trim()} | |
(New-Object -TypeName PSObject -Property $properties) | |
} | |
} finally { #regardless of whether the above works, ensure that if we forced things, we put them back how they were | |
if($forced) { | |
[Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $ComputerName).OpenSubKey('SYSTEM\CurrentControlSet\Control\Terminal Server',$true).SetValue('AllowRemoteRPC', $previousValue) | |
write-verbose "$ComputerName's AllowRDP reset to $previousValue" | |
} | |
} | |
} | |
} | |
#demo for one computer | |
Get-RdpSessions -ComputerName $MyComputer -Force -Verbose | |
#demo for all servers in AD: | |
#uses Test-ConnectionQuickly workflow from here to avoid running against offline machines https://codereview.stackexchange.com/questions/97726/powershell-to-quickly-ping-a-number-of-machines | |
$servers = Get-AdComputer {(OperatingSystem -like "*server*") -and (Enabled -eq $true)} | |
$servers = Test-ConnectionQuickly $servers | ? Online | |
$servers | Get-RdpSessions -Force -Verbose | ? Username |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment