解释PowerShell中的Try/Catch/Finally块
PowerShell中的**Try/Catch**块用于处理脚本中产生的错误。具体来说,这些错误应该是终止性错误。PowerShell中的**Finally**块并非每次都必须与**Try/Catch**一起使用,但无论是否发生错误,它都会执行。
因此,当使用**Try**块时,**Catch**块是必须的,但**Finally**块不是必须的。
带有终止性错误的Try/Catch块 - 下面是无Finally块的终止性错误示例。
示例
try{
This is not allowed
"This is Allowed"
}
catch{
Write-Host "Error occured" -BackgroundColor DarkRed
}输出
PS C:\WINDOWS\system32> try{
This is not allowed
"THis is allowed"
}
catch{
Write-Host "Error occured" -BackgroundColor Darkred
}
Error occured在上面的示例中,我们返回了一些不允许的内容,但下一行是正常的,尽管由于终止性错误而无法执行。
我们的目标是捕获Try块中生成的异常和错误消息。众所周知,错误存储在$Error变量中。如果你检查$error变量的输出,你可以看到整个视图,但是每当你运行任何脚本并处理错误时,请确保使用$error.clear()命令清除旧错误或使用新的PowerShell控制台。如果你知道错误变量在数组中的特定位置,可以直接使用它。例如,$error[2]
PS C:\WINDOWS\system32> $Error This : The term 'This' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At line:3 char:5 + This is not allowed + ~~~~ + CategoryInfo : ObjectNotFound: (This:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException
我们可以查看$Error变量的所有属性。
PS C:\WINDOWS\system32> $Error | Get-Member | Select Name, MemberType Name MemberType ---- ---------- Equals Method GetHashCode Method GetObjectData Method GetType Method ToString Method CategoryInfo Property ErrorDetails Property Exception Property FullyQualifiedErrorId Property InvocationInfo Property PipelineIterationInfo Property ScriptStackTrace Property TargetObject Property PSMessageDetails ScriptProperty
上面的一些属性有助于查找异常和错误详细信息。让我们看看它们,我们也可以在Catch块中利用它们。
首先是InvocationInfo属性。你也可以使用$Error[0],但这到目前为止是唯一生成的错误,所以我们直接使用$Error,但是你不能直接使用$error变量获得自动建议弹出窗口。
PS C:\WINDOWS\system32> $Error.InvocationInfo
MyCommand :
BoundParameters : {}
UnboundArguments : {}
ScriptLineNumber : 3
OffsetInLine : 5
HistoryId : 50
ScriptName :
Line : This is not allowed
PositionMessage : At line:3 char:5
+ This is not allowed
+ ~~~~
PSScriptRoot :
PSCommandPath :
InvocationName : This
PipelineLength : 0
PipelinePosition : 0
ExpectingInput : False
CommandOrigin : Internal
DisplayScriptPosition :你可以从Line和PositionMessage获取特定信息,如下所示。
PS C:\WINDOWS\system32> $Error.InvocationInfo.Line This is not allowed PS C:\WINDOWS\system32> $Error.InvocationInfo.PositionMessage At line:3 char:5 + This is not allowed + ~~~~
现在检查Exception属性。
PS C:\WINDOWS\system32> $Error.Exception The term 'This' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
异常消息
PS C:\WINDOWS\system32>$error.Exception.Message The term 'This' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
你可以使用你认为有助于显示错误消息的其他属性。我们将在Catch块中使用其中的一些来捕获错误。由于我们正在使用当前错误,我们将使用$_.来处理当前的**错误/异常**。
$error.clear()
try{
This is not allowed
"THis is allowed"
}
catch{
Write-Host "`nError Message: " $_.Exception.Message
Write-Host "`nError in Line: " $_.InvocationInfo.Line
Write-Host "`nError in Line Number: "$_.InvocationInfo.ScriptLineNumber
Write-Host "`nError Item Name: "$_.Exception.ItemName
}输出
Error Message: The term 'This' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. Error in Line: This is not allowed Error in Line Number: 3 Error Item Name:
正如我们在上面看到的,没有Finally块,Try/Catch仍然可以工作。你可以添加Finally块来清除你的变量和错误,并显示任何消息。
try{
This is not allowed
"THis is allowed"
}
catch{
Write-Host "`nError Message: " $_.Exception.Message
Write-Host "`nError in Line: " $_.InvocationInfo.Line
Write-Host "`nError in Line Number: "$_.InvocationInfo.ScriptLineNumber
Write-Host "`nError Item Name: "$_.Exception.ItemName
}
finally{
"This is going to run anyway"
$error.clear()
}带有非终止性错误的Try/Catch块。
正如我们在上面的示例中看到的,终止性错误可以用Try/Catch块控制,但非终止性错误不能,因为它们是内置cmdlet和函数生成的错误,并且**Error**操作的默认首选项是Continue,因此即使错误未被处理,下一个命令也会继续运行。
PS C:\WINDOWS\system32> $ErrorActionPreference Continue
要将非终止性错误强制转换为终止性错误,我们需要将$ErrorActionPreference变量更改为Stop,或者需要使用ErrorAction参数并将其值设置为Stop。在这里,我们将使用ErrorAction参数,因为我们只需要它用于特定命令,而不是整个脚本。
示例
$error.clear()
try{
Get-Service WhichService -ErrorAction Stop
}
catch{
Write-Host "`nError Message: " $_.Exception.Message
Write-Host "`nError in Line: " $_.InvocationInfo.Line
Write-Host "`nError in Line Number: "$_.InvocationInfo.ScriptLineNumber
Write-Host "`nError Item Name: "$_.Exception.ItemName
}
finally{
"This is going to run anyway"
$error.clear()
}输出
Error Message: Cannot find any service with service name 'WhichService'. Error in Line: Get-Service WhichService -ErrorAction Stop Error in Line Number: 4 Error Item Name: This is going to run anyway
正如你可以在上面的示例中看到的,Get-Service产生非终止性错误,我们可以通过–ErrorAction Stop参数将其转换为终止性错误,并且Catch块已捕获相同的异常。
手动处理特定异常
如果你想处理特定类型的异常,你可以在catch块中提供异常名称。要了解异常的名称,你需要获取$Error变量的属性,它是**GetType()**。在下面的示例中,我们需要从下面的错误输出中找到异常名称。
示例
PS C:\WINDOWS\system32> Test-Connection Remote-Computer -Count 1 -ErrorAction Stop Test-Connection : Testing connection to computer 'Remote-Computer' failed: No such host is known At line:1 char:4 + Test-Connection Remote-Computer -Count 1 -ErrorAction Stop + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ResourceUnavailable: (Remote-Computer:String) [Test-Connection], PingException + FullyQualifiedErrorId : TestConnectionException,Microsoft.PowerShell.Commands. TestConnectionCommand
假设你的错误存储在$Error[0]变量中,你需要运行以下命令来获取要在catch块中使用的异常名称。
$Error[0].Exception.GetType().FullName
PS C:\WINDOWS\system32> $Error[0].Exception.GetType().FullName System.Management.Automation.MethodInvocationException
你使用上面的命令获得了异常类型名称,你可以在catch块中使用相同的名称,这样catch块将只捕获该特定异常。
$error.clear()
try{
Test-Connection Remote-Computer -Count 1 -ErrorAction Stop
}
catch [System.Net.NetworkInformation.PingException]{
Write-Host $_.Exception.Message -BackgroundColor DarkRed
}输出
PS C:\WINDOWS\system32> $error.clear()
try{
Test-Connection Remote-Computer -Count 1 -ErrorAction Stop
}
catch [System.Net.NetworkInformation.PingException]{
Write-Host $_.Exception.Message -BackgroundColor DarkRed -NoNewline
}
Testing connection to computer 'Remote-Computer' failed: No such host is known捕获多个PowerShell异常。
你也可以在PowerShell中捕获多个异常。为此,你可以使用一个Try块和多个catch块。
示例
$error.clear()
$ErrorActionPreference = "Stop"
try{
Get-ItemProperty C:\temp\cominfo1.html
Test-Connection Remote-Computer -Count 1
}
catch [System.Management.Automation.ItemNotFoundException]{
Write-Host $_.Exception.Message -BackgroundColor DarkRed
}
catch [System.Net.NetworkInformation.PingException]{
Write-Host ""
Write-Host $_.Exception.Message -BackgroundColor DarkRed
}
Finally{
Write-Output "`nSetting up ErrorActionPreference to the Default value"
$ErrorActionPreference = "Continue"
}输出
Cannot find path 'C:\temp\cominfo1.html' because it does not exist. Setting up ErrorActionPreference to the Default value
在这里,在第一个命令本身就生成了错误,因此下一个命令将不会执行。如果第一个命令没有产生任何错误,则将检查下一个命令,如果发生异常,则将执行具有该特定异常块的Catch。
如果你不想处理多个异常,并且仍然需要忽略某些命令的错误,但这些错误不应该通过catch块,以便下一个命令可以执行,那么你可以在ErrorAction参数中使用Ignore或SilentlyIgnore。
数据结构
网络
关系数据库管理系统 (RDBMS)
操作系统
Java
iOS
HTML
CSS
Android
Python
C语言编程
C++
C#
MongoDB
MySQL
Javascript
PHP