Evr*_*glu 6 powershell openssl powershell-ise powershell-3.0 powershell-4.0
我正在尝试在 PowerShell ISE 中调试脚本,但我遇到了一个问题,其中一行的正常输出被 ISE 解释为错误
我已经能够简化这个问题的重现:我在https://www.openssl.org/related/binaries.html获得了任何版本的 openssl (我用 1.0.2d x86 来自链接存储库http:/ /slproweb.com/products/Win32OpenSSL.html )
我打开 Powershell ISE,导航到 exe 所在的位置并运行以下命令:
$ErrorActionPreference = "Stop"
$env:OPENSSL_CONF = ((Resolve-Path "openssl.cfg").Path)
&openssl.exe genrsa
Run Code Online (Sandbox Code Playgroud)
输出是红色的,开始是这样的:
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
Run Code Online (Sandbox Code Playgroud)
如果我在正常的 PowerShell 命令窗口中运行它,输出相同但为白色,不会被视为错误
Loading 'screen' into random state - done
Generating RSA private key, 2048 bit long modulus
Run Code Online (Sandbox Code Playgroud)
我曾尝试使用 2>&1 或使用 ErrorPreference 参数封装调用(如PowerShell ISE 中所建议的在git checkout 上抛出错误)但它仍然失败
尝试/捕获所有异常确实有效,但如果我可以避免它,我宁愿不这样做。
我曾尝试使用 PowerShell 3.0 和 4.0 版
编辑:如果您使用$ErrorActionPreference = "SilentlyContinue",它确实会消除错误,但是您将无法访问输出,并且合法问题也会消失
Powershell 将任何到错误通道的转储解释为应用程序端发生的错误,因此它会停止该点之后的脚本。您应该添加2>&1调用 的行openssl.exe,以便 Powershell 不会捕获应用程序的标准错误并将其解释为实际错误。
$ErrorActionPreference = "Stop"
$env:OPENSSL_CONF = ((Resolve-Path "openssl.cfg").Path)
& openssl.exe genrsa 2>&1
Run Code Online (Sandbox Code Playgroud)
更新:这是无法治愈的,Powershell ISE 确实会拦截标准错误通道Write-Error并触发停止。这里有一个解决方法,包括将生成错误通道输出的外部应用程序包装到具有本地覆盖的脚本块中$ErrorActionPreference,如下所示:
& {
$ErrorActionPreference='silentlycontinue'
openssl.exe genrsa 2>&1
}
Run Code Online (Sandbox Code Playgroud)
我找到了一个可行的解决方案。
正如问题编辑中所指定的,设置$ErrorActionPreference = "SilentlyContinue"是一个有点错误的解决方案,因为在这种情况下,PowerShell 相当于吞下了所有错误,并且它还删除了对进程实际输出的访问。但是,在使用实际上会返回合法错误的命令参数进行测试时,我注意到在这种情况下我会得到一个非 0 $LASTEXITCODE (请注意任何有类似问题的人:这实际上特定于 openssl.exe,无论您调用哪个应用程序,情况都可能并非如此)。
因此,我决定依靠进程退出代码来决定是否应该将 stderr 视为实际错误。
使用 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
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3115 次 |
| 最近记录: |