PowerShell如何将qwinsta结果转换为规范RDP会话对象
Get-QWinsta 可靠实现方案
不要用多空白替换为逗号再转CSV的解析逻辑——qwinsta 输出是固定列宽的格式化文本,当某字段为空(比如断开的会话没有SessionName、系统监听会话没有UserName)时,连续空白替换会直接吃掉空字段位置,必然导致列错位。
实现逻辑
- 先解析表头行的各列起始索引,按固定偏移切分每行内容,从根源避免错位
- 切分后直接过滤UserName字段为空/纯空白的系统会话(Disc/Listen/Conn类无有效用户的条目)
- 输出严格限定4个属性的强类型对象,支持直接属性调用
完整函数代码
function Get-QWinsta { # 执行qwinsta命令,跳过空行 $rawOutput = qwinsta 2>$null | Where-Object { $_ -notmatch '^\s*$' } if (-not $rawOutput) { return } # 解析表头,定位各列的起始偏移 $headerLine = $rawOutput[0] $columns = @( @{Name = 'SessionName'; Start = $headerLine.IndexOf('SESSIONNAME')}, @{Name = 'UserName'; Start = $headerLine.IndexOf('USERNAME')}, @{Name = 'SessionID'; Start = $headerLine.IndexOf('ID')}, @{Name = 'SessionState'; Start = $headerLine.IndexOf('STATE')} ) | Sort-Object Start -Descending # 逐行解析内容,跳过表头 $results = foreach ($line in $rawOutput[1..($rawOutput.Count - 1)]) { # 处理行首的>标记(当前会话标识),避免偏移错位 $line = $line -replace '^>', ' ' $entry = @{} # 按列偏移从后往前切分,避免前序切分影响后续索引 $currentLine = $line foreach ($col in $columns) { if ($col.Start -ge $currentLine.Length) { $entry[$col.Name] = $null continue } $value = $currentLine.Substring($col.Start).Trim() $currentLine = $currentLine.Substring(0, $col.Start) $entry[$col.Name] = $value } # 过滤无有效用户名的冗余会话 if ([string]::IsNullOrWhiteSpace($entry.UserName)) { continue } # 构造规范输出对象,SessionID转整数类型 [PSCustomObject]@{ UserName = $entry.UserName SessionName = $entry.SessionName SessionID = [int]$entry.SessionID SessionState = $entry.SessionState } } return $results }
用法验证
直接调用即可获得结构化对象,支持属性直接取值:
# 获取所有有效用户会话 $allSessions = Get-QWinsta # 直接提取所有用户名 $allUserNames = (Get-QWinsta).UserName # 按会话ID筛选目标会话 $targetSession = Get-QWinsta | Where-Object SessionID -eq 2
该实现不会出现列错位问题,也不会返回无用户的系统空会话,所有返回条目均为绑定了有效用户的活动/断开RDP、控制台会话。
内容的提问来源于stack exchange,提问作者Chris Hatzis
相关产品推荐
相关产品推荐

