【问题标题】:Getting stdout to appear on console with PowerShell Invoke-Command and Process使用 PowerShell Invoke-Command 和 Process 让标准输出出现在控制台上
【发布时间】:2016-06-05 21:52:04
【问题描述】:

我有一个使用 Invoke-Command 的 Powershell 脚本。这是正在调用的代码:

$scriptblock = {
  $process = New-Object system.Diagnostics.Process

  $si = New-Object System.Diagnostics.ProcessStartInfo
  $si.FileName = $cmd
  $si.Arguments = $cmd_args
  $si.UseShellExecute = false
  $si.RedirectStandardOutput = true

  $process.StartInfo = $si
  $process.Start()
  $processId = $process.Id
  $process.WaitForExit()
}

Invoke-Command -ScriptBlock $scriptblock

当从 PowerShell 窗口运行脚本时,该问题与让进程的标准输出显示到 PowerShell 控制台有关。

现在,我确信可执行文件 $cmd 会发送到标准输出,因为当我使用 cmd.exe 运行可执行文件时,它会向该控制台显示输出。当我从 NodeJS 脚本调用这个 Powershell 脚本时,我也能够成功地重定向输出,如下所示:

var exec  = require('child_process').exec,
var cmd   = 'powershell -ExecutionPolicy Bypass "' + launch_cmd + " \'" + ver + "\'\"";

console.log("\n\tUsing command for NodeJS child process:\n\t\t" + cmd + "\n\n")
child = exec(cmd, { cwd : prj }, function(stdout, stderr){});

child.stdout.on("data",function(data){
    process.stdout.write(data);
});

child.stderr.on("data",function(data){
    process.stderr.write(data);
});

child.on("exit",function(){
    console.log("\n\nFinished Process");
});

我希望能够将 StandardOutput 发送到 PowerShell 控制台。我查看了this TechNet documentation 并在脚本块中尝试了以下内容,但无济于事:

$scriptblock = {
  $process = New-Object system.Diagnostics.Process

  $si = New-Object System.Diagnostics.ProcessStartInfo
  $si.FileName = $cmd
  $si.Arguments = $cmd_args
  $si.UseShellExecute = false
  $si.RedirectStandardOutput = true

  $process.StartInfo = $si
  $process.Start()
  $process.BeginOutputReadLine()
  $process.StandardOutput.ReadToEnd()
  $processId = $process.Id
  $process.StandardOutput
  $process.WaitForExit()
}

Invoke-Command -ScriptBlock $scriptblock

关于如何使进程将其标准输出显示到 PowerShell 控制台的任何建议?

【问题讨论】:

  • 您必须为 $process.StandardOutput 分配一个流读取器,因为您链接的技术网显示。这个页面:stackoverflow.com/questions/8761888/… 说你可以这样做: $stdout = $p.StandardOutput.ReadToEnd() $stderr = $p.StandardError.ReadToEnd()

标签: node.js windows powershell


【解决方案1】:

您需要不断读取 StandardOutput 流,直到进程退出以获取所有内容:

$scriptblock = {

    param($cmd, $cmd_args)

    $process = New-Object system.Diagnostics.Process

    $si = New-Object System.Diagnostics.ProcessStartInfo
    $si.FileName = $cmd
    $si.Arguments = $cmd_args
    $si.UseShellExecute = $false
    $si.RedirectStandardOutput = $true

    $process.StartInfo = $si
    $process.Start() | Out-Null

    do{ # Keep redirecting output until process exits
        Write-Host $process.StandardOutput.ReadLine()
    } until ($process.HasExited)
}

Invoke-Command -ScriptBlock $scriptblock -ArgumentList "cmd.exe","/c echo test1 & echo test2 & ping 127.0.0.1 -n 3 > nul & echo test3"

您会看到输出流实时复制到您的主机。如果您有兴趣将结果传递到管道中,也可以使用 Write-Output

【讨论】:

  • 漂亮!非常感谢,马蒂亚斯。您的代码完美地解决了这个问题。我想我现在的问题是为什么 Node 能够显示输出而 Powershell 不能?
  • 因为您在 nodejs 示例中的流上主动订阅了“数据”事件。你可以在 PowerShell 中做同样的事情,但我认为对于 95% 的用例,这种方法 (do{}until($process.HasExited)) 可能就足够了(更不用说更简单和更清洁了):)
猜你喜欢
  • 1970-01-01
  • 2011-12-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-16
  • 1970-01-01
  • 2015-03-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多