PowerShell脚本无法注销域内服务器会话的问题排查
脚本问题排查与修复
核心问题点及修复方案
远程脚本块传递错误
原代码中Invoke-Command -ScriptBlock {$ScriptBlock}是将本地定义的$ScriptBlock作为嵌套脚本块传递,远程会话无法正确解析执行逻辑。正确做法是直接传递$ScriptBlock变量:Invoke-Command -ComputerName $Server -ScriptBlock $ScriptBlock远程会话无法获取
$Server变量
本地$Server变量不会自动传入远程会话,导致输出的服务器名称为空。可改用远程机器的环境变量$env:COMPUTERNAME获取当前执行的服务器名称,或通过ArgumentList传递变量并在脚本块中用param接收。quser输出处理逻辑错误,仅能获取第一个会话ID
当quser返回多行会话记录时,$Sessions -split ' +'会将所有行内容合并为一个数组,取索引[2]只能拿到第一行的会话ID。正确方式是遍历每行会话记录单独拆分提取ID:$SessionIDs = $Sessions | ForEach-Object { ($_ -split ' +')[2] }变量比较运算符使用错误
原代码用$Server -isnot $env:COMPUTERNAME判断是否为本地机器,-isnot是类型判断运算符,字符串比较应使用-ne:if ($Server -ne $env:COMPUTERNAME)错误偏好设置未作用于远程会话
本地设置的$ErrorActionPreference不会同步到远程会话,需将该设置放到远程脚本块内部,确保远程执行时错误被静默处理,避免单台机器报错中断整个脚本。未过滤AD计算机对象,包含非目标机器
Get-ADComputer -Filter *会获取域内所有计算机(含客户端、离线设备),建议添加过滤条件仅获取Windows服务器:$Servers = (Get-ADComputer -Filter {OperatingSystem -like "*Windows Server*"}).Name
修正后的完整脚本
# 获取域内所有Windows服务器名称 $Servers = (Get-ADComputer -Filter {OperatingSystem -like "*Windows Server*"}).Name # 定义远程执行的脚本块 $ScriptBlock = { $ErrorActionPreference = "SilentlyContinue" $CurrentUser = $env:USERNAME $CurrentServer = $env:COMPUTERNAME # 获取当前用户的会话记录 $Sessions = quser | Where-Object { $_ -match $CurrentUser } if ($Sessions.Count -ge 1) { # 遍历每行会话,提取会话ID $SessionIDs = $Sessions | ForEach-Object { ($_ -split ' +')[2] } Write-Host "Found $($SessionIDs.Count) user login(s) on $CurrentServer." # 逐个注销会话 $SessionIDs | ForEach-Object { Write-Host "Logging off session [$_] on $CurrentServer..." logoff $_ } } } # 遍历服务器执行远程命令 foreach ($Server in $Servers) { if ($Server -ne $env:COMPUTERNAME) { # 跳过不可达的服务器,避免脚本卡住 if (Test-Connection -ComputerName $Server -Count 1 -Quiet) { Invoke-Command -ComputerName $Server -ScriptBlock $ScriptBlock } else { Write-Host "Server $Server is unreachable, skipping." } } }
内容的提问来源于stack exchange,提问作者Petr Synek
相关产品推荐
相关产品推荐

