Powershell 加速 Get-MessageTrackingLog

Powershell Speed Up Get-MessageTrackingLog

目前我正在尝试获取所有禁用用户的输出以及他们的消息计数作为交换。通过 foreach 循环这很容易:

    $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://aserversomewhere.local/PowerShell/ -Authentication Kerberos -Credential $UserCredential
    Import-PSSession $Session -AllowClobber    

    Import-Module ActiveDirectory    

    $Users = Get-ADUser -filter * -Properties * -SearchBase "OU=Disabled User Accounts,DC=Private,DC=Private"

    $Today = (Get-Date).ToShortDateString()
    $OneMonthAgo = (Get-Date).AddMonths(-1).ToShortDateString()

    $results = @()

    $OnPrem = $Users | Where-Object {$_.mDBUseDefaults -eq "True"}
    5 = $Users | Where-Object{$_.mDBUseDefaults -ne "True"}

    Write-Host "Start Date: " $OneMonthAgo -ForegroundColor Green
    Write-Host "Total Users OnPrem: " ($OnPrem.mail).Count -ForegroundColor Green

    foreach($User in $OnPrem)
    {
        Write-Host "Checking User: "$User.DisplayName -ForegroundColor Yellow
        $MessageCount = Get-MessageTrackingLog -recipients $User.Mail -Start $OneMonthAgo.ToString() | Where-Object {$_.EventID -eq "RECEIVE"} | Measure-Object

        Write-Host $User.Name": MessageCount: "$MessageCount.Count -ForegroundColor Cyan

         $Object = New-Object PSObject -Property @{
            User = $User.Name
            Email = $User.Mail
            Type = "OnPrem"
            DisabledDate = $User.Modified
            Location = $User.Office
            MessagesReceived = $MessageCount.Count
         }

         $script:results += $Object
    }

问题是这需要几个小时才能完成,因为它是一次 运行 一个用户。我的目标是通过作业或并行 运行 一次进行多个查询。由于 exchange 服务器的政策限制,这需要 运行 以 10 个为单位。

编辑(关于原因的更多信息):

The reason to find the message counts of the users is, they are disabled and sitting an a disabled OU. The reason for this is their mail is fw to another recipient. Or, their mailbox has been delegated. This is intended for house keeping. The results of this search will be filtered by MessageCount = 0. Then it will either be reported/saved as csv/users removed.

披露:我对 运行ning 作业或 运行ning 在 powershell 中的并行工作非常无知运行t。而且,我的 google-foo 似乎坏了。任何指导或帮助将不胜感激。

版本信息:

Name             : Windows PowerShell ISE Host
Version          : 5.1.15063.966

更新:

在 Shawn 的指导下,我成功地显着加快了这些请求的速度。

更新代码:

$RunSpaceCollection = @()
$RunspacePool = [RunspaceFactory]::CreateRunspacePool(1, 10)
$RunspacePool.ApartmentState = "MTA"
$RunspacePool.Open()


$UserCredential = Get-Credential

Import-Module ActiveDirectory


$Users = Get-ADUser -filter * -Properties * -SearchBase "OU=Disabled User Accounts,DC=private,DC=private"

$Today = (Get-Date).ToShortDateString()
$OneMonthAgo = (Get-Date).AddMonths(-1).ToShortDateString()

[Collections.ArrayList]$results = @()

$OnPrem = $Users | Where-Object {$_.mDBUseDefaults -eq "True"}
5 = $Users | Where-Object{$_.mDBUseDefaults -ne "True"}

Write-Host "Start Date: " $OneMonthAgo -ForegroundColor Green
Write-Host "Total Users OnPrem: " ($OnPrem.mail).Count -ForegroundColor Green

$scriptblock = {
    Param (
        [System.Management.Automation.PSCredential]$Credential,
        [string]$emailAddress,
        [string]$startTime,
        [string]$userName,
        [string]$loginName,
        [string]$DisabledDate,
        [string]$OfficeLocation
    )      

    $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://someserver.local/PowerShell/ -Authentication Kerberos -Credential $Credential
    Import-PSSession $Session -AllowClobber -DisableNameChecking -Verbose:$false | Out-Null

    $MessageCount = Get-MessageTrackingLog -recipients $emailAddress -Start $startTime.ToString() -ResultSize unlimited  

    $Object = New-Object PSObject -Property @{
        User = $userName
        Login = $loginName
        Email = $emailaddress
        Type = "OnPrem"
        DisabledDate = $DisabledDate
        Location = $OfficeLocation
        MessagesReceived = $MessageCount.Count.ToString()
        }           

     $Object


}

foreach($User in $OnPrem)
{
    $Powershell = [PowerShell]::Create()
    $null = $Powershell.AddScript($scriptblock)
    $null = $Powershell.AddArgument($UserCredential)
    $null = $Powershell.AddArgument($user.mail)
    $null = $Powershell.AddArgument($OneMonthAgo)
    $null = $Powershell.AddArgument($user.Name)
    $null = $Powershell.AddArgument($user.samaccountname)
    $null = $Powershell.AddArgument($user.Modified)
    $null = $Powershell.AddArgument($user.Office)
    $Powershell.RunspacePool = $RunspacePool   

    [Collections.ArrayList]$RunSpaceCollection += New-Object -TypeName PSObject -Property @{
        RunSpace = $Powershell.BeginInvoke()
        PowerShell = $Powershell
    }

}

 While($RunspaceCollection) {        

    Foreach($Runspace in $RunSpaceCollection.ToArray())
    {        
        If ($Runspace.Runspace.IsCompleted) {           

            [void]$results.Add($Runspace.PowerShell.EndInvoke($Runspace.Runspace))          

            $Runspace.PowerShell.Dispose()
            $RunspaceCollection.Remove($Runspace)

        }
    }    
 }

$RunspacePool.Close() 
$RunspacePool.Dispose()


 $results

我遇到的问题是每个用户(除了最后 3 个用户)都显示 0 作为消息计数。我知道这是错误的。这会不会以某种方式不等待 Get-MessageTrackingLog -sender 的查询完成?

示例(共 77 个用户):

除最后三个节目外的所有节目:

Email : a.b@something.com

DisabledDate : 02/08/2018

Login : a.b

Type : OnPrem

User : a, b

Location : Clearfield, IA

MessagesReceived : 0

为了加速 Get-MessageTrackingLog,您必须使用池。

原文:

$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://aserversomewhere.local/PowerShell/ -Authentication Kerberos -Credential $UserCredential
Import-PSSession $Session -AllowClobber    

Import-Module ActiveDirectory    

$Users = Get-ADUser -filter * -Properties * -SearchBase "OU=Disabled User Accounts,DC=Private,DC=Private"

$Today = (Get-Date).ToShortDateString()
$OneMonthAgo = (Get-Date).AddMonths(-1).ToShortDateString()

$results = @()

$OnPrem = $Users | Where-Object {$_.mDBUseDefaults -eq "True"}
5 = $Users | Where-Object{$_.mDBUseDefaults -ne "True"}

Write-Host "Start Date: " $OneMonthAgo -ForegroundColor Green
Write-Host "Total Users OnPrem: " ($OnPrem.mail).Count -ForegroundColor Green

foreach($User in $OnPrem)
{
    Write-Host "Checking User: "$User.DisplayName -ForegroundColor Yellow
    $MessageCount = Get-MessageTrackingLog -recipients $User.Mail -Start $OneMonthAgo.ToString() | Where-Object {$_.EventID -eq "RECEIVE"} | Measure-Object

    Write-Host $User.Name": MessageCount: "$MessageCount.Count -ForegroundColor Cyan

     $Object = New-Object PSObject -Property @{
        User = $User.Name
        Email = $User.Mail
        Type = "OnPrem"
        DisabledDate = $User.Modified
        Location = $User.Office
        MessagesReceived = $MessageCount.Count
     }

     $script:results += $Object
}

有乔布斯:

$MaxThread = 10
$RunspacePool = [runspacefactory]::CreateRunspacePool(
    [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
)
[void]$RunspacePool.SetMaxRunspaces($MaxThread)
$RunspacePool.Open()

$UserCredential = Get-Credential

Import-Module ActiveDirectory


$Users = Get-ADUser -filter * -Properties * -SearchBase "OU=Disabled User Accounts,DC=private,DC=private"

$Today = (Get-Date).ToShortDateString()
$OneMonthAgo = (Get-Date).AddMonths(-1).ToShortDateString()

[Collections.ArrayList]$results = @()    

$OnPrem = $Users | Where-Object {$_.mDBUseDefaults -eq "True"}
5 = $Users | Where-Object{$_.mDBUseDefaults -ne "True"}

Write-Host "Start Date: " $OneMonthAgo -ForegroundColor Green
Write-Host "Total Users OnPrem: " ($OnPrem.mail).Count -ForegroundColor Green


$OnPremScriptblock = {
    Param (
        [System.Management.Automation.PSCredential]$Credential,
        [string]$emailAddress,
        [string]$startTime,
        [string]$userName,
        [string]$loginName,
        [string]$DisabledDate,
        [string]$OfficeLocation
    )      

    $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://aserversomewhere.local/PowerShell/ -Authentication Kerberos -Credential $Credential
    Import-PSSession $Session -AllowClobber -DisableNameChecking -Verbose:$false | Out-Null

    $MessageCount = Get-MessageTrackingLog -recipients $emailAddress -Start $startTime.ToString() -ResultSize unlimited  

    $Object = New-Object PSObject -Property @{
        User = $userName
        Login = $loginName
        Email = $emailaddress
        Type = "OnPrem"
        DisabledDate = $DisabledDate
        Location = $OfficeLocation
        MessagesReceived = $MessageCount.Count.ToString()
        }           

     $Object


}

$jobs = New-Object System.Collections.ArrayList
foreach ($user in $OnPrem){

    $PowerShell = [PowerShell]::Create()

    $null = $PowerShell.AddScript($OnPremScriptblock)
    $null = $PowerShell.AddArgument($UserCredential)
    $null = $PowerShell.AddArgument($user.mail)
    $null = $PowerShell.AddArgument($OneMonthAgo)
    $null = $PowerShell.AddArgument($user.name)
    $null = $PowerShell.AddArgument($user.samaccountname)
    $null = $PowerShell.AddArgument($user.modified)
    $null = $PowerShell.AddArgument($user.Office)

    $PowerShell.RunspacePool = $RunspacePool

    [void]$jobs.Add((
    [pscustomobject]@{
        PowerShell = $PowerShell
        Handle = $PowerShell.BeginInvoke()
    }
    ))
}

While($jobs.handle.IsCompleted -eq $false){
    Write-Host "." -NoNewline
    Start-Sleep -Milliseconds 100
}

$return = $jobs | foreach{
    $_.PowerShell.EndInvoke($_.Handle)
    $_.PowerShell.Dispose()
}
$jobs.Clear()
$return

结果存储在$return