You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell中通过psexec.exe调用vmrun.exe无法获取StdOut/StdErr如何解决

问题根因

你遇到的输出丢失问题由3个常见原因导致:

  1. PsExec调用时缺少必要参数,默认没有完全透传子进程的标准输出/错误
  2. 你当前使用的Invoke-Process函数存在输出读取逻辑缺陷,先等待进程退出再同步读取两个输出流,极易触发死锁导致输出被截断/丢失
  3. 未处理PsExec首次运行的EULA确认逻辑,可能导致进程静默卡住无输出

修复方案

1. 优化Invoke-Process函数

修正输出读取逻辑,改用异步读取避免死锁:

function Invoke-Process {
    [CmdletBinding(SupportsShouldProcess)]
    param
        (
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$FilePath,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string]$ArgumentList,

        [ValidateSet("Full","StdOut","StdErr","ExitCode","None")]
        [string]$DisplayLevel
        )

    $ErrorActionPreference = 'Stop'

    try {
        $pinfo = New-Object System.Diagnostics.ProcessStartInfo
        $pinfo.FileName = $FilePath
        $pinfo.RedirectStandardError = $true
        $pinfo.RedirectStandardOutput = $true      
        $pinfo.StandardOutputEncoding = [System.Text.Encoding]::UTF8
        $pinfo.StandardErrorEncoding = [System.Text.Encoding]::UTF8

        $pinfo.UseShellExecute = $false
        $pinfo.WindowStyle = 'Hidden'
        $pinfo.CreateNoWindow = $true
        $pinfo.Arguments = $ArgumentList
        $p = New-Object System.Diagnostics.Process
        $p.StartInfo = $pinfo
        $p.EnableRaisingEvents = $true
        
        # 异步收集输出避免死锁
        $stdOutBuilder = New-Object System.Text.StringBuilder
        $stdErrBuilder = New-Object System.Text.StringBuilder
        Register-ObjectEvent -InputObject $p -EventName OutputDataReceived -Action {
            param($sender, $e)
            if (-not [string]::IsNullOrEmpty($e.Data)) {
                $Event.MessageData.AppendLine($e.Data)
            }
        } -MessageData $stdOutBuilder | Out-Null
        Register-ObjectEvent -InputObject $p -EventName ErrorDataReceived -Action {
            param($sender, $e)
            if (-not [string]::IsNullOrEmpty($e.Data)) {
                $Event.MessageData.AppendLine($e.Data)
            }
        } -MessageData $stdErrBuilder | Out-Null

        $p.Start() | Out-Null
        $p.BeginOutputReadLine()
        $p.BeginErrorReadLine()
        $p.WaitForExit()
        
        # 等待异步事件处理完成
        Start-Sleep -Milliseconds 100

        $result = [pscustomobject]@{
        Title = ($MyInvocation.MyCommand).Name
        Command = $FilePath
        Arguments = $ArgumentList
        StdOut = $stdOutBuilder.ToString().Trim()
        StdErr = $stdErrBuilder.ToString().Trim()
        ExitCode = $p.ExitCode
        }
        

        if (-not([string]::IsNullOrEmpty($DisplayLevel))) {
            switch($DisplayLevel) {
                "Full" { return $result; break }
                "StdOut" { return $result.StdOut; break }
                "StdErr" { return $result.StdErr; break }
                "ExitCode" { return $result.ExitCode; break }
                }
            }
        }
    catch {
        Write-Error $_
    }
}

2. 修正PsExec调用参数

需要补充以下参数确保输出正常透传:

  • /accepteula:自动接受PsExec的许可协议,避免首次运行静默卡住
  • -nobanner:关闭PsExec自身的版权banner输出,避免干扰子进程输出
  • 本地执行需要显式指定\\localhost作为目标主机
  • 如果vmrun需要桌面交互权限,补充-i参数

修正后的调用示例:

write-host "******************************Call vmrun directly******************************"
Invoke-Process -FilePath  "C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe" -ArgumentList "stop E:\VMs\VM1\vm1.vmx" -DisplayLevel Full
write-host "******************************Call vmrun from psexec******************************"
Invoke-Process -FilePath  "C:\Windows\System32\PsExec64.exe" -ArgumentList "/accepteula -nobanner \\localhost ""C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe"" stop E:\VMs\VM1\vm1.vmx" -DisplayLevel Full

额外注意事项

  • 运行PowerShell时需要以管理员权限启动,否则PsExec调用本地系统进程会权限不足
  • 如果vmrun操作的虚拟机是在当前用户桌面运行的,需要在PsExec参数中补充-i 1指定当前会话ID,否则vmrun会找不到目标虚拟机导致无输出

内容的提问来源于stack exchange,提问作者funkmaster

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 10:06:02