问题描述
从一个 powershell 脚本(安装了 nuget
并在路径上),我试图执行一个可执行文件(.net,如果这很重要)......但出于某种原因,我可以不让 STDOUT 显示在命令窗口中.
From a powershell script (with nuget
installed and on the path), I'm trying to execute an executable (.net, if that matters) ... but for some reason, I can't get the STDOUT to display in the command window.
nuget install mdoc -OutputDirectory packages -ExcludeVersion
start-process "packages/mdoc/tools/mdoc.exe" "--version"
echo "done"
这应该输出 mdoc 5.7.2
(在本文发布时,当前版本).但是你会看到 nuget 输出,然后 done
.
This should output mdoc 5.7.2
(at the time of this post, current version). But you'll see the nuget output, then done
.
关于为什么这不显示的任何想法?
Any thoughts on why this is not showing up?
推荐答案
正如 Ansgar 的评论所暗示的:在 Windows 上,Start-Process
在新的控制台窗口中运行控制台程序默认情况下,异步.
As Ansgar's comment implies: On Windows, Start-Process
runs console programs in a new console window by default, asynchronously.
如果该程序快速完成,您可能会看到新的控制台窗口只是短暂闪烁,因为它随后很快就会打开和关闭,或者您可能完全错过了闪烁 - 无论哪种方式,它的输出都不会显示在调用者的 控制台窗口.
If that program completes quickly, you may see the new console window flash only briefly, as it opens and closes soon thereafter, or you may miss the flash altogether - either way, its output will not show in the caller's console window.
退一步:如果您想同步运行控制台程序,并且其标准流连接到,请不要使用Start-Process
PowerShell 的流 - 只需直接调用这样的程序:
Taking a step back: Do not use Start-Process
if you want to run a console program synchronously, with its standard streams connected to PowerShell's streams - just invoke such a program directly:
packages/mdoc/tools/mdoc.exe --version
如果外部程序的路径/名称必须引用(因为它的路径包含空格)和/或它存储在变量中,只需使用&
,调用运算符,调用它:
If the external program's path / name must be quoted (because its path contains spaces) and/or it is stored in a variable, simply use &
, the call operator, to invoke it:
# Via a quoted string:
& "packages/mdoc/tools/mdoc.exe" --version
# Via a variable:
$exePath = "packages/mdoc/tools/mdoc.exe"
& $exePath --version
使用直接调用方法可让您免费同步执行,以及捕获和/或重定向被调用程序的 stdout 和 stderr 流的能力.
Using the direct-invocation approach gives you synchronous execution for free, as well as the ability to capture and/or redirect the invoked program's stdout and stderr streams.
把它们放在一起(根据你后来的评论):
To put it all together (based on your later comments):
nuget install mdoc -OutputDirectory packages -ExcludeVersion
$exePath = "packages/mdoc/tools/mdoc.exe"
& $exePath --version
"done"
这将打印版本号 - mdoc 5.7.2
截至撰写本文时 - 就在打印 done
之前(在 Microsoft Windows 10 上的 Windows PowerShell v5.1.17134.48 上验证)专业版(64 位;版本 1709,操作系统版本:16299.371)).
This prints the version number - mdoc 5.7.2
as of this writing - just before printing done
(verified on Windows PowerShell v5.1.17134.48 on Microsoft Windows 10 Pro (64-bit; Version 1709, OS Build: 16299.371)).
可选阅读:捕获来自外部程序的 stdout/stderr 输出:
Optional reading: capturing stdout / stderr output from external programs:
要捕获stdout 输出,只需将调用分配给一个变量:
To capture stdout output, simply assign the call to a variable:
$version = & $exePath --version # $version receives stdout output as an *array of lines*
$version
如果只有 1 行输出,则接收字符串标量(单个字符串),或表示输出行的 array 字符串.
$version
receives either a string scalar (single string) if there was only 1 line of output, or an array of strings representing the output lines.
要同时捕获 stderr 输出,请使用重定向 2>&1
:
To also capture stderr output, use redirection 2>&1
:
[string[]] $allOutput = & $exePath --version 2>&1
注意对 [string[]]
的转换,这确保 stderr 行也被捕获为 strings.
Note the cast to [string[]]
, which ensures that the stderr lines are captured as strings too.
默认情况下,它们被捕获为
[System.Management.Automation.ErrorRecord]
实例,这在 Windows PowerShell 中会有些混乱地打印它们,好像它们PowerShell 错误 - 此问题已在 PowerShell Core 中修复.
By default, they are captured as
[System.Management.Automation.ErrorRecord]
instances, which in Windows PowerShell will somewhat confusingly print them as if they were PowerShell errors - this problem has been fixed in PowerShell Core.
相反,但是,如果不将返回的数组元素的类型转换为字符串,则可以使用 -is [System.Management.Automation.ErrorRecord] 检查每个元素
来确定它是源自 stdout 还是 stderr.
Conversely, however, if you don't convert the type of the elements of the array that is returned to strings, you can examine each element with -is [System.Management.Automation.ErrorRecord]
to determine whether it originated from stdout or stderr.
这篇关于Powershell 可执行文件未输出到 STDOUT的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!