如何查询所有WTS / RDP会话?



如何查询所有WTS/RDP会话?

我想知道谁在Windows机器上有会话,但不想使用和解析quser,qwinsta,query sessionquery user的输出。

信息:
这只是一个自我回答的问题。

可以使用以下函数:
基础来自P/Invoke民间,但已被我改编和增强。
P/Invoke base: https://pinvoke.net/default.aspx/wtsapi32.WTSEnumerateSessions

<标题>

函数这段代码是一个简单的高级函数。
同时,我也创建了一个enhanced version,发布在这里:https://gist.github.com/swbbl/205694b7e1bdf09e74f25800194d5bcd

function Get-ComputerSession {
[CmdletBinding()]
param(
# The computer name to get the current sessions from.
[Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
[AllowEmptyString()]
[String]
$ComputerName
)
begin {
# this script is based on the PS code example for WTSEnumerateSessions from:
# https://pinvoke.net/default.aspx/wtsapi32.WTSEnumerateSessions
# but has many adaptions and enhancements.
# thanks for the input!
Add-Type -TypeDefinition @'
using System;
using System.Runtime.InteropServices;
using System.ComponentModel;
namespace WTS
{
public class API {
// https://learn.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsopenserverexw
[DllImport("wtsapi32.dll", SetLastError=true, CharSet = CharSet.Unicode)]
public static extern IntPtr WTSOpenServerEx(string pServerName);
// https://learn.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtscloseserver
[DllImport("wtsapi32.dll", SetLastError=true, CharSet = CharSet.Unicode)]
public static extern void WTSCloseServer(System.IntPtr hServer);
// https://learn.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsenumeratesessionsexw
[DllImport("wtsapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern int WTSEnumerateSessionsEx(
System.IntPtr hServer,
ref int pLevel,
int Filter,
ref System.IntPtr ppSessionInfo,
ref int pCount);
[DllImport("wtsapi32.dll", SetLastError=true)]
public static extern int WTSQuerySessionInformationW(
System.IntPtr hServer,
int SessionId,
int WTSInfoClass ,
ref System.IntPtr ppSessionInfo,
ref int pBytesReturned );
// https://learn.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsfreememoryexw
[DllImport("wtsapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool WTSFreeMemoryEx(
WTS_TYPE_CLASS WTSTypeClass,
IntPtr pMemory,
UInt32 NumberOfEntries);
}
// https://learn.microsoft.com/en-us/windows/win32/api/wtsapi32/ns-wtsapi32-wts_session_info_1w
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct WTS_SESSION_INFO_1
{
public int ExecEnvId;
public WTS_CONNECTSTATE_CLASS State;
public UInt32 SessionId;
public String SessionName;
public String HostName;
public String UserName;
public String DomainName;
public String FarmName;
}
public enum WTS_TYPE_CLASS
{
TypeProcessInfoLevel0,
TypeProcessInfoLevel1,
TypeSessionInfoLevel1
}
// https://learn.microsoft.com/en-us/windows/win32/api/wtsapi32/ne-wtsapi32-wts_connectstate_class
public enum WTS_CONNECTSTATE_CLASS
{
[Description("A user is logged on to the WinStation. This state occurs when a user is signed in and actively connected to the device.")]
Active,
[Description("The WinStation is connected to the client.")]
Connected,
[Description("The WinStation is in the process of connecting to the client.")]
ConnectQuery,
[Description("The WinStation is shadowing another WinStation.")]
Shadow,
[Description("The WinStation is active but the client is disconnected. This state occurs when a user is signed in but not actively connected to the device, such as when the user has chosen to exit to the lock screen.")]
Disconnected,
[Description("The WinStation is waiting for a client to connect.")]
Idle,
[Description("The WinStation is listening for a connection. A listener session waits for requests for new client connections. No user is logged on a listener session. A listener session cannot be reset, shadowed, or changed to a regular client session.")]
Listen,
[Description("The WinStation is being reset.")]
Reset,
[Description("The WinStation is down due to an error.")]
Down,
[Description("The WinStation is initializing.")]
Init
}
}
'@
$wtsSessionDataSize = [System.Runtime.InteropServices.Marshal]::SizeOf([System.Type][WTS.WTS_SESSION_INFO_1])
}
process {
[UInt32] $pLevel        = 1 # for a reserved parameter. must be always 1
[UInt32] $pCount        = 0
[IntPtr] $ppSessionInfo = 0
try {
[IntPtr] $wtsServerHandle = [WTS.API]::WTSOpenServerEx($ComputerName)
if (-not $wtsServerHandle) {
throw [System.ComponentModel.Win32Exception]::new([Runtime.InteropServices.Marshal]::GetLastWin32Error())
}
[bool] $wtsSessionsCheck = [WTS.API]::WTSEnumerateSessionsEx($wtsServerHandle, [ref] $pLevel, [UInt32] 0, [ref] $ppSessionInfo, [ref] $pCount)
if (-not $wtsSessionsCheck) {
throw [System.ComponentModel.Win32Exception]::new([Runtime.InteropServices.Marshal]::GetLastWin32Error())
}
for ($i = 0; $i -lt $pCount; $i++) {
$wtsSessionInfoOffset = $wtsSessionDataSize * $i
[System.Runtime.InteropServices.Marshal]::PtrToStructure([IntPtr]::Add($ppSessionInfo, $wtsSessionInfoOffset), [type][WTS.WTS_SESSION_INFO_1])
}
} catch {
Write-Error -ErrorRecord $_
} finally {
try {
$wtsSessionInfoFreeMemCheck = [WTS.API]::WTSFreeMemoryEx([WTS.WTS_TYPE_CLASS]::TypeSessionInfoLevel1, $ppSessionInfo, $pCount)
if (-not $wtsSessionInfoFreeMemCheck) {
throw [System.ComponentModel.Win32Exception]::new([Runtime.InteropServices.Marshal]::GetLastWin32Error())
}
} finally {
$ppSessionInfo = [IntPtr]::Zero
[WTS.API]::WTSCloseServer($wtsServerHandle)
}
}
}
}

如何使用

使用不带参数ComputerName的函数将要求您输入名称。如果您想获得本地计算机/服务器的会话,或者为参数ComputerName

提供一个空字符串,请按[ENTER]。<标题>

例子用于本地查询。

PS> Get-ComputerSession -ComputerName ''
ExecEnvId   : 0
State       : Disconnected
SessionId   : 0
SessionName : Services
HostName    :
UserName    :
DomainName  :
FarmName    :
ExecEnvId   : 1
State       : Active
SessionId   : 1
SessionName : Console
HostName    :
UserName    : svenw
DomainName  : SVEN-PC
FarmName    :
ExecEnvId   : 2
State       : Disconnected
SessionId   : 2
SessionName :
HostName    :
UserName    : Test
DomainName  : Sven-PC
FarmName    :

每个属性(或多或少)在这里解释:https://learn.microsoft.com/en-us/windows/win32/api/wtsapi32/ns-wtsapi32-wts_session_info_1w

<标题>

增强版我还在gist上创建并上传了一个更增强的版本:https://gist.github.com/swbbl/205694b7e1bdf09e74f25800194d5bcd

最新更新