PowerShell获取用户数量结果不准确的原因及修正方案咨询
问题原因与解决方案
一、错误结果的内部机制原因
你使用的Win32_LogonSession和Win32_LoggedOnUser这两个WMI类,核心问题出在登录会话的清理逻辑上:
- 用户注销交互会话后,只要还有以该用户身份运行的后台进程(比如未关闭的后台程序、挂起的服务进程)存在,系统不会立即销毁对应的登录会话对象。
- WMI通过读取这些未销毁的登录会话判定用户“在线”,但实际上用户已经退出了交互环境。
- 而服务器管理器的远程桌面服务模块,直接对接RD服务的会话管理数据,它会区分用户是否处于活跃交互状态——哪怕有残留进程,只要用户完成注销操作,RD服务就会标记该会话为离线,这就是两者结果不一致的根本原因。
二、准确获取用户数量的修正方案
方案1:使用RD服务专用命令(推荐)
直接调用远程桌面服务的PowerShell模块命令,和服务器管理器的数据源完全一致,结果最准确:
$computer = 'computername' # 获取所有活跃的远程桌面用户会话(可根据需求调整SessionState过滤条件) $activeUsers = Get-RDUserSession -ConnectionBroker $computer | Where-Object { $_.SessionState -eq 'Active' } $anzahl_user = $activeUsers.Count
注:该命令需要服务器安装远程桌面服务角色,且PowerShell会话拥有足够权限。
方案2:使用RD专用WMI类
如果无法使用RD模块,可直接查询专门针对远程桌面会话的WMI类Win32_RDMSession:
$computer = 'computername' # SessionState=2代表活跃会话,其他状态可根据需求过滤 $users = Get-WmiObject -ComputerName $computer -Class Win32_RDMSession | Where-Object { $_.SessionState -eq 2 } $anzahl_user = $users.Count
方案3:对原有WMI结果补充过滤
如果必须沿用原有逻辑,可通过检查会话的活跃交互进程来过滤无效会话:
$computer = 'computername' $users = Get-WmiObject Win32_LogonSession -Computer $computer -Filter 'LogonType=2 or LogonType=10' | ForEach-Object { $logonId = $_.LogonId # 检查该登录会话是否有活跃的交互进程(以explorer.exe为标志) $hasActiveProcess = Get-WmiObject -ComputerName $computer -Query "SELECT * FROM Win32_Process WHERE LogonId='$logonId' AND Name='explorer.exe'" if ($hasActiveProcess) { Get-WmiObject -ComputerName $computer -Query "Associators of {Win32_LogonSession.LogonId=$logonId} Where AssocClass=Win32_LoggedOnUser Role=Dependent" | Select-Object -ExpandProperty Name } } $anzahl_user = $users.Count
注:该方案依赖
explorer.exe作为交互活跃的标志,部分特殊场景可能不适用。
内容的提问来源于stack exchange,提问作者NinaGr
相关产品推荐
相关产品推荐

