powershell - 如何使用 PSCustomObjects 对对象进行不可变的更改?

标签 powershell import-csv pscustomobject get-aduser add-member

我有两个表作为 pscustomobjects,我尝试执行相当于 SQL 连接的操作,将一些属性添加回我需要读取的主对象中。问题是我下面的代码在一个包含大约 40,000 个条目的对象集合上运行了 5 个小时,但仍然没有完成。我是不是做错了什么?

$tableObj = import-csv ".\employeeIDsAndAttributes.csv"

"Getting AD data"
$directoryTable = Get-ADUser -Filter {(employeeid -like "*")} -Properties employeeid,name,samaccountname,distinguishedname | 
Select-Object employeeid,name,samaccountname,distinguishedname
"Finished getting AD data. Joining tables."

foreach ($changeRecordLine in $tableObj) {
    $changeRecordLine | add-member -NotePropertyName "Name" -NotePropertyValue ($directoryTable | Where-Object {($_.employeeid -eq $changeRecordLine.employeeID)} | Select-Object -ExpandProperty name) -Force
    $changeRecordLine | add-member -NotePropertyName "DN" -NotePropertyValue ($directoryTable | Where-Object {($_.employeeid -eq $changeRecordLine.employeeID)} | Select-Object -ExpandProperty distinguishedname) -Force
    $changeRecordLine | add-member -NotePropertyName "ParentDN" -NotePropertyValue ( $changeRecordLine.DN.substring($changeRecordLine.Name.length+4)) -Force
}

Excel 让我可以使用 vlookup 毫无问题地加入我的列,但这也应该很快。

我尝试运行上面的代码。当我取消该过程时,我获取了 $tableObj 并在 Excel 中检查它,并注意到一些条目已更改,但不是全部。我原以为这个过程会很快完成。

最佳答案

您的代码速度慢有两个主要原因,您正在使用 Where-Object 进行线性查找,这本身​​很慢(这是在 PowerShell 中过滤集合的最慢技术),但除此之外为此,每次循环迭代您都会执行两次线性查找,而它可能只需要一次:

# lookup just once:
$lookUp = $directoryTable | Where-Object { $_.employeeid -eq $changeRecordLine.employeeID }
# then Name and DN are available to you:
$lookUp.Name
$lookUp.DistinguishedName

What you should use instead of a linear lookup is a structure meant specifically for fast lookups:

$tableObj = Import-Csv ".\employeeIDsAndAttributes.csv"
$map = @{}

# `name, samaccountname, distinguishedname` are already default properties
# no need to include them in `-Properties`
foreach($user in Get-ADUser -Filter "EmployeeId -like '*'" -Properties employeeid) {
    $map[$user.employeeid] = $user
}

foreach($changeRecordLine in $tableObj) {
    $value = $map[$changeRecordLine.employeeid]
    $props = $changeRecordLine.PSObject.Properties

    $parentDN = try {
        $changeRecordLine.DN.SubString($changeRecordLine.Name.Length + 4)
    }
    catch { }

    # `Add-Member` adds overhead even though this is the least of your code's issues,
    # adding `NoteProperties` to your objects by accessing
    # the object's PSObject Properties and adding them manually is faster
    $props.Add([psnoteproperty]::new('Name', $value.Name))
    $props.Add([psnoteproperty]::new('DN', $value.DistinguishedName))
    $props.Add([psnoteproperty]::new('ParentDN', $parentDN))
}

关于powershell - 如何使用 PSCustomObjects 对对象进行不可变的更改?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74804974/

相关文章:

powershell - 何时可以使用方法以及何时使用命令行选项?

arrays - 数组第一个元素

powershell - 创建自定义对象并使用输出

powershell - Import-CSV:将行(成员)添加到 foreach 循环中的结果对象

powershell - 在子字符串中向日期时间添加小时

powershell - 为什么我不能在类方法中使用预定义的变量?

Powershell 奇怪的错误处理行为

amazon-s3 - 在不通过 S3 的情况下将 csv 加载到 Redshift

powershell - 使用Powershell写出两个标题行而不删除现有数据

arrays - 如果已存在,则防止将 pscustomobject 添加到数组