【问题标题】:Powershell Combine Arrays, working code, but slowPowershell组合数组,工作代码,但速度慢
【发布时间】:2017-07-14 09:30:00
【问题描述】:

在研究了如何组合数组之后,使用我在此处和其他来源中找到的信息,我能够创建一个脚本,该脚本采用多个数组并将它们组合到一个主键(userprincipalname)上。该脚本的目的是将 Office 365 的许可和使用统计信息与 Active Directory 中的用户帐户信息相结合。

我有兴趣改进的代码块是我结合三个数据源的最后一步。虽然我的代码有效,但它需要 30 多分钟才能运行。我认为这主要是由于我如何循环并分别处理每条记录。此时,虽然代码可以工作,但实际上打开电子表格并在 Excel 中执行 VLOOKUP 会快得多。

下面是合并三个数组的代码:

$MBInfoCC = Import-Excel C:\Work\MBStats.xlsx | Sort-Object -Property UserPrincipalName
$LicInfoCC = Import-Excel C:\Work\LicStats.xlsx | Sort-Object -Property UserPrincipalName
$ADInfoCC = Import-Excel C:\Work\ADUserInfo.xlsx | Sort-Object -Property UserPrincipalName

$ADInfoCC | ForEach-Object {
$gumdrop = $_
[PSCustomObject]@{
    'Windows Username' = $ADInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}).WindowsUserName
    'User Principal Name' = $ADInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}).UserPrincipalName
    'Display Name' = $ADInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}).DisplayName
    'Last Name' = $ADInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}).LastName
    'First Name' = $ADInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}).FirstName
    'Email Address' = $ADInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}).EmailAddress
    'Employee Number' = $ADInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}).EmployeeNumber
    'Description' = $ADInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}).Description
    'Employee Type' = $ADInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}).EmployeeType
    'Division' = $ADInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}).Division
    'Department' = $ADInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}).Department
    'Account Enabled' = $ADInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}).AccountEnabled
    'Last Windows Logon' = $ADInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}).LastWindowsLogon
    'Last Mailbox Access' = $MBInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}).LastMailboxLogon
    'Office 365 License' = $LicInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}).License
    'Mailbox Size' = $MBInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}).MailboxSize
    'Mailbox Type' = $MBInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}).MailboxType
    'Account Expiration Date' = $ADInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}).AccountExpirationDate
    'Password Last Set' = $ADInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}).PasswordLastSet
    'Password Has Expired' = $ADInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}).PasswordExpired
    'Password Not Required' = $ADInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}).PasswordNotRequired
    'Password Never Expires' = $ADInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}).PasswordNeverExpires
    'User Cannot Change Password' = $ADInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}).CannotChangePassword
    }
} | Export-Excel -Path C:\Work\FullUserReport.xlsx -FreezeTopRow -AutoSize -BoldTopRow

正如您在代码中所读到的,其工作方式是将所有三个 excel 工作表加载到单独的数组中,每个数组都有一个 UserPrincipalName 字段。 AD 信息包含所有用户,无论他们是否是邮箱用户,因此我将其用作主要用户。我遍历与字段匹配的列表。我还使用 import-excel 模块而不是 import-csv 以便能够应用一些格式。我昨天将 Sort-Object 添加到数组中,以查看对列表进行排序是否会提高性能,它在一定程度上起到了作用,因为运行时间从 40 多分钟下降到 30 多分钟。

谢谢, 克拉克

【问题讨论】:

  • 您正在运行大量的 where 过滤器,并且每次您都在过滤整个电子表格。如果先合并对象,然后提取数据,效率会高得多。 Warren Frame 的 Join-Object 可以让这一切变得简单。
  • 您可以分配过滤后的对象并使用它,而不是每次都使用 where 过滤。例如:$UsrPrinInstance = $ADInfoCC.Where({$PSItem.UserPrincipalName -eq $gumdrop.UserPrincipalName}) ... 'Windows 用户名' = $UsrPrinInstance.WindowsUserName

标签: arrays powershell active-directory office365


【解决方案1】:

我会创建哈希表,而不是数组,使用 UserPrincipalName 作为键, 例如:

$MBInfoCC = @{}

 Import-Excel C:\Work\MBStats.xlsx |
 ForEach-Object  {$MBInfoCC[$_.UserPrincipalName] = $_}

$LicInfoCC = @{}

Import-Excel C:\Work\LicStats.xlsx |
ForEach-Object {$LicInfoCC[$_.UserPrincipalName] = $_}

$ADUserInfo = @{}

Import-Excel C:\Work\ADUserInfo.xlsx |
ForEach-Object {$ADUserInfo[$_.UserPrincipalName] = $_}

现在您可以通过哈希表键直接引用它们,而无需 .where() 搜索。

【讨论】:

  • 是的,另外将找到的项目存储在一个变量中,而不是多次重新访问它:$mb = $MBInfoCC[$_.UserPrincipalName] 然后在 PSCustomObject 哈希表中引用它'Mailbox Size' = $mb.MailboxSize; 'Mailbox Type' = $mb.MailboxType;
【解决方案2】:

BenH 关于尝试 Warren Frame 的 Join-Object 的评论让我再次尝试 Join-Object,之前我使用了从 Microsoft 下载的 Join-Object 模块,但是它不能正确地加入数据(看起来像一个内部连接无论我设置什么类型)。然而,Warren's Join 确实有效。

使用它,我现在可以在几分钟内完成这段代码:

$MBInfoCC = Import-Excel C:\Work\MBStats.xlsx | Sort-Object -Property UserPrincipalName
$LicInfoCC = Import-Excel C:\Work\LicStats.xlsx | Sort-Object -Property UserPrincipalName
$ADInfoCC = Import-Excel C:\Work\ADUserInfo.xlsx | Sort-Object -Property UserPrincipalName

$combo1 = Join-Object -Left $ADInfoCC -LeftJoinProperty UserPrincpalName -Right $MBInfoCC -RightJoinProperty UserPrincipalName -LeftProperties 'Windows UserName',UserPrincipalName,'Display Name','Last Name','First Name','Email Address','Employee Number',Description,'Employee Type',Division,Department,'Account Enabled','Last Windows Logon','Account Expiration Date','Password Last Set','Password Has Expired','Password Not Required','Password Never Expires','User Cannot Change Password' -RightProperties 'Mailbox Size','Last Mailbox Access','Mailbox Type' -Type AllInLeft

Join-Object -Left $combo1 -LeftJoinProperty UserPrincpalName -Right $LicInfoCC -RightJoinProperty UserPrincpalName -LeftProperties 'Windows UserName',UserPrincipalName,'Display Name','Last Name','First Name','Email Address','Employee Number',Description,'Employee Type',Division,Department,'Account Enabled','Last Windows Logon','Account Expiration Date','Password Last Set','Password Has Expired','Password Not Required','Password Never Expires','User Cannot Change Password','Mailbox Size','Last Mailbox Access','Mailbox Type' -RightProperties License -Type AllInLeft | Export-Excel C:\Work\FullUserReport.xlsx -FreezeTopRow -AutoSize -BoldTopRow

【讨论】:

  • 这就是我最终完成这个脚本的方式。
猜你喜欢
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多