错误时跳过脚本的一部分

时间:2018-06-29 00:08:55

标签: powershell if-statement foreach active-directory try-catch

在这上面我已经将头撞墙了一段时间了。迄今为止,没有多少谷歌搜索为我带来任何成功的结果。想知道有人可以帮我吗?

# Load the PowerShell module for Active Directory
Import-Module ActiveDirectory

# For each computer in AD that is a member of the target group
Get-ADGroupMember -Identity "CN=RenameComputer,CN=Users,DC=int,DC=example,DC=com" | ForEach {

        # Define the new name as the old one, minus one letter at the end
        $NewComputerName = $_.Name -replace ".$"

        # Perform the rename operation
        Rename-Computer -ComputerName $_.Name -NewName $NewComputerName -Force -PassThru -Restart -WhatIf

        # Remove the computer from the target group
        # THIS SHOULD NOT OCCUR IF THE RENAME ABOVE FAILED!!!
        Remove-ADGroupMember -Identity "CN=RenameComputer,CN=Users,DC=int,DC=example,DC=com" -Members $NewComputerName -WhatIf

}

TL; DR::该脚本在指定组中查找一堆计算机,对其进行重命名,然后将其从该组中删除。我需要帮助告诉脚本在重命名失败(计算机处于脱机状态等)或引发某些错误的情况下,不要将其从组中删除。

有想法吗?

谢谢!

1 个答案:

答案 0 :(得分:5)

有几种方法可以在Powershell中检查cmdlet的结果。

将cmdlet作为if语句条件运行

您可以将cmdlet的返回对象用作if语句条件,只要它在成功时返回一个对象(这就是为什么我们需要-PassThru用于Rename-Computer的原因,通常不会返回任何对象)。因此,以您的代码为例(并删除-WhatIf):

# If Rename-Computer succeeds...
if( Rename-Computer -ComputerName $_.Name `
  -NewName $NewComputerName -Force -PassThru -Restart ) {

  # then remove the Computer from group 
  Remove-ADGroupMember -Identity "CN=RenameComputer,CN=Users,DC=int,DC=example,DC=com" `
   -Members $NewComputerName

}

之所以可行,是因为对象在Powershell中是真实的。大多数定义的对象和0(零)以外的任何数字都被认为是$True,但是诸如$null""(空字符串)和0之类的值(零)被评估为$False。因此,对于您的代码,如果成功,将返回一个对象($True),如果发生错误,将不返回任何对象($ False)。

明确检查cmdlet结果

或者,您可以先运行Rename-Computer,然后检查其成功:

Rename-Computer -ComputerName $_.Name -NewName $NewComputerName -Force

# Check success of last cmdlet
if( $? ) {
  Remove-ADGroupMember -Identity "CN=RenameComputer,CN=Users,DC=int,DC=example,DC=com" `
   -Members $NewComputerName
}

$?评估上一次cmdlet运行的成功(不要将此与$LASTEXITCODE混淆,后者用于检查上次运行的程序结果,而不是cmdlet结果)。如果该cmdlet成功,则返回$True,否则返回$False

Try/Catch块中捕获错误

第三种方法是使用try/catch块,尽管您必须确保终止任何错误(如果未被捕获,则将停止脚本)以捕获异常。您可以为此使用-ErrorAction Stop参数:

    try {

      Rename-Computer -ComputerName $_.Name -NewName $NewComputerName -Force `
        -PassThru -Restart -ErrorAction Stop

      Remove-ADGroupMember -Identity "CN=RenameComputer,CN=Users,DC=int,DC=example,DC=com" `
        -Members $NewComputerName

    } catch {
      # Do something on failure
      Write-Warning "An error occurred: $($_.Exception.Message)"
    }

如果Rename-Computertry块内引发错误(错误将失败),则执行将跳至catch块,并跳过Remove-ADGroupMember。如果使用try/catch是首选的错误处理方法,则可以考虑在脚本中设置$ErrorActionPreference = 'Stop',这会将默认的-ErrorAction行为设置为Stop,而您没有不必在每个cmdlet上都指定它。

其他信息

以下是有关Powershell中try/catch/finallyif语句的一些官方文档。我没有在上面介绍finally,但这是try/catch语句的可选部分:

关于If https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_if?view=powershell-6

关于尝试/捕获/最终https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_try_catch_finally?view=powershell-6

以下是有关异常,错误以及在Powershell中处理它们的一些高级信息https://kevinmarquette.github.io/2017-04-10-Powershell-exceptions-everything-you-ever-wanted-to-know/