在使用 Invoke-Expression 命令执行 PowerShell 时,标准错误流(Stderr)和标准输出流(Stdout)没有任何输出或错误。

16 浏览
0 Comments

在使用 Invoke-Expression 命令执行 PowerShell 时,标准错误流(Stderr)和标准输出流(Stdout)没有任何输出或错误。

我正试图从运行的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消息。

我甚至尝试了这种复杂的方法,但它似乎甚至没有运行我认为的进程,因为返回几乎是瞬间的,而我知道正常的进程需要几秒钟。它也没有显示任何输出或错误:

$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"

(尝试:添加:

do

$process.StandardOutput.ReadLine()

}

while (!$process.HasExited)

0
0 Comments

问题原因:外部工具发送错误消息到stdout而不是stderr。

解决方法:

1. 使用以下代码将stdout和stderr分别存储到变量中:

$stdout = java -jar secretserver-jconsole.jar -s 123456 Password 2>($tmpFile=New-TemporaryFile)
$stderr = Get-Content $tmpFile; Remove-Item $tmpFile

注意,$stdout和$stderr将包含一个字符串数组,每个条目表示一行输出。

2. 使用以下代码将stdout和stderr合并到一个变量中:

$stdoutAndStdErr = java -jar secretserver-jconsole.jar -s 123456 Password 2>&1

注意,合并后的stdout和stderr将作为字符串的数组表示。

补充说明:

- 外部工具的退出码可以通过PowerShell的自动变量$LASTEXITCODE获取。

- 使用-OutVariable和-ErrorVariable参数只能捕获PowerShell的输出流,而无法捕获外部工具的stdout和stderr。

- 如果外部工具发送错误消息到stdout而不是stderr,需要自己解析stdout输出以提取错误消息。

出现问题的原因是使用Invoke-Expression命令存储命令字符串并执行。实际上,可以直接执行外部命令,并使用字符串数组或脚本块存储命令。

文章结束。

0