Powershell ускорить 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"}
$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
}
Проблема в том, что это занимает несколько часов, потому что он запускается по одному пользователю за раз. Моя цель состоит в том, чтобы выполнять несколько запросов одновременно либо через задания, либо параллельно. Это должно быть выполнено в блоках по 10 из-за ограничений политики на сервере обмена.
Изменить (подробнее о том, почему):
Причина для того, чтобы найти количество сообщений пользователей, заключается в том, что они отключены и находятся в отключенном подразделении. Причиной этого является то, что их почта отправлена другому получателю. Или их почтовый ящик был делегирован. Это предназначено для домашнего хозяйства. Результаты этого поиска будут отфильтрованы по MessageCount = 0. Затем он будет либо сообщен / сохранен как удаленный csv/users.
Раскрытие информации: я очень не осведомлен о выполнении заданий или параллельной работе в powershell. И, похоже, мой гугл-фу сломан. Любое руководство или помощь с этим будет очень признателен.
Информация о версии:
Name : Windows PowerShell ISE Host
Version : 5.1.15063.966
ОБНОВИТЬ:
Следуя указаниям Шона, я смог значительно ускорить эти запросы.
Обновленный код:
$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
Проблема, с которой я сталкиваюсь, заключается в том, что каждый пользователь (кроме последних 3-х пользователей) показывает 0 в качестве количества сообщений. Я знаю это неправильно. Может ли это как-то не ожидать завершения запроса Get-MessageTrackingLog -sender?
Пример (всего 77 пользователей):
Все, кроме трех последних шоу:
Электронная почта: ab@something.com
DisabledDate: 02/08/2018
Логин: ab
Тип: OnPrem
Пользователь: a, b
Расположение: Клирфилд, IA
Получено сообщений: 0
1 ответ
Чтобы ускорить 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"}
$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
}
С работой:
$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"}
$365 = $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