我有这个简单的脚本:
$ErrorActionPreference = "Stop"
try
{
cmd /c mklink a .\DataSvc.sln
}
catch
{
"Failed"
}
(文件DataSvc.sln存在)
当我在ISE powershell控制台中运行它时,它会显示“失败”,而当我从“常规” powershell控制台中进行操作时,它会显示“您没有足够的特权来执行此操作”。
ISE:
常规:
在两种情况下,我应该如何编写它以便打印“失败”?
编辑1
您必须在Windows 10开发人员模式关闭的情况下以普通帐户(不是提升帐户)身份运行它。如果您不知道什么是Windows 10开发人员模式,则可以(针对此问题)。
最佳答案
不幸的是,不同的主机对外部程序的stderr输出进行不同的处理。
try
/catch
处理程序。由于存在bug,您当前(Windows PowerShell v5.1/PowerShell Core v6.1)可以通过在PowerShell中重定向流号
2
来在控制台中触发错误:$ErrorActionPreference = "Stop"
try {
cmd /c 'echo tostderr >&2' 2>&1 # even 2>$null would trigger an error(!)
} catch {
"Failed"
}
但是,我不会依赖它,因为该错误可能会(而且希望会)得到修复。
退后一步:正如注释中的链接所暗示的那样,外部程序是否失败应该仅从其退出代码中得出,而不应从存在stderr输出中得出,因为许多程序使用stderr输出来报告错误以外的信息(例如作为诊断信息或仅作为警告)。
因此,应单独使用
if ($LASTEXITCODE -ne 0)
来确定失败。如果由于某种原因您确实需要根据stderr输出的存在来推断出失败-例如,由于某些程序无法正确地反射(reflect)其退出代码中的失败-您可以尝试以下方法,该方法现在和之后都适用前述错误已修复:
$ErrorActionPreference = "Stop"
try {
cmd /c 'echo tostderr >&2' 2>&1 | ForEach-Object {
if ($_ -is [System.Management.Automation.ErrorRecord]) { Throw $_ }
$_
}
} catch {
"Failed"
}
这依赖于将错误流合并到成功流中,然后根据其类型来检测源自stderr的行。
请注意,虽然在PowerShell内部,您可以使用公用参数
-ErrorVariable
/-ev
将变量的命令输出错误收集起来,但是在调用外部程序时没有类似的机制。但是,在this GitHub issue中提出了引入这种机制的建议。
关于powershell - 无论脚本是在 “regular” Powershell控制台还是在Powershell ISE中运行,如何以相同的方式处理错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51431975/