【问题标题】:Powershell try/catch/finally isn't executing right (or I've completely hosed it)Powershell tr​​y/catch/finally 没有正确执行(或者我已经完全搞砸了)
【发布时间】:2017-07-11 15:53:26
【问题描述】:

我有一个检查循环组的脚本。
该脚本获取域中的所有组(父组),检查这些组的成员资格,并将 objectClass 为“组”的任何成员添加到数组(子组)中。

脚本然后检查子组以查看父组是否是子组的成员(是的,这是允许的,但仍然不是一个好主意)。

我添加了一个 try/catch/finally 块,因此我可以获得实际的组名,而不是 PowerShell 返回的截断错误消息。

问题是,脚本在遇到第一个错误时停止,而不是继续。

这是我第一次尝试/捕捉,所以请多多包涵。

这是脚本:

$original_ErrorActionPreference = 'Continue'
$ErrorActionPreference = 'Stop'

Import-Module -Name ActiveDirectory

$domains = @('corp.com', 'dom1.corp.com', 'dom2.corp.com')


foreach($domain in $domains){
  Write-Host $domain -ForegroundColor Yellow
  $parents = Get-ADGroup -server $domain -Properties name,objectclass -Filter * #get all domain groups
  write-host $parents.count

  $table = @()
  $pGroupCount = @($parents).Count

  $record = @{
    'Parent' = ''
    'Child' = ''
    'Nester' = ''
  }

  foreach($parent in $parents){ 
    Write-Host $parent.name -ForegroundColor Green

脚本运行到此为止。

这是失败的部分-

    try { #get members in the parent that are groups
      $children = Get-ADGroupMember -Identity $parent | Where-Object{$_.ObjectClass -eq 'group'} | Select-Object name,distinguishedName,objectClass  
      } catch [Microsoft.ActiveDirectory.Management.Commands.GetADGroupMember]{

        Write-Host $parent.name ' must be checked manually' -ForegroundColor blue -BackgroundColor Yellow
        $parent.distinguishedName | Out-String -Width 4096 | Out-File -FilePath "$env:USERPROFILE\desktop\$domain-manualCheck.txt" -Width 5120 -Append

    } finally {

    $pGroupCount = $pGroupCount - 1
    write-host $children.count ' - ' $children.name -ForegroundColor Gray
    Write-Host $pGroupCount ' groups to go' -foregroundColor yellow



  foreach($child in $children){ #get members in the children that are groups AND that have the same name as the parent
    $nested = Get-ADGroupMember $child.name | Where-Object {$_.objectClass -eq 'group' -and $_.name -eq $parent.name} 
    $nestedCount = @($nested).count

      if ($nestedCount -gt 0){
        foreach($nester in $nested){
          Write-Host $parent.name -ForegroundColor White
          Write-Host $nestedCount -ForegroundColor Magenta
          Write-Host $nester.name -ForegroundColor Cyan
          $record.'Parent' = $parent.name
          $record.'Child' = $child.name
          $record.'Nester' = $nester.name
          $objRecord = New-Object psobject -Property $record
          $table += $objRecord
        }
      }
    }
    $table | Export-Csv -Path "$env:USERPROFILE\desktop\$domain-Group-Report.csv" -NoTypeInformation
    $error | out-string -width 4096 | Out-File -FilePath "$env:USERPROFILE\desktop\$domain-Errors.txt" -Width 5120 -Append
  }
  }
  }
  $ErrorActionPreference = $original_ErrorActionPreference 

一旦脚本遇到问题的第一个组,就会返回以下错误(添加了#cmets):

PS C:\Users\admin_j\Desktop> .\gtest.ps1
corp.com #current domain
283 #total group count
Exchange Servers #current group
6  -  Exchange Install Domain Servers Exchange Install Domain Servers Exchange Install Domain Servers Exchange Install Domain Servers Exchange Install Domain Servers #6 groups within the parent, groups are from sub-domains
Exchange Install Domain Servers
282  groups to go
Get-ADGroupMember : Cannot find an object with identity: 'Exchange Install Domain Servers' under: 'DC=corp,DC=com'.
At C:\Users\admin_j\Desktop\gtest.ps1:46 char:15
+     $nested = Get-ADGroupMember $child.name | Where-Object $_.objectClass -eq ' ...
+               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Exchange Install Domain Servers:ADGroup) [Get-ADGroupMember], ADIdentityNotFoundException
    + FullyQualifiedErrorId : Cannot find an object with identity: 'Exchange Install Domain Servers' under: 'DC=corp,DC=com'.,Microsoft.ActiveDirectory.Management.Commands.GetADGroupMember

为什么脚本没有将坏组(在本例中为“DC=corp,DC=com”下的“Exchange 安装域服务器”)写入文件,而是停止了?该组确实存在。

我应该添加另一个块来捕获任何“找不到对象”错误并将它们发送到文件吗?

谢谢!

【问题讨论】:

  • catch [Microsoft.ActiveDirectory.Management.Commands.GetADGroupMember] 不。 caught 对象将是被抛出的异常。 GetADGroupMember 也不例外。您可以通过捕获 System.Exception 来进行概括,这可能对您有用。当您在 catch 中指定类型时,如果异常不是该类型,则不会执行 catch。你指定了一些永远不会被你调用的代码抛出的东西,所以你的 catch 块没有执行。您也可以跳过指定类型,以便它每次都执行。
  • @Will- 谢谢,这有帮助!我将类型更改为[Microsoft.ActiveDirectory.Management.ADIdentityNotFound],现在可以使用了。我还添加了另一个块来使用[Microsoft.ActiveDirectory.Management.ADException] 捕获一般错误。出于某种原因,我收到一个错误,即命令已在子数组中的最后一个元素上成功完成。

标签: powershell


【解决方案1】:

作为Will's comment implies,您确实通过指定与您期望抛出的异常不匹配的类型文字来破坏您的catch 子句。

catch 子句的一般语法如下

catch [catch-type-list] <statement block>

其中[catch-type-list] 是一个可选的异常类型列表,关联的语句块将充当异常处理程序。

也就是说,这个catch子句:

catch [Microsoft.ActiveDirectory.Management.Commands.GetADGroupMem‌​ber] {
    # ...
}

只会处理由 [Microsoft.ActiveDirectory.Management.Commands.GetADGroupMem‌​ber] 类型的异常引起的错误 - 这当然不是异常类型,因此相关的语句块永远不会执行。

为了使您的 catch 子句在此上下文中有意义,请指定相关的异常类型:

try{
    Get-ADGroupMember -Identity $parent
}
catch [Microsoft.ActiveDirectory.Management.ADServerDownException]{
    # DC is unreachable, abort
}
catch [Microsoft.ActiveDirectory.Management.ADIdentityResolutionException]{
    # Group identity not resolved, add to list and continue
}
catch {
    # Something else, completely unforeseen, happened, you might want to re-throw and return from your function
}

最后一个catch 子句(其中省略了类型列表)被称为通用catch 子句,它将处理不匹配的任何异常任何前面的 catch 子句。

【讨论】:

  • 谢谢马蒂亚斯。根据 Will 的建议,我能够让 try/catch 工作。我会说,你对我的回答比我读过的一些文章更疯狂。再次感谢!
  • @Joe-L_177 很高兴这有点道理^_^
猜你喜欢
  • 2011-10-10
  • 1970-01-01
  • 2013-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-09
  • 1970-01-01
  • 2012-01-16
相关资源
最近更新 更多