带有 Invoke-Expression 的 powershell 的 Stderr 和 stdout 没有输出或错误
Stderr and stdout for powershell with Invoke-Expression has no output or errors
我正在尝试从 运行 宁一个 java 过程中获取 stdout
和 stderr
,并且看到了一种看起来很简单、很酷的方法,但它没有用:
$command = "java -jar secretserver-jconsole.jar -s 123456 Password"
Invoke-Expression $command -OutVariable output -ErrorVariable errors
Write-Host "stdout: $output"
Write-Host "stderr: $errors"
$output
或 $errors
没有任何显示。
我现在正在使用:
$output = cmd /c $command
这确实让我得到了一些 stdout
,但它并不像我想要的 $error
消息那样理想。
我什至尝试过这种精心设计的方法,但它甚至似乎没有运行我想的那样returns几乎是即时的过程,而且我知道正常过程任务需要几秒钟。它还显示没有输出或错误:
$psi = New-object System.Diagnostics.ProcessStartInfo
$psi.CreateNoWindow = $true
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError = $true
$psi.FileName = 'java'
$psi.Arguments = @("-jar","secretserver-jconsole.jar","-
s","123456","Password")
$process = New-Object System.Diagnostics.Process
$process.StartInfo = $psi
[void]$process.Start()
$output = $process.StandardOutput.ReadToEnd()
$process.WaitForExit()
Write-Host "stdout: $output"
(tried: adding:
do
$process.StandardOutput.ReadLine()
}
while (!$process.HasExited)
注意:下面的解决方案假定一个行为良好的外部实用程序:将 data 发送到 stdout 的实用程序, 错误消息到stderr。如果给定的实用程序意外地将错误消息发送到 stdout,就像 OP 的情况一样,您必须自己解析 stdout 输出以提取错误消息。
$stdout = java -jar secretserver-jconsole.jar -s 123456 Password 2>($tmpFile=New-TemporaryFile)
$stderr = Get-Content $tmpFile; Remove-Item $tmpFile
New-TemporaryFile
需要 PSv5,但您可以在早期版本中使用 [io.path]::GetTempFileName()
。
请注意,$stdout
和 $stderr
都将包含一个字符串 数组 ,每个项目代表一个输出行。
外部实用程序的 退出代码 反映在 PowerShell 的自动 $LASTEXITCODE
变量中。
请注意,捕获 stdout 和 stderr 组合 实际上更容易:
$stdoutAndStdErr = java -jar secretserver-jconsole.jar -s 123456 Password 2>&1
注意:每个 stderr 行在结果中都表示为一个 [System.Management.Automation.ErrorRecord]
实例,但它们的计算结果为 contents字符串上下文。
至于你尝试了什么:
通常不需要将命令存储在 字符串 中(因此很少需要使用 Invoke-Expression
,其使用可能有风险)。
- 或者:直接调用外部命令行(注意 PowerShell 可能不需要的命令行解释;在 PSv3 中,
--%
关闭 PowerShell 的解释 - 参见 Get-Help about_Parsing
),
- 或者,如果您需要先将命令存储在变量中,请使用 脚本块 (
$cmd = { ... }
),稍后使用 [=22= 调用它](调用运算符)或 .
(点源运算符)- 前者为 PS 变量创建子作用域,后者则没有。
-OutVariable
和 -ErrorVariable
通用参数仅设计用于 PowerShell 的 输出流,而不是外部世界的 stdout 和 stderr。
PowerShell 捕获 stdout 输出,就好像它已被发送到 PowerShell 的成功输出流一样,并将输出行视为 字符串数组 .
Stderr 输出被传递(并且未反映在 $Error
中),但您可以将其重定向到带有 2>$file
的文件,或者您可以将其合并到2>&1
的成功流(在这种情况下,每个 stderr 行都表示为一个 [System.Management.Automation.ErrorRecord]
实例)。
我正在尝试从 运行 宁一个 java 过程中获取 stdout
和 stderr
,并且看到了一种看起来很简单、很酷的方法,但它没有用:
$command = "java -jar secretserver-jconsole.jar -s 123456 Password"
Invoke-Expression $command -OutVariable output -ErrorVariable errors
Write-Host "stdout: $output"
Write-Host "stderr: $errors"
$output
或 $errors
没有任何显示。
我现在正在使用:
$output = cmd /c $command
这确实让我得到了一些 stdout
,但它并不像我想要的 $error
消息那样理想。
我什至尝试过这种精心设计的方法,但它甚至似乎没有运行我想的那样returns几乎是即时的过程,而且我知道正常过程任务需要几秒钟。它还显示没有输出或错误:
$psi = New-object System.Diagnostics.ProcessStartInfo
$psi.CreateNoWindow = $true
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError = $true
$psi.FileName = 'java'
$psi.Arguments = @("-jar","secretserver-jconsole.jar","-
s","123456","Password")
$process = New-Object System.Diagnostics.Process
$process.StartInfo = $psi
[void]$process.Start()
$output = $process.StandardOutput.ReadToEnd()
$process.WaitForExit()
Write-Host "stdout: $output"
(tried: adding:
do
$process.StandardOutput.ReadLine()
}
while (!$process.HasExited)
注意:下面的解决方案假定一个行为良好的外部实用程序:将 data 发送到 stdout 的实用程序, 错误消息到stderr。如果给定的实用程序意外地将错误消息发送到 stdout,就像 OP 的情况一样,您必须自己解析 stdout 输出以提取错误消息。
$stdout = java -jar secretserver-jconsole.jar -s 123456 Password 2>($tmpFile=New-TemporaryFile)
$stderr = Get-Content $tmpFile; Remove-Item $tmpFile
New-TemporaryFile
需要 PSv5,但您可以在早期版本中使用 [io.path]::GetTempFileName()
。
请注意,$stdout
和 $stderr
都将包含一个字符串 数组 ,每个项目代表一个输出行。
外部实用程序的 退出代码 反映在 PowerShell 的自动 $LASTEXITCODE
变量中。
请注意,捕获 stdout 和 stderr 组合 实际上更容易:
$stdoutAndStdErr = java -jar secretserver-jconsole.jar -s 123456 Password 2>&1
注意:每个 stderr 行在结果中都表示为一个 [System.Management.Automation.ErrorRecord]
实例,但它们的计算结果为 contents字符串上下文。
至于你尝试了什么:
通常不需要将命令存储在 字符串 中(因此很少需要使用 Invoke-Expression
,其使用可能有风险)。
- 或者:直接调用外部命令行(注意 PowerShell 可能不需要的命令行解释;在 PSv3 中,
--%
关闭 PowerShell 的解释 - 参见Get-Help about_Parsing
), - 或者,如果您需要先将命令存储在变量中,请使用 脚本块 (
$cmd = { ... }
),稍后使用 [=22= 调用它](调用运算符)或.
(点源运算符)- 前者为 PS 变量创建子作用域,后者则没有。
-OutVariable
和 -ErrorVariable
通用参数仅设计用于 PowerShell 的 输出流,而不是外部世界的 stdout 和 stderr。
PowerShell 捕获 stdout 输出,就好像它已被发送到 PowerShell 的成功输出流一样,并将输出行视为 字符串数组 .
Stderr 输出被传递(并且未反映在
$Error
中),但您可以将其重定向到带有2>$file
的文件,或者您可以将其合并到2>&1
的成功流(在这种情况下,每个 stderr 行都表示为一个[System.Management.Automation.ErrorRecord]
实例)。