Powershell 无法从Get-PSDrive捕获DriveNotFoundException
在以下示例中,我无法捕获由Powershell 无法从Get-PSDrive捕获DriveNotFoundException,powershell,Powershell,在以下示例中,我无法捕获由Get PSDrive生成的DriveNotFoundException: try { # Assumes no Q:\ drive connected. $foo = Get-PSDrive -name 'Q' -ErrorAction Stop } catch [System.Management.Automation.DriveNotFoundException] { Write-Output "Drive not found." } ca
Get PSDrive
生成的DriveNotFoundException
:
try {
# Assumes no Q:\ drive connected.
$foo = Get-PSDrive -name 'Q' -ErrorAction Stop
}
catch [System.Management.Automation.DriveNotFoundException] {
Write-Output "Drive not found."
}
catch {
Write-Output "Something else went wrong."
}
应打印以下内容:
PS C:\temp> .\foo.ps1
Drive not found.
PS C:\temp>
相反,我得到:
PS C:\temp> .\foo.ps1
Something else went wrong.
PS C:\temp>
如果相关的话,我正在使用Powershell 2.0。我意识到这是由于一些奇怪的行为(根据上面对Powershell更高版本的评论),但这确实能够处理特定错误:
try {
$foo = Get-PSDrive -name 'Q' -ErrorAction Stop
}
catch {
if ($Error[0].Exception.GetType().Name -eq 'DriveNotFoundException') {
Write-Output 'No such drive.'
}
else {
Write-Output 'Something else went wrong.'
}
}
问题是因为
-ErrorAction Stop
正在更改try/catch块看到的异常类型
您可以通过捕获ActionPreferenceStopException
类型来证明这一点。因此,让我们运行一些疑难解答代码,看看发生了什么:
try {
# Assumes no Q:\ drive connected.
$foo = Get-PSDrive -name 'Q' -ErrorAction Stop
}
catch [System.Management.Automation.DriveNotFoundException] {
Write-Output "Drive not found."
}
catch [System.Management.Automation.ActionPreferenceStopException] {
Write-Output "Stop Exception."
write-host "Caught an exception:" -ForegroundColor Red
write-host "Exception Type: $($_.Exception.GetType().FullName)" -ForegroundColor Red
write-host "Exception Message: $($_.Exception.Message)" -ForegroundColor Red
}
catch
{
write-host "Caught an exception:" -ForegroundColor Red
write-host "Exception Type: $($_.Exception.GetType().FullName)" -ForegroundColor Red
write-host "Exception Message: $($_.Exception.Message)" -ForegroundColor Red
}
这将返回以下输出:
Stop Exception.
Caught an exception:
Exception Type: System.Management.Automation.DriveNotFoundException
Exception Message: Cannot find drive. A drive with the name 'Q' does not exist.
因此,您可以看到try/catch捕获了[System.Management.Automation.ActionPreferenceStopException]
异常,即使异常类型是catch块中的[System.Management.Automation.DriveNotFoundException]
因此,我们可以使用@haliphax解决方案的稍微修改版本来处理它,即检查ActionPreferenceStopException
catch块中的错误类型:
try {
# Assumes no Q:\ drive connected.
$foo = Get-PSDrive -name 'Q' -ErrorAction Stop
}
catch [System.Management.Automation.ActionPreferenceStopException] {
if ($Error[0].Exception.GetType().Name -eq 'DriveNotFoundException') {
Write-Output "Drive not found."
}
else {
Write-Output "Something else went wrong."
}
}
catch {
Write-Output "Something else went wrong."
}
这只是我使用的代码的最终版本的一篇简短文章,基于@HAL9256在中提供的解释: 这已经在PowerShell 2.0和4.0上进行了测试,并且在这两个版本上都有效。我假设在PowerShell 2.0环境中的
Get PSDrive
语句中会发生一些other异常,从而触发catch
块的风险很小,但在我的用例中,这是一个可接受的风险,稍后会在脚本中触发另一个异常。补充:
注:以下部分是推测性的。如果我错了,一定要告诉我
- 观察到的行为是一个可能是PowerShell v1和v2中的一个bug,其中类型为
在[System.Management.Automation.ActionPreferenceStopException]的内部异常
语句中键入的try/catch
块的匹配逻辑中意外地屏蔽了原始异常catch
- 我怀疑
纯粹是一个不应该公开的内部异常的原因是[System.Management.Automation.ActionPreferenceStopException]
及其在$Error[0]。异常
块中的别名,catch
反映了原始异常,即使在PowerShell v1和v2中,$\ucode>异常
集合也不包含$Errors
的跟踪[System.Management.Automation.ActionPreferenceStopException]
- 虽然在v3+
捕获处理程序中的[System.Management.Automation.ActionPreferenceStopException]
匹配,大概是为了不破坏向后兼容性
鉴于其一般性质(它只是告诉您cmdlet遇到了非终止错误),捕获[System.Management.Automation.ActionPreferenceStopException]
几乎没有什么好处
- 捕获它的唯一可能的原因是,如果您想知道手头的异常是本机终止的,还是仅由于
或-ErrorAction Stop
而被视为终止的$ErrorActionPreference='Stop'
try {
# Assumes no Q:\ drive connected.
$foo = Get-PSDrive -name 'Q' -ErrorAction Stop
}
catch { # Use a generic handler to work around the bug in v1 an v2.
# $_ is the [System.Management.Automation.ErrorRecord] instance representing
# the PowerShell error at hand (same as $Error[0]).
# $_.Exception contains the exception that triggered the error,
# and can be compared to specific exception types with -is.
if ($_.Exception -is [System.Management.Automation.DriveNotFoundException]) {
"Drive not found."
} else {
"Something else went wrong."
}
}
这在4.0上适用于我。不知道异常类型在2.0版上是否不同是的,在5.0版中可以正常工作。谢谢。你们都证明了我不是疯子。我看不出这不起作用的任何原因。不幸的是,一些将要运行这个特定脚本的服务器已经安装了2.0,所以我不得不用最小公分母来编写它。感谢您对发生的事情的解释。那么,鉴于编写的原始代码在更高版本的Powershell中正常工作,这是v2特有的吗?我几乎无法控制脚本将在任何机器上运行的版本,但我知道它的范围是2到4。如果在PS的更高版本上,异常被作为
DriveNotFoundException
抛出,我可能需要使用一个裸catch
来检查错误,因为这样做会让我很痛苦。很棒的侦察。假设$Error[0].Exception
(或$\u0.Exception
在catch
处理程序中)包含原始异常,即使在PS v2-,您如何确定[System.Management.Automation.ActionPreferenceStopException]
是匹配的?
try {
# Assumes no Q:\ drive connected.
$foo = Get-PSDrive -name 'Q' -ErrorAction Stop
}
catch { # Use a generic handler to work around the bug in v1 an v2.
# $_ is the [System.Management.Automation.ErrorRecord] instance representing
# the PowerShell error at hand (same as $Error[0]).
# $_.Exception contains the exception that triggered the error,
# and can be compared to specific exception types with -is.
if ($_.Exception -is [System.Management.Automation.DriveNotFoundException]) {
"Drive not found."
} else {
"Something else went wrong."
}
}