从Get-ADObject服务器超时捕获错误

时间:2018-12-09 04:18:05

标签: powershell error-handling active-directory

Tim Rhymer运行此脚本时,我从某些域控制器收到错误,这些服务器由于某种原因服务器超时。当我收到以下错误时,它将脚本停滞15-30秒,而不是查询域控制器花费1-2秒。我如何才能捕获该错误并且不会使脚本停滞这么长时间?以下是

部分

错误消息:

Get-ADObject : Unable to contact the server. This may be because this server
does not exist, it is currently down, or it does not have the Active Directory
Web Services running.
At C:\Users\jimbob\AD_Lookup.ps1:58 char:54
+ ... countName | Get-ADObject -Server $hostname -Properties lastlogon <# - ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (CN=jimbob...DC=domaincontroller,DC=com:User) [Get-ADObject], ADServerDownException
    + FullyQualifiedErrorId : ActiveDirectoryServer:0,Microsoft.ActiveDirectory.Management.Commands.GetADObject

下面是查询域控制器以从所有域控制器获取上次登录日期的脚本。

Import-Module ActiveDirectory

function Get-ADUsersLastLogon() {
  $dcs = Get-ADDomainController -Filter {Name -like "*"}
  $users = Get-ADUser -Filter *
  $time = 0
  $exportFilePath = "c:lastLogon.csv"
  $columns = "name,username,datetime"

  Out-File -FilePath $exportFilePath -Force -InputObject $columns

  foreach ($user in $users) {
    foreach ($dc in $dcs) { 
      $hostname = $dc.HostName
      $currentUser = Get-ADUser $user.SamAccountName | Get-ADObject -Server $hostname -Properties lastLogon

      if ($currentUser.LastLogon -gt $time) {
        $time = $currentUser.LastLogon
      }
    }

    $dt = [DateTime]::FromFileTime($time)
    $row = $user.Name + "," + $user.SamAccountName + "," + $dt

    Out-File -FilePath $exportFilePath -Append -NoClobber -InputObject $row

    $time = 0
  }
}

Get-ADUsersLastLogon

我认为我需要更改某些内容以捕获错误,或者从脚本的以下部分之一绕过导致错误的问题:

$dcs = Get-ADDomainController -Filter {Name -like "*"}

$currentUser = Get-ADUser $user.SamAccountName |
               Get-ADObject -Server $hostname -Properties lastLogon

1 个答案:

答案 0 :(得分:1)

从错误中您可以看到,您得到了ADServerDownException。您可以像这样捕获并处理特定的异常:

try {
    $currentUser = Get-ADUser $user.SamAccountName |
                   Get-ADObject -Server $hostname -Properties lastLogon
} catch [Microsoft.ActiveDirectory.Management.ADServerDownException] {
    # handle AD server unreachable
} catch {
    # handle all other exceptions
}

如果您希望所有其他异常仅冒泡给调用者而不是您自己处理,则末尾的catch可以省略。

但是,这不会加快代码的速度,因为只会在发生超时后 引发异常。为了减少代码的执行时间,您可以

  • 在尝试与服务器进行交互之前,例如,检查服务器是否可访问

    if (Test-Connection -Computer $hostname -Count 2 -Quiet) {
        $currentUser = ...
        ...
    }
    
  • 使用background jobs并行运行操作

    $jobs = foreach ($dc in $dcs) {
        Start-Job -ScriptBlock {
            Param($username, $hostname)
            Get-ADUser $username |
                Get-ADObject -Server $hostname -Properties lastLogon
        } -ArgumentList $user.SamAccountName, $dc.HostName
    }
    $jobs | Wait-Job | Receive-Job
    $jobs | Remove-Job
    

但是,可以说,代码中最大的瓶颈是它首先从AD(Get-ADUser -Filter *)获取所有用户,然后再次再次查询每个用户的DC({{1} }),然后然后对特定DC(Get-ADUser $user.SamAccountName)运行实际查询。

通过针对每个DC对所有用户运行单个查询,您应该能够大大加快代码的速度。将结果按Get-ADObject分组,并从每个组中选择带有最近时间戳记的记录,然后将结果导出到CSV。

SamAccountName