我想从我在PowerShell脚本中启动的进程中捕获stdout和stderr,并将其异步显示到控制台。我已经找到了一些通过MSDN和other blogs来实现这一点的文档。
在创建并运行下面的示例之后,我似乎无法获得任何要异步显示的输出。所有输出仅在进程终止时显示。
$ps = new-object System.Diagnostics.Process
$ps.StartInfo.Filename = "cmd.exe"
$ps.StartInfo.UseShellExecute = $false
$ps.StartInfo.RedirectStandardOutput = $true
$ps.StartInfo.Arguments = "/c echo `"hi`" `& timeout 5"
$action = { Write-Host $EventArgs.Data }
Register-ObjectEvent -InputObject $ps -EventName OutputDataReceived -Action $action | Out-Null
$ps.start() | Out-Null
$ps.BeginOutputReadLine()
$ps.WaitForExit()
在这个例子中,我希望在程序执行结束之前在命令行上看到“hi”的输出,因为OutputDataReceived事件应该已经被触发了。
我尝试过使用其他可执行文件- java.exe,git.exe等。所有这些都有同样的效果,所以我只能认为有一些简单的东西我不理解或错过了。异步读取stdout还需要做什么?
7条答案
按热度按时间6qftjkof1#
我遇到了这个线程,并想分享我的解决方案,为任何人可能需要在未来。这是在PowerShell Core 7.3.4上运行的。
示例1:常规使用
示例2:逗号分隔的参数
实施例3:通过使用
示例4:错误示例
kmpatx3s2#
不幸的是,如果你想正确地进行异步阅读,并不是那么容易。如果你调用WaitForExit()而不超时,你可以使用类似我写的这个函数(基于C#代码):
它捕获stdout、stderr和退出代码。示例用法:
有关更多信息和替代实现(在C#中),请阅读this blog post。
j8ag8udp3#
基于Alexander Obersht's answer,我创建了一个函数,它使用超时和异步Task类而不是事件处理程序。根据Mike Adelson
不幸的是,此方法(事件处理程序)无法知道何时收到最后一位数据。因为一切都是异步的,所以在WaitForExit()返回之后,事件有可能被触发(我观察到了这一点)。
5n0oy7gb4#
我无法让这些例子中的任何一个在PS4.0上工作。
我想从Octopus Deploy包(通过
Deploy.ps1
)运行puppet apply
,并“真实的”查看输出,而不是等待过程完成(一个小时后),所以我想出了以下方法:感谢T30和Stefan Goßner
ars1skjm5#
这里的例子都很有用,但并不完全适合我的用例。我不想调用命令并退出。我想打开一个命令提示符,发送输入,读取输出,然后重复。这是我的解决方案。
创建Utils.CmdManager.cs
然后从PowerShell中添加该类并使用它。
不要忘记在最后调用
Dispose()
函数来清理在后台运行的进程。或者,您可以通过运行类似$cmd.RunCommand("exit")
的程序来关闭该进程rta7y2nd6#
我来到这里寻找一个解决方案,创建一个 Package 器,记录过程,并将其输出到屏幕。这些对我都不起作用。我做了这个代码,看起来工作得很好。
PSDataCollection允许您继续执行脚本,而不必等待进程完成。
vd2z7a6w7#
如果你只是想动态地将其转储到PowerShell控制台,请执行以下操作:
my.exe | Out-Default
我不能说我已经弄明白了。
请看这篇Technet文章的底部:https://social.technet.microsoft.com/Forums/windowsserver/en-US/b6691fba-0e92-4e9d-aec2-47f3d5a17419/start-process-and-redirect-output-to-powershell-window?forum=winserverpowershell
它也指this stackoverflow post。
$LASTEXITCODE也填充了我的exe的退出代码,这也是我所需要的。