My below script works fine but runs slow. I need to run with -resultsize unlimited. when I run it with -resultsize 550 users it takes 12 minutes to finish. What can I change in my code to run it faster.
Note: I shorten the last line $Results
Thank you!
$DataPath = "C:\temp85\o365UserData.csv"
$Results = @()
$MailboxUsers = get-EXOmailbox -resultsize 550
foreach($user in $mailboxusers)
{
$UPN = $user.userprincipalname
$License = Get-MsolUser -userprincipalname $UPN
$MbxStats = Get-EXOMailboxStatistics $UPN
$Properties = @{
Name = $user.name
UPN = $UPN
Alias = $user.alias
# UsageLocation = $user.usagelocation
License = $License.Licenses[0].AccountSkuId
# ArchiveStatus = $user.archivestatus
LitigationHoldEnabled = $user.LitigationHoldEnabled
LitigationHoldDate = $User.LitigationHoldDate
LitigationHoldOwner = $User.LitigationHoldOwner
LitigationHoldDuration = $User.LitigationHoldDuration
RetentionPolicy = $user.RetentionPolicy
RetentionHoldEnabled = $User.RetentionHoldEnabled
ExchangeGuid = $user.ExchangeGuid
SamAccountName = $User.SamAccountName
Office = $user.Office
InPlaceHolds = $User.InPlaceHolds
IsInactiveMailbox = $User.IsInactiveMailbox
IsSoftDeletedByRemove = $User.IsSoftDeletedByRemove
IsSoftDeletedByDisable = $User.IsSoftDeletedByDisable
AccountDisabled = $User.AccountDisabled
OrganizationalUnit = $User.OrganizationalUnit
DisplayName = $User.DisplayName
PrimarySmtpAddress = $User.PrimarySmtpAddress
RecipientTypeDetails = $User.RecipientTypeDetails
WhenCreated = $User.WhenCreated
WhenMailboxCreated = $User.WhenMailboxCreated
WhenSoftDeleted = $User.WhenSoftDeleted
# ServerName = $MbxStats.servername
# DatabaseName = $MbxStats.databasename
TotItemSize = $MbxStats.totalitemsize
ItemCount = $MbxStats.ItemCount
}
$Results += New-Object psobject -Property $properties
}
$Results | Select-Object Name,DisplayName,License......,License | Export-Csv -notypeinformation -Path $DataPath
It’s not just the size, but For loops in general are always slow. Well, that is depending on what type of For loop you are using, well, that is associated with what PS version you are running as well. Once you throw a large array at it as your are, well, same thing.
So, one option is to chuck the request, just as ADDS does anyway. ADDS has a default count of 1K objects per page, and if you want more, you have to change that settings and understand the impact of that. Also, depending on how many you really have, even TechNet recommends not running it on more than 3K mailboxes at a time.
The other option is to use parallel processing, runspaces, workflows. This still entails break your stuff into chunks though.
Yet when using this construct…
+=
… you really want o understand that impact as well. See this…
https://powershell.org/2013/09/16/powershell-performance-the-operator-and-when-to-avoid-it
See also:
Slow Code: Top 5 Ways to Make Your PowerShell Scripts Run Faster
‘Slow Code: Top 5 Ways to Make Your PowerShell Scripts Run Faster | Microsoft Learn ’
Why cant PowerShell run loops fast ?
‘Why cant PowerShell run loops fast ? | Microsoft Learn ’
jarkko
August 31, 2018, 2:42am
3
Hi
Try following, might not be so much faster. Basically you can skip the whole $Results and pipe the forEach loop to Export-csv also.
Also, measure which one is faster foreach($user in $mailboxusers) or $mailboxusers | ForEach {}
$DataPath = "C:\temp85\o365UserData.csv"
$Results = New-Object System.Collections.Generic.List[System.Object]
$MailboxUsers = get-EXOmailbox -resultsize 550
foreach($user in $mailboxusers) {
$UPN = $user.userprincipalname
$License = Get-MsolUser -userprincipalname $UPN
$MbxStats = Get-EXOMailboxStatistics $UPN
$Results.add([PSCustomObject]@{
Name = $user.name
UPN = $UPN
Alias = $user.alias
# UsageLocation = $user.usagelocation
License = $License.Licenses[0].AccountSkuId
# ArchiveStatus = $user.archivestatus
LitigationHoldEnabled = $user.LitigationHoldEnabled
LitigationHoldDate = $User.LitigationHoldDate
LitigationHoldOwner = $User.LitigationHoldOwner
LitigationHoldDuration = $User.LitigationHoldDuration
RetentionPolicy = $user.RetentionPolicy
RetentionHoldEnabled = $User.RetentionHoldEnabled
ExchangeGuid = $user.ExchangeGuid
SamAccountName = $User.SamAccountName
Office = $user.Office
InPlaceHolds = $User.InPlaceHolds
IsInactiveMailbox = $User.IsInactiveMailbox
IsSoftDeletedByRemove = $User.IsSoftDeletedByRemove
IsSoftDeletedByDisable = $User.IsSoftDeletedByDisable
AccountDisabled = $User.AccountDisabled
OrganizationalUnit = $User.OrganizationalUnit
DisplayName = $User.DisplayName
PrimarySmtpAddress = $User.PrimarySmtpAddress
RecipientTypeDetails = $User.RecipientTypeDetails
WhenCreated = $User.WhenCreated
WhenMailboxCreated = $User.WhenMailboxCreated
WhenSoftDeleted = $User.WhenSoftDeleted
# ServerName = $MbxStats.servername
# DatabaseName = $MbxStats.databasename
TotItemSize = $MbxStats.totalitemsize
ItemCount = $MbxStats.ItemCount
})
}
$Results | Export-Csv -notypeinformation -Path $DataPath -Delimiter ';'
Regards
Jake
js2010
August 31, 2018, 6:57am
4
Not sure if this is faster, but this is how I would do it. Hmm, “-not” is a different color.
$DataPath = "C:\temp85\o365UserData.csv"
get-EXOmailbox -resultsize 550 | foreach-object {
$user = $_
$UPN = $user.userprincipalname
$License = Get-MsolUser -userprincipalname $UPN
$MbxStats = Get-EXOMailboxStatistics $UPN
[pscustomobject]@{
Name = $user.name
UPN = $UPN
Alias = $user.alias
# ...
}
} | Export-Csv -notypeinformation -Path $DataPath