Powershell ISE 错误地将 openssl.exe 正常输出解释为错误
Powershell ISE wrongly interprets openssl.exe normal output as error
我正在尝试在 PowerShell ISE 中调试脚本,但我运行遇到一个问题,其中一行的正常输出被 ISE 解释为错误
我已经能够简化这个问题的重现:
我在 https://www.openssl.org/related/binaries.html (I tested this with 1.0.2d x86 from the linked repository http://slproweb.com/products/Win32OpenSSL.html)
获得了任何版本的 openssl
我打开 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 命令中执行此操作 window,输出是相同的,但为白色,不被视为错误
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 中所建议),但仍然失败
try/catching 所有异常都有效,但如果可以避免,我宁愿不这样做。
我尝试过使用 PowerShell 3.0 和 4.0 版
编辑:如果你使用 $ErrorActionPreference = "SilentlyContinue"
,它确实会消除错误,但你会失去对输出的访问权限,合法问题也会消失
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
}
我找到了可行的解决方案。
正如在对问题的编辑中指定的那样,设置 $ErrorActionPreference = "SilentlyContinue"
是一个有点错误的解决方案,因为在这种情况下 PowerShell 相当于吞下所有错误,并且它还删除了对实际的访问过程的输出。
但是,在使用实际上 return 合法错误的命令的参数进行测试时,我注意到在这种情况下我会得到一个非 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
}
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
我正在尝试在 PowerShell ISE 中调试脚本,但我运行遇到一个问题,其中一行的正常输出被 ISE 解释为错误
我已经能够简化这个问题的重现: 我在 https://www.openssl.org/related/binaries.html (I tested this with 1.0.2d x86 from the linked repository http://slproweb.com/products/Win32OpenSSL.html)
获得了任何版本的 openssl我打开 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 命令中执行此操作 window,输出是相同的,但为白色,不被视为错误
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 中所建议),但仍然失败
try/catching 所有异常都有效,但如果可以避免,我宁愿不这样做。
我尝试过使用 PowerShell 3.0 和 4.0 版
编辑:如果你使用 $ErrorActionPreference = "SilentlyContinue"
,它确实会消除错误,但你会失去对输出的访问权限,合法问题也会消失
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
}
我找到了可行的解决方案。
正如在对问题的编辑中指定的那样,设置 $ErrorActionPreference = "SilentlyContinue"
是一个有点错误的解决方案,因为在这种情况下 PowerShell 相当于吞下所有错误,并且它还删除了对实际的访问过程的输出。
但是,在使用实际上 return 合法错误的命令的参数进行测试时,我注意到在这种情况下我会得到一个非 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
}
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