[英]How to handle errors in a way that works the same whether the script runs in “regular” powershell console or in powershell ISE?
我有這個簡單的腳本:
$ErrorActionPreference = "Stop"
try
{
cmd /c mklink a .\DataSvc.sln
}
catch
{
"Failed"
}
(文件DataSvc.sln存在)
當我在ISE powershell控制台中運行它時,它會顯示“失敗”,而當我從“常規” powershell控制台中進行操作時,它會顯示“您沒有足夠的特權執行此操作”。
ISE:
定期:
在兩種情況下,我應該如何編寫它以便打印“失敗”?
編輯1
您必須在Windows 10開發人員模式關閉的情況下以普通帳戶(不是提升帳戶)身份運行它。 如果您不知道什么是Windows 10開發人員模式,則可以(針對此問題)。
不幸的是,不同的主機對外部程序的 stderr輸出進行不同的處理。
ISE將stderr輸出路由到PowerShell自己的錯誤流,這解釋了為什么寫入stderr的任何內容都會觸發try
/ catch
處理程序。
常規控制台會將stderr輸出修補到控制台 ,在這種情況下,不會觸發任何錯誤。
由於存在錯誤 ,您當前(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輸出的存在來推斷出失敗-例如,由於某些程序無法正確反映其退出代碼中的失敗-您可以嘗試以下方法,該方法現在和之后都適用上述錯誤已修復:
$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
在一個變量中收集命令的錯誤輸出,但是在調用外部程序時沒有類似的機制。 但是,在此GitHub問題中提出了引入這種機制的建議。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.