powershell - 从 Get-ADObject 服务器超时捕获错误
问题描述
当我从Tim Rhymer运行此脚本时,我从一些域控制器中收到错误,其中服务器由于某种原因超时。当我收到以下错误时,它会暂停脚本 15-30 秒,而不是查询域控制器需要 1-2 秒。我怎样才能捕捉到错误并且不让脚本停顿这么久?以下是该部分
错误信息:
Get-ADObject:无法联系服务器。这可能是因为这个服务器 不存在、当前已关闭或没有 Active Directory Web 服务正在运行。 在 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
解决方案
正如您从错误中看到的那样,您得到了一个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 = ... ... }
使用后台作业并行运行操作
$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 () 获取所有用户,然后针对每个 DC ( )再次Get-ADUser -Filter *
单独查询每个用户,然后针对特定 DC () 运行实际查询。Get-ADUser $user.SamAccountName
Get-ADObject
您应该能够通过针对每个 DC 对所有用户运行单个查询来显着加快代码速度。将结果分组SamAccountName
并从每个组中选择具有最新时间戳的记录,然后将结果导出到 CSV。
$fltr = '(&(objectClass=user)(objectCategory=person))'
$props = 'SamAccountName', 'LastLogon'
Get-ADDomainController -Filter * |
Select-Object -Expand HostName |
Where-Object { Test-Connection -Computer $_ -Count 2 -Quiet } |
ForEach-Object { Get-ADObject -LDAPFilter $fltr -Properties $props -Server $_ } |
Select-Object Name, SamAccountName,
@{n='LastLogon';e={[DateTime]::FromFileTime($_.LastLogon)}} |
Group-Object SamAccountName |
ForEach-Object { $_.Group | Sort-Object LastLogon | Select-Object -Last 1 } |
Export-Csv $exportFilePath -NoType
推荐阅读
- java - 如何在 Java 中将 Bson 时间戳从 Mongo 更改流转换为 UTC 日期格式?
- command-line - Xunit 完整的命令行选项列表
- python - Python 中的 Pathlib 与 os.path.join
- c# - 我需要手动刷新 StreamWriter 吗?
- video - CDN 不允许我将 mov 视频格式转换为 mp4
- reactjs - #React 如何通过指定参数为某些参数传入函数值?
- python - 无法从 numpy 数组中检索值
- splunk - 如何在使用统计信息加入数据集之前过滤掉事件
- single-sign-on - IdentityServer - 将额外参数从 endsession 端点传递到 Logout
- excel - 仅当某个单元格已填充时才填充单元格