PowerShell查询锁定用户会话:过滤无效结果与解析问题求助
问题1:过滤无用户的计算机并仅返回匹配用户的会话
原代码问题点
- 匹配到"No User exists for *"时用
break会直接终止整个遍历循环,应该跳过当前计算机而非停止全部任务 - 条件判断的括号层级混乱,导致部分逻辑分支无法正确执行
- 未处理
query user命令执行失败的场景(比如计算机离线、权限不足)
修正后的代码
$computers = Get-ADComputer -Filter * | Select-Object -ExpandProperty Name $total = $computers.Count $counter = 0 $stringToMatch = "No User exists for" $lockedOutUser = 'rdiring' foreach ($computer in $computers) { $counter++ $percentComplete = ($counter / $total) * 100 Write-Progress -Activity "Processing computers" -Status "Computer $counter of $total" -PercentComplete $percentComplete try { # 捕获命令执行的错误,避免中断循环 $quserResult = query user /server:$computer 2>&1 Start-Sleep -Milliseconds 50 # 检查是否无用户或命令执行失败 if ($quserResult -match $stringToMatch -or $quserResult -is [System.Management.Automation.ErrorRecord]) { continue } # 解析输出为CSV对象 $quserRegex = $quserResult | ForEach-Object { $_ -replace '\s{2,}', ',' } $quserObject = $quserRegex | ConvertFrom-Csv # 筛选目标用户会话并输出 $userSession = $quserObject | Where-Object { $_.USERNAME -eq $lockedOutUser } if ($userSession) { [PSCustomObject]@{ ComputerName = $computer UserName = $userSession.USERNAME SessionID = $userSession.ID SessionState = $userSession.STATE LogonTime = $userSession.'LOGON TIME' } } } catch { continue } }
关键优化点
- 用
2>&1捕获命令的错误输出,判断计算机是否无法连接 - 匹配无用户提示时用
continue跳过当前计算机,不输出冗余信息 - 将结果封装为自定义对象,输出格式更规范易读
- 修正条件层级,确保逻辑分支正确执行
问题2:修复
query user解析代码输出为空的问题 原代码问题点
- 读取计算机列表到
$names后立刻赋值为空数组,导致循环没有数据可处理 - 仅匹配表头行,完全忽略了实际的用户会话数据行
-errorAction silentlyContinue写法错误,无法生效- 用
-split '\s+'解析数据行时,会因空的SESSIONNAME列导致字段错位
修正后的代码
# 定义输入输出路径 $InputFile = "C:\path\to\computers.txt" $OutputFile = "C:\path\to\session_results.csv" # 读取计算机列表,避免清空 $computerNames = Get-Content $InputFile $sessionResults = @() foreach ($name in $computerNames) { try { # 捕获错误输出,跳过无法连接的计算机 $Lines = @(query user /server:$name 2>&1) # 跳过命令执行失败或无用户的情况 if ($Lines -match "No User exists for" -or $Lines -is [System.Management.Automation.ErrorRecord]) { continue } # 跳过表头行,处理数据行 $dataLines = $Lines | Select-Object -Skip 1 foreach ($Line in $dataLines) { # 用正则匹配数据行,兼容SESSIONNAME为空的情况 if ($Line -match '^(\S+)\s+(.*?)\s+(\d+)\s+(\S+)\s+(\S+)\s+(.*)$') { $sessionResults += [PSCustomObject]@{ SERVER = $name USERNAME = $matches[1] SESSIONNAME = $matches[2].Trim() ID = $matches[3] STATE = $matches[4] IDLE_TIME = $matches[5] LOGON_TIME = $matches[6] } } } } catch { continue } } # 导出结果到CSV $sessionResults | Export-Csv -Path $OutputFile -NoTypeInformation
关键修复点
- 保留读取的计算机列表,用
$computerNames存储,避免覆盖 - 用
Select-Object -Skip 1跳过表头,处理实际数据行 - 采用正则表达式匹配数据行,解决空SESSIONNAME导致的字段错位问题
- 单独用
$sessionResults收集结果,避免和计算机列表变量混淆 - 正确处理命令执行错误,跳过无法访问的计算机
内容的提问来源于stack exchange,提问作者Richard Diring
相关产品推荐
相关产品推荐

