【问题标题】:Powershell ISE wrongly interprets openssl.exe normal output as errorPowershell ISE 错误地将 openssl.exe 正常输出解释为错误
【发布时间】:2015-10-05 14:30:30
【问题描述】:

我正在尝试在 PowerShell ISE 中调试脚本,但我遇到了一个问题,即一行的正常输出被 ISE 解释为错误

我已经能够简化此问题的重现: 我在https://www.openssl.org/related/binaries.html 获得了任何版本的openssl(我使用来自链接存储库http://slproweb.com/products/Win32OpenSSL.html 的1.0.2d x86 对此进行了测试)

我打开 Powershell ISE,导航到 exe 所在的位置并运行以下命令:

$ErrorActionPreference = "Stop"
$env:OPENSSL_CONF = ((Resolve-Path "openssl.cfg").Path)
&openssl.exe genrsa

输出是红色的,开始是这样的:

openssl.exe : Loading 'screen' into random state - done
At line:1 char:1
+ &C:\Trayport\OpenSsl\openssl.exe genrsa
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (Loading 'screen...om state - done:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError

Generating RSA private key, 2048 bit long modulus

如果我在普通的 PowerShell 命令窗口中运行它,输出是一样的,但是是白色的,不被认为是错误

Loading 'screen' into random state - done
Generating RSA private key, 2048 bit long modulus

我尝试过使用 2>&1 或使用 ErrorPreference 参数封装调用(如 PowerShell ISE throws an error on git checkout 中所建议的那样),但仍然失败

尝试/捕获所有异常确实有效,但如果可以避免,我宁愿不这样做。

我尝试过使用 PowerShell 3.0 和 4.0 版

编辑:如果您使用$ErrorActionPreference = "SilentlyContinue",它确实会消除错误,但随后您将无法访问输出,而且合法问题也会消失

【问题讨论】:

标签: powershell openssl powershell-3.0 powershell-ise powershell-4.0


【解决方案1】:

Powershell 将任何转储到错误通道中的错误解释为发生在应用程序端的错误,因此它会停止该点之后的脚本。您应该在调用openssl.exe 的行中添加2>&1,以便Powershell 不会捕获应用程序的标准错误并将其解释为实际错误。

$ErrorActionPreference = "Stop"
$env:OPENSSL_CONF = ((Resolve-Path "openssl.cfg").Path)
& openssl.exe genrsa 2>&1

更新:这是无法治愈的,Powershell ISE 确实将标准错误通道拦截到Write-Error 并触发停止。有一个解决方法here,包括将生成错误通道输出的外部应用程序包装到一个脚本块中,本地覆盖为$ErrorActionPreference,如下所示:

& { 
  $ErrorActionPreference='silentlycontinue'
  openssl.exe genrsa 2>&1 
}

【讨论】:

  • 我试过这个,但它并没有改变任何东西。消息 openssl.exe 输出根本不在错误通道上。它们只是普通的消息。
  • 是的,有问题。 openssl.exe 确实会生成 std​​err 数据,并且 ISE 确实会在重定向之前捕获它……进一步思考。
  • 这是很常见的事情。例如 psexec 使用 std err 作为启动程序时出现的横幅
  • $ErrorActionPreference='silentlycontinue' 不会阻止标准错误消息的吞咽。
【解决方案2】:

我找到了一个可行的解决方案。

正如问题编辑中所指定的,设置$ErrorActionPreference = "SilentlyContinue" 是一个错误的解决方案,因为在这种情况下,PowerShell 等同于吞噬所有错误,并且它还删除了对进程实际输出的访问. 但是,在使用实际返回合法错误的命令的参数进行测试时,我注意到在这种情况下,我会得到一个非 0 $LASTEXITCODE(请注意任何有类似问题的人:这实际上是特定于 openssl.exe,您调用的任何应用程序都可能不是这种情况)。

所以我决定依靠进程退出代码来决定是否应该将 stderr 视为实际错误。

Capturing standard out and error with Start-Process 给出了一个保持进程输出存活的解决方案,所以:

$processStartInfo = New-Object System.Diagnostics.ProcessStartInfo
$processStartInfo.FileName = "openssl.exe"
$processStartInfo.RedirectStandardError = $true
$processStartInfo.RedirectStandardOutput = $true
$processStartInfo.UseShellExecute = $false
$processStartInfo.Arguments = "genrsa"
$process = New-Object System.Diagnostics.Process
$process.StartInfo = $processStartInfo
$process.Start() | Out-Null
$process.WaitForExit()
$standardError = $process.StandardError.ReadToEnd()
if ($process.ExitCode) {
   Write-Error $standardError
} else {
   Write-Host $standardError
}

【讨论】:

    【解决方案3】:
    Invoke-Expression ".\openssl.exe req -new -nodes -out c:\test\certs\rui.csr -keyout c:\test\certs\rui.key -config c:\test\certs\esxi.cfg" 2>&1
    

    From here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-08
      • 2012-07-09
      • 1970-01-01
      • 1970-01-01
      • 2021-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多