【问题标题】:Trying to find a way to speed up this powershell script试图找到一种方法来加速这个 powershell 脚本
【发布时间】:2016-05-22 13:12:30
【问题描述】:

我有这个运行良好的脚本(输出看起来不错),但现在需要超过 12 个小时。 csv中有34220条记录,现在只有2110。也许我需要先加载所有用户数据,然后与csv文件比较?谢谢帮忙...

import-module ActiveDirectory

$CCure = Import-csv C:\Scripts\CCure\CCure-Personnel-enabled.csv 

ForEach ($Row in $CCure) {
    [string]$ID = $Row.ObjectID
    [string]$Name = $Row.Name
    [string]$EmpID = $Row.Int5

    If ($EmpID.Trim() -ne "0") {
    $User = Get-ADUser -LDAPFilter "(&(&(&(objectclass=user)(objectcategory=person)(!userAccountControl:1.2.840.113556.1.4.803:=2))))((employeeId=*$EmpID))" -SearchBase 'DC=Enterprise,DC=mycompany,DC=org' -Properties SamAccountName,DisplayName,EmployeeId,enabled  | 
    Select @{Name="CCure ObjectID";Expression={$ID}},SamAccountName,DisplayName,@{Name="CCure Name";Expression={$Name}},EmployeeId,@{Name="CCure Int5 Row";Expression={$EmpID}},enabled | Export-csv c:\scripts\ccure\EmployeeIds4-10-2016.csv -NoTypeInformation -append

    }
    }

【问题讨论】:

  • 域中有多少个帐户?
  • AD 中有超过 21k 的活跃用户,但 CCure 可能有很多不在 AD 中。
  • 为什么要在 LDAPFilter 中添加 $EmpID*EmployeeId 是否包含更多而不仅仅是 ID?
  • 这是个好问题。我可能是从另一个脚本中完成的,只是偶然保留了它。我可能可以删除它,但不确定它会加快速度吗?
  • 满足(&(attribute=*value)) 的搜索比满足(&(attribute=value)) 的搜索要快方式(并且在DC 上占用的资源要少得多)

标签: powershell


【解决方案1】:

也许我需要先加载所有用户数据,然后与 csv 文件进行比较?

正是你需要做的!

由于您希望通过 EmployeeId 属性关联 CSV 中的用户,我建议提取所有填充了 EmployeeId 的(启用)用户,然后将它们存储在一个哈希表中,其中 @ 987654323@作为key:

$ADUserTable = @{}
Get-ADUser -LDAPFilter "(&(!userAccountControl:1.2.840.113556.1.4.803:=2)(employeeId=*))' -SearchBase 'DC=Enterprise,DC=mycompany,DC=org' -Properties SamAccountName,DisplayName,EmployeeId |ForEach-Object {
    $ADUserTable[$_.EmployeeId] = $_
}

然后,当您遍历 CSV 中的行时,在哈希表中查找用户,而不是再次搜索 AD:

$ExistingUsers = ForEach ($Row in $CCure) {
    # Import-Csv always creates string properties anyways
    $ID = $Row.ObjectID
    $Name = $Row.Name
    $EmpID = $Row.Int5.Trim()

    if ($EmpID -ne "0" -and $ADUserTable.ContainsKeys($EmpID)) 
    {
        $ADUserTable[$EmpID] |Select @{Name="CCure ObjectID";Expression={$ID}},SamAccountName,DisplayName,@{Name="CCure Name";Expression={$Name}},EmployeeId,@{Name="CCure Int5 Row";Expression={$EmpID}}
    }
}

在您收集所有信息之前不要将它们导出到 Csv - 否则您将打开、写入和关闭同一个文件 35000 次!

所以,最后:

$ExistingUsers |Export-csv c:\scripts\ccure\EmployeeIds4-10-2016.csv -NoTypeInformation

这无疑会加快你的脚本的执行速度


注意:我已从 Get-ADUserSelect-Object 中删除了 Enabled 属性。您的 LDAP 过滤器已经保证只返回启用的用户,所以我没有看到将它添加到 CSV 的任何价值

【讨论】:

  • 嗨,Mathias,这看起来棒极了!但是我收到一个错误方法调用失败,因为 [System.Collections.Hashtable] 不包含名为“ContainsKeys”的方法。在 line:18 char:9 + if ($EmpID -ne "0" -and $ADUserTable.ContainsKeys($EmpID)) + ~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : MethodNotFound跨度>
  • 不好意思,手写的,方法名是ContainsKey(末尾没有s)
  • 谢谢!好的,但是在这一切之后,输出只包含 5266 个匹配项?呃,这是那个系统中非常脏的数据。现在我必须想出另一种方法来验证两个系统中都存在谁,因为这种方法似乎缺乏。接下来我将尝试使用 DisplayName。再次感谢!
  • If(@($ADUserTable.Keys -like "*$Email").Count -gt 0) 而不是 ContainsKey 如果这是问题,则会产生部分匹配
  • 如果没有从您的 Active Directory 中获取 CSV 样本和一些相应的用户,我很难说 DisplayName/Firstname Lastname/EmployeeId 是否是数据之间关联的最佳键值。它基本上归结为:“我们是否有任何两个 distinct 值可以在两个数据源之间轻松比较?”,然后应用我向您展示的算法:将两者读入内存,排序/组织一个按键,然后遍历另一个。有意义吗?
猜你喜欢
  • 2021-12-25
  • 1970-01-01
  • 2019-06-11
  • 1970-01-01
  • 2014-01-09
  • 1970-01-01
  • 2022-06-15
  • 2021-11-26
  • 2017-08-16
相关资源
最近更新 更多