【问题标题】:PowerShell processing of large users very slow - Is there a better way?大型用户的 PowerShell 处理速度非常慢 - 有没有更好的方法?
【发布时间】:2017-01-10 08:11:27
【问题描述】:

我一直在使用 Office365 许可证跟踪。实际上它看起来不错,但是完成该过程需要太多时间。大部分时间都花在 Get-MsolUser 上,并行计算它们可能会得到改进(在处理用户 1 时,您已经在获取用户 2 的数据等等......)顺便说一句,我们有大约 3000 多个云用户我该如何改进脚本速度?

$T1 = @()
$O365Users = Get-MsolUser -All
ForEach ($O365User in $O365Users)
{
    $ADuser = Get-ADUser -Filter { UserPrincipalName -eq $O365User.UserPrincipalName } -Properties whenCreated, Enabled, lastlogondate
    $O365Stats = Get-MailboxStatistics $O365User.DisplayName -ErrorAction SilentlyContinue
    $O365Smtp =  Get-Recipient $O365User.DisplayName -ErrorAction SilentlyContinue
    If ($O365Stats -and $O365Smtp) {
    If (($ADUser.Enabled -eq $true) -and ($O365User.isLicensed -eq $true))
    {
        $T1 += New-Object psobject -Property @{
            CollectDate = $(Get-Date);
            ADUserUPN = $($ADUser.UserPrincipalName);
            O365UserUPN = $($O365User.UserPrincipalName);
            ADUserCreated = $($ADUser.whenCreated);
            ADUserEnabled = $($ADUser.Enabled);
            ADLastLogonDate = $($ADUser.LastLogonDate);
            O365Licensed = $($O365User.isLicensed);
            O365LastLogonTime = $($O365Stats.LastLogonTime);
            O365SMTPAddress = $($O365Smtp.PrimarySMTPAddress)
        }
    }
}
}
$T1 = $T1 | Sort-Object -Property ADUserCreated
$T1 | Format-Table
$T1 | Export-Csv -Path $OutputFile -NoTypeInformation
Write-Host "Output to $OutputFile"

【问题讨论】:

  • 就像你说的一样,平行出来
  • 感谢您所说的我如何重建我的脚本?请澄清

标签: powershell office365 exchange-server export-to-csv


【解决方案1】:

使用管道、尽早过滤和避免附加到数组应该已经大大加快了速度:

Get-MsolUser -All | Where-Object {
    $_.IsLicensed
} | ForEach-Object {
    $upn = $_.UserPrincipalName
    Get-ADUser -Filter "UserPrincipalName -eq '$upn'" -Properties whenCreated, Enabled, lastlogondate
} | Where-Object {
    $_.Enabled
} | ForEach-Object {
    $O365Stats = Get-MailboxStatistics $_.DisplayName -ErrorAction SilentlyContinue
    $O365Smtp  = Get-Recipient $_.DisplayName -ErrorAction SilentlyContinue
    if ($O365Stats -and $O365Smtp) {
        New-Object -Type PSObject -Property @{
            'CollectDate'       = Get-Date
            'ADUserUPN'         = $_.UserPrincipalName
            'O365UserUPN'       = $_.UserPrincipalName
            'ADUserCreated'     = $_.whenCreated
            'ADUserEnabled'     = $_.Enabled
            'ADLastLogonDate'   = $_.LastLogonDate
            'O365Licensed'      = $true
            'O365LastLogonTime' = $O365Stats.LastLogonTime
            'O365SMTPAddress'   = $O365Smtp.PrimarySMTPAddress
        }
    }
} | Sort-Object -Property ADUserCreated | Export-Csv -Path $OutputFile -NoType

另外,为什么每个人都对子表达式如此着迷?在需要的地方使用它们。不要在不必要的时候用它们混淆你的代码。

【讨论】:

  • 你是对的关于不必要的过滤人我会尽快检查这个。
  • 我收到如下警告:默认情况下,仅返回前 1000 个项目。使用 ResultSize 参数指定返回的项目数。要返回所有项目,请指定“-ResultSize Unlimited”。请注意,根据项目的实际数量,返回所有项目可能需要很长时间并消耗大量内存。此外,我们不建议将结果存储在变量中。相反,将结果通过管道传输到另一个任务或脚本以执行批量更改。你有什么推荐的?
  • 你到底是从哪里得到这个警告的? AFAICS 除Get-MsolUser 之外的所有cmdlet 都应返回单个项目,但根据文档,Get-MsolUser 的参数应为-MaxResults(默认值为500),而不是-ResultSize
  • 据我所见,我在脚本运行期间不断收到此警告,我也不知道警告的确切来源。最后,如果我运行上面的脚本(未经编辑),那么我不会收到这样的警告。
  • 试试我更新的答案。你还在收到那个警告吗?如果您删除 Sort-Object 步骤,它是否仍然存在?
【解决方案2】:

为您提供 Powershell 中的并行性。

我希望您完成 PS 工作流程。

我们有 -parallel 可以帮助您进行并行调用。

除此之外,我们还有一个Invoke-Parallel

函数

这是它的链接:Invoke-Parallel Function

注意:示例在函数本身内提及。您也可以在编译后对该函数使用 get-help。

【讨论】:

  • 谢谢我如何将我的脚本与 Invoke-Parallel 函数结合起来?我对么 ? Invoke-Parallel -scriptfile myscript.ps1 -runspaceTimeout 10 -throttle 10
  • @Arbelac:是的,你应该做的工作......检查一下
猜你喜欢
  • 2014-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-30
  • 2021-01-13
相关资源
最近更新 更多