title: Powershell Speed Up Get-MessageTrackingLog
body: <p>Currently I am trying to get an output of all disabled users and their message counts in exchange. This is easy enough through a foreach loop:</p>
  
  <pre><code>    $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"}
      $365 = $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
      }
  </code></pre>
  
  <p>The issue is this takes several hours to complete because it is being ran one user at a time. My Goal is to run multiple inquiries at a time either through jobs or in parallel. This needs to be ran in blocks of 10 due to the policy restrictions on the exchange server.</p>
  
  <p><strong>Edit (more information on why):</strong></p>
  
  <blockquote>
    <p>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.</p>
  </blockquote>
  
  <p>Disclosure: I am very ignorant on running jobs or running in parallel within powershell. And, my google-foo seems to be broken. Any guidance or help with this would be very appreciated.</p>
  
  <p>Version info:</p>
  
  <pre><code>Name             : Windows PowerShell ISE Host
  Version          : 5.1.15063.966
  </code></pre>
  
  <p><strong>UPDATE:</strong> </p>
  
  <p>After Following Shawn's guidance, I was able to successfully speed up these requests quite significantly.</p>
  
  <p><strong>Updated code:</strong></p>
  
  <pre><code>$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"}
  $365 = $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
  </code></pre>
  
  <p>The issue I am having is every user (<strong>except the last 3 users</strong>) are showing 0 as the message count. I know this wrong. Could this somehow not be waiting for the query of Get-MessageTrackingLog -sender to finish?</p>
  
  <p>Example (77 Users total):</p>
  
  <p>All but the last three show:</p>
  
  <blockquote>
    <p>Email            : a.b@something.com </p>
    
    <p>DisabledDate     : 02/08/2018</p>
    
    <p>Login            : a.b </p>
    
    <p>Type             : OnPrem </p>
    
    <p>User             : a, b </p>
    
    <p>Location         : Clearfield, IA</p>
    
    <p><strong>MessagesReceived : 0</strong></p>
  </blockquote>