使用PsExec获取远程进程无法返回完整表格结果的问题
问题描述
我用PsExec写了个脚本批量获取多台电脑的进程,脚本能运行但出不来预期的表格化结果,只返回部分零散内容。公司防火墙、杀毒软件和组策略限制,没法用Invoke-Command或Get-PSSession,加的例外电脑更新后会自动重置。
- 当前执行结果:仅返回无结构的进程文本,列不对齐,字段展示混乱
- 预期结果:进程信息以标准PowerShell表格形式展示,包含
Name、ID、VM、PM列,格式整齐、字段完整
现有脚本代码
$pathscript = "D:\SCRIPTSM\ALV" $fpassword = "D:\SCRIPTSM\pswd.json" $rutaLog = "D:\SCRIPTSM\ALV\fallos.log" $fecha = Date Set-Location -Path $pathscript $JsonObject = Get-Content $fpassword | ConvertFrom-Json $usuario = 'Administrador' $password = $JsonObject.password $equipos = "D:\SCRIPTSM\despFi\equinom.txt" $listaEquipos = Get-Content $equipos foreach ($equipo in $listaEquipos){ if (test-connection -ComputerName $equipo -Count 1 -Quiet){ Set-Location -Path "D:\SCRIPTSM\PSTools" .\psexec.exe \$equipo -u $usuario -p $password -h powershell.exe Get-Process | Select -First 15 Name,ID,VM,PM >> 'D:\SCRIPTSM\ALV\PRUEBNOMB.txt' Set-Location -Path $pathscript }else{ Write-Output "No se puede conectar al equipo --> $equipo" >> $rutaLog } }
解决方案
问题核心:PsExec返回的是纯文本流,不是PowerShell可识别的对象,本地的Select-Object没法对远程输出做正确的结构化处理。以下是三种可行修复方案:
方案1:让远程直接输出格式化表格(快速查看)
修改PsExec调用命令,让远程PowerShell先完成筛选并输出规整的表格,再写入文件:
.\psexec.exe \\$equipo -u $usuario -p $password -h powershell.exe "Get-Process | Select-Object -First 15 Name,ID,VM,PM | Format-Table -AutoSize" >> 'D:\SCRIPTSM\ALV\PRUEBNOMB.txt'
- 优点:直接得到整齐的表格文本,适合人工查看
- 缺点:输出是纯文本,后续无法用PowerShell做进一步数据处理
方案2:输出CSV格式(推荐,可复用)
如果需要后续对进程数据做分析,让远程输出CSV格式,本地追加到文件:
.\psexec.exe \\$equipo -u $usuario -p $password -h powershell.exe "Get-Process | Select-Object -First 15 Name,ID,VM,PM,@{Name='ComputerName';Expression={'$equipo'}} | ConvertTo-Csv -NoTypeInformation" >> 'D:\SCRIPTSM\ALV\PRUEBNOMB.csv'
- 额外添加
ComputerName字段,方便区分不同机器的进程 - 后续可通过
Import-Csv 'D:\SCRIPTSM\ALV\PRUEBNOMB.csv'将数据转为PowerShell对象,随时查看或处理
方案3:保留对象结构(灵活度最高)
让远程把进程对象序列化为XML,本地反序列化后再处理,避免纯文本解析问题:
# 获取远程序列化的XML输出 $remoteXml = .\psexec.exe \\$equipo -u $usuario -p $password -h powershell.exe "Get-Process | Select-Object -First 15 Name,ID,VM,PM | Export-Clixml -Path -" | Select-String -Pattern '<Objs' # 反序列化为PowerShell对象 $processObjects = $remoteXml.Line | ConvertFrom-Clixml # 追加表格到文本文件 $processObjects | Format-Table -AutoSize >> 'D:\SCRIPTSM\ALV\PRUEBNOMB.txt' # 或者追加带机器名的CSV数据 $processObjects | Select-Object *,@{Name='ComputerName';Expression={$equipo}} | Export-Csv 'D:\SCRIPTSM\ALV\PRUEBNOMB.csv' -Append -NoTypeInformation
- 保留了进程的对象属性,后续可任意筛选、排序、统计
- 用
Select-String过滤掉PsExec自带的启动提示文本,只保留有效XML数据
额外优化建议
- 避免频繁切换目录,直接使用PsExec的完整路径:
& "D:\SCRIPTSM\PSTools\psexec.exe" \\$equipo -u $usuario -p $password -h powershell.exe "..."
- 日志添加时间戳,方便排查问题:
$fecha = Get-Date -Format "yyyy-MM-dd HH:mm:ss" Write-Output "[$fecha] No se puede conectar al equipo --> $equipo" >> $rutaLog
内容的提问来源于stack exchange,提问作者AALV8
相关产品推荐
相关产品推荐

