For suspending move requests during business hours (only those below 94%)
Bear these in mind:
The script has to produce a move request statistics report which takes an hour per 1500 requests.
Suspending is performed at a rate of 6000 per hour.
Work backwards from the cutoff time (with an emergency window allowed for).
E.g. Move requests = 3000
Business hours start at 09:00
Emergency cutoff = 08:00
Suspend time = 07:30
Start report time = 05:00 (allow an extra bit of time between report and suspend to be safe)
EMS:
[string]$ExchOnline = "outlook.office365.com"
$exolusername = "#####@#####.onmicrosoft.com"
$exolpassword = Get-Content "C:\TEMP\EncryptedPasswords\#####.txt" | ConvertTo-SecureString
$Excredential = new-object -typename System.Management.Automation.PSCredential -argumentlist $exolusername, $exolpassword
$EXOnlineSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://$ExchOnline/powershell-liveid/ -Credential $Excredential -Authentication Basic -AllowRedirection -ErrorAction Stop
$startreporttimeinput = Read-host "Specify the time to run a report (in hh:mm format)"
$startsuspendtimeinput = Read-host "Also state what time mailbox moves should be suspended (in hh:mm format)"
$now = [System.DateTime]::Now
$today = [System.DateTime]::Today
$tomorrow = ($today).AddDays(1)
$startreporttime = Get-date $startreporttimeinput
$startsuspendtime = Get-date $startsuspendtimeinput
if($now -gt $startreporttime){$startreporttime = ($startreporttime).AddDays(1); $startsuspendtime = ($startsuspendtime).AddDays(1) }
write-host "`$startreporttime is $startreporttime"
write-host "`$startsuspendtime is $startsuspendtime"
while($startreporttime -gt $now){write-progress -Activity "Waiting to start report at $($startreporttime)" -Status "Time last checked at $($now)"; sleep 60; $now = [System.DateTime]::Now}
[string]$DateTime = (Get-Date).Tostring("dd-MM-yyyy_HHmmss")
[string]$FilePath = "C:\Temp\"
[string]$OutputFilename1 = [string]::Format($FilePath + "MoveRequest_Full_Report_{0}.csv",$DateTime)
[System.DateTime]::Now
$warningPreference = "SilentlyContinue"
Import-PSSession $EXOnlineSession -warningaction silentlycontinue -erroraction silentlycontinue | Out-Null
$warningPreference = "Continue"
Write-host "Gathering all move request information..."
$mrs = Get-MoveRequest -ResultSize unlimited | ?{$_.Status -notlike "Complet*"}
[INT]$mrscount = ($mrs).count
$moveresults = @()
$remainingmoveresults = @()
[INT64]$totaldata = 0
[INT64]$remainingdatavol = 0
$allmovestats = @()
[int64]$alltransferreddata = 0
[INT]$counter = 0
[System.DateTime]::Now
Write-host "The move requests will now be analyzed for more information..."
foreach($mr in $mrs){
$counter ++
Write-Progress -Activity "Gathering move request statistics..." -Status "$counter of $mrscount"
[String]$ExchangeGUID = $mr.ExchangeGUID
$mrstats = Get-MoveRequestStatistics $ExchangeGUID
[int64]$TotalMailboxSizeBytes = $mrstats.TotalMailboxSize -replace "(^.*?\()|\D"
[INT64]$TotalMailboxSizeMB = $TotalMailboxSizeBytes /1048576
[INT64]$TotalMailboxSizeGB = $TotalMailboxSizeMB /1024
[INT64]$TotalMailboxSizeGBrounded =[math]::Round($TotalMailboxSizeGB,2)
[int64]$TransferredBytes = $mrstats.BytesTransferred -replace "(^.*?\()|\D"
[INT64]$TransferredMB = $TransferredBytes /1048576
[INT64]$TransferredGB = $TransferredMB /1024
[INT64]$TransferredGBrounded =[math]::Round($TransferredGB,2)
#$RemainingGBtoTransfer = $TotalMailboxSizeGB - $TransferredGB
#if($RemainingGBtoTransfer -lt 0){$RemainingGBtoTransfer = 0}
#[INT64]$RemainingGBtoTransferrounded =[math]::Round($RemainingGBtoTransfer,2)
[INT]$TotalMailboxItemCount = $mrstats.TotalMailboxItemCount
[INT]$ItemsTransferred = $mrstats.ItemsTransferred
[INT]$ItemsRemaining = (($TotalMailboxItemCount) - ($ItemsTransferred))
if($ItemsRemaining -lt 0){$ItemsRemaining = 0}
$i = New-Object -TypeName PSObject
$i | Add-Member -MemberType NoteProperty -Name Alias -Value $mrstats.Alias
$i | Add-Member -MemberType NoteProperty -Name PrimarySMTPAddress -Value $mrstats.Alias
$i | Add-Member -MemberType NoteProperty -Name BatchName -Value $mrstats.BatchName
$i | Add-Member -MemberType NoteProperty -Name TotalMailboxSizeGB -Value $TotalMailboxSizeGBrounded
$i | Add-Member -MemberType NoteProperty -Name TransferredGB -Value $TransferredGBrounded
$i | Add-Member -MemberType NoteProperty -Name PercentComplete -Value $mrstats.PercentComplete
$i | Add-Member -MemberType NoteProperty -Name TotalMailboxItemCount -Value $TotalMailboxItemCount
$i | Add-Member -MemberType NoteProperty -Name ItemsTransferred -Value $ItemsTransferred
$i | Add-Member -MemberType NoteProperty -Name ItemsRemaining -Value $ItemsRemaining
$i | Add-Member -MemberType NoteProperty -Name OverallDuration -Value $mrstats.OverallDuration
$i | Add-Member -MemberType NoteProperty -Name TotalInProgressDuration -Value $mrstats.TotalInProgressDuration
$i | Add-Member -MemberType NoteProperty -Name TotalSuspendedDuration -Value $mrstats.TotalSuspendedDuration
$i | Add-Member -MemberType NoteProperty -Name ExchangeGuid -Value $mrstats.ExchangeGuid
$moveresults += $i
$totaldata = (($totaldata) + ($TotalMailboxSizeGB))
[INT64]$alltransferreddata = (($alltransferreddata) + ($TransferredGB))
}
Write-host "Analysis complete. Report saved to"$OutputFilename1
[System.DateTime]::Now
Get-PsSession | Remove-PsSession
$moveresults | sort PercentComplete | export-csv $OutputFilename1 -NoTypeInformation
$moverequeststosuspend = $moveresults | ?{$_.PercentComplete -ne 95}
[INT]$moverequeststosuspendCount = ($moverequeststosuspend).Count
$timenow = [System.DateTime]::Now
while($startsuspendtime -gt $now){write-progress -Activity "Waiting to suspend $moverequeststosuspendCount move requests at $($startsuspendtime)" -Status "Checking once per minute. Time last checked at $($now)"; sleep 60; $now = [System.DateTime]::Now}
write-progress -Activity "Waiting to suspend $moverequeststosuspendCount move requests at $($startsuspendtime)" -Status "Completed" -Completed
[System.DateTime]::Now
$warningPreference = "SilentlyContinue"
Import-PSSession $EXOnlineSession -warningaction silentlycontinue -erroraction silentlycontinue | Out-Null
$warningPreference = "Continue"
[INT]$counter = 0
Write-host "Suspending $moverequeststosuspendCount move requests..."
foreach($moverequesttosuspend in $moverequeststosuspend){
$counter ++
Write-Progress -Activity "Suspending $moverequeststosuspendCount move requests..." -Status "$counter of $moverequeststosuspendCount"
[String]$ExchangeGUID2 = $moverequesttosuspend.ExchangeGUID
Suspend-MoveRequest $ExchangeGUID2 -confirm:$false
}
[System.DateTime]::Now
Get-PsSession | Remove-PsSession
Office 365 move requests - random incremental sync interval
EMS:
There are two random number generation processes here. Firstly, a random number to change the sort order of the move requests (this is because with large numbers of move requests, the remote Exchange online PS connection can get terminated before the script completes - so the list order is changed each time the script is executed). Secondly, the time periods within the ranges specified are randomized, but only to minutes, not seconds).
The reason for the script? Because as move requests tend to be started in batches / migration batches, they generally start at the same time and there is more than a distinct possibility that they will achieve 95% sync status at the same time. As they are configured by default to 1 day, that may result in a large number of requests all wanting to do their incremental sync at the same time (possibly during business hours), which is not a good thing. Setting them to 12-24 hours in the first instance is a suggestion. Changing that to 1-3 hours in the run up to cutover is another suggestion (as the mailboxes are more likely to be synced at cutover time then).
The script checks for an Exchange online connection, although I advise closing any existing session and starting a new one each time.
[string]$ExchOnline = "outlook.office365.com"
If((Get-PsSession).Computername -ne $ExchOnline){Write-host -foregroundcolor yellow "The script requires a PsSession to $ExchOnline"; Exit}
Write-Progress -Activity "Getting the move requests" -Status "Working..."
$mrs = Get-moverequest -resultsize unlimited
[int]$rnd = get-random -Minimum 1 -Maximum 15
switch ($rnd)
{
1 {$mrs = $mrs | sort RunspaceId}
2 {$mrs = $mrs | sort RunspaceId -descending}
3 {$mrs = $mrs | sort ExchangeGuid}
4 {$mrs = $mrs | sort ExchangeGuid -descending}
5 {$mrs = $mrs | sort TargetDatabase}
6 {$mrs = $mrs | sort TargetDatabase -descending}
7 {$mrs = $mrs | sort Alias}
8 {$mrs = $mrs | sort Alias -descending}
9 {$mrs = $mrs | sort DisplayName}
10 {$mrs = $mrs | sort DisplayName -descending}
11 {$mrs = $mrs | sort ExternalDirectoryObjectId}
12 {$mrs = $mrs | sort ExternalDirectoryObjectId -descending}
13 {$mrs = $mrs | sort Guid}
14 {$mrs = $mrs | sort Guid -descending}
}
[INT]$counter = 0
[INT]$mrscount = ($mrs).count
[INT]$mintimein = Read-host "Specify the minimum number of minutes"
[INT]$maxtimein = Read-host "Specify the maximum number of minutes"
$mintime = $mintimein +1
$maxtime = $maxtimein +1
Foreach($mr in $mrs){
$rn = get-random -Minimum $mintime -Maximum $maxtime
$ts = [timespan]::fromminutes($rn)
[String]$randomoffest = "{0:HH:mm:ss}" -f ([datetime]$ts.ticks)
$counter++
Write-Progress -Activity "Randomizing incremental sync" -Status "$counter of $mrscount"
Set-MoveRequest $mr.exchangeguid -IncrementalSyncInterval $randomoffest
Write-host "The following IncrementalSyncInterval has been set`: $mr`: $randomoffest"
Clear-Variable rn,ts,randomoffest
}
There are two random number generation processes here. Firstly, a random number to change the sort order of the move requests (this is because with large numbers of move requests, the remote Exchange online PS connection can get terminated before the script completes - so the list order is changed each time the script is executed). Secondly, the time periods within the ranges specified are randomized, but only to minutes, not seconds).
The reason for the script? Because as move requests tend to be started in batches / migration batches, they generally start at the same time and there is more than a distinct possibility that they will achieve 95% sync status at the same time. As they are configured by default to 1 day, that may result in a large number of requests all wanting to do their incremental sync at the same time (possibly during business hours), which is not a good thing. Setting them to 12-24 hours in the first instance is a suggestion. Changing that to 1-3 hours in the run up to cutover is another suggestion (as the mailboxes are more likely to be synced at cutover time then).
The script checks for an Exchange online connection, although I advise closing any existing session and starting a new one each time.
[string]$ExchOnline = "outlook.office365.com"
If((Get-PsSession).Computername -ne $ExchOnline){Write-host -foregroundcolor yellow "The script requires a PsSession to $ExchOnline"; Exit}
Write-Progress -Activity "Getting the move requests" -Status "Working..."
$mrs = Get-moverequest -resultsize unlimited
[int]$rnd = get-random -Minimum 1 -Maximum 15
switch ($rnd)
{
1 {$mrs = $mrs | sort RunspaceId}
2 {$mrs = $mrs | sort RunspaceId -descending}
3 {$mrs = $mrs | sort ExchangeGuid}
4 {$mrs = $mrs | sort ExchangeGuid -descending}
5 {$mrs = $mrs | sort TargetDatabase}
6 {$mrs = $mrs | sort TargetDatabase -descending}
7 {$mrs = $mrs | sort Alias}
8 {$mrs = $mrs | sort Alias -descending}
9 {$mrs = $mrs | sort DisplayName}
10 {$mrs = $mrs | sort DisplayName -descending}
11 {$mrs = $mrs | sort ExternalDirectoryObjectId}
12 {$mrs = $mrs | sort ExternalDirectoryObjectId -descending}
13 {$mrs = $mrs | sort Guid}
14 {$mrs = $mrs | sort Guid -descending}
}
[INT]$counter = 0
[INT]$mrscount = ($mrs).count
[INT]$mintimein = Read-host "Specify the minimum number of minutes"
[INT]$maxtimein = Read-host "Specify the maximum number of minutes"
$mintime = $mintimein +1
$maxtime = $maxtimein +1
Foreach($mr in $mrs){
$rn = get-random -Minimum $mintime -Maximum $maxtime
$ts = [timespan]::fromminutes($rn)
[String]$randomoffest = "{0:HH:mm:ss}" -f ([datetime]$ts.ticks)
$counter++
Write-Progress -Activity "Randomizing incremental sync" -Status "$counter of $mrscount"
Set-MoveRequest $mr.exchangeguid -IncrementalSyncInterval $randomoffest
Write-host "The following IncrementalSyncInterval has been set`: $mr`: $randomoffest"
Clear-Variable rn,ts,randomoffest
}
MSOL license check
*Requires O365 admin account with Licensing permission*
PS:
[string]$DateTime = (Get-Date).Tostring("dd-MM-yyyy_HHmmss")
[string]$FilePath = "C:\Temp\"
[string]$Filename1 = "MSOL_LicenseCheck"
[string]$OutputFilename1 = [string]::Format($FilePath + $Filename1 + "_{0}.csv",$DateTime)
[string]$AccountSkuID = "#######"
$msolUsername = "########@########.onmicrosoft.com"
$msolpassword = Get-Content "C:\TEMP\EncryptedPasswords\########.txt" | ConvertTo-SecureString
$msolcredential = new-object -typename System.Management.Automation.PSCredential -argumentlist $msolUsername, $msolpassword
Write-Progress -Activity "Connecting to MSOL" -Status "Working..."
Connect-MsolService -Credential $msolcredential -WarningAction SilentlyContinue | Out-Null
Write-Progress -Activity "Connecting to MSOL" -Status "Working..." -Completed
Write-Progress -Activity "Getting MSOL users" -Status "Working..."
$msolusers = Get-MSOLUser -ALL
Write-Progress -Activity "Getting MSOL users" -Status "Working..." -Completed
[INT]$c = 0
[INT]$msoluserscount = ($msolusers).count
foreach($msoluser in $msolusers){
$c++
Write-Progress -Activity "Examining license status" -Status "$c of $msoluserscount" -PercentComplete ($c/$msoluserscount * 100)
$i = New-Object -TypeName PSObject
$i | Add-Member -MemberType NoteProperty -Name UserPrincipalName -Value $msoluser.UserPrincipalName
if ($msoluser.isLicensed -eq $false){
$i | Add-Member -MemberType NoteProperty -Name isLicensed -Value "False"
$i | Add-Member -MemberType NoteProperty -Name HasPlan -Value "False"
$i | Add-Member -MemberType NoteProperty -Name EXCHANGE_S_ENTERPRISE -Value "NA"
$i | Add-Member -MemberType NoteProperty -Name MCOSTANDARD -Value "NA"
}
if ($msoluser.isLicensed -eq $true -and $msoluser.licenses.AccountSkuId -notcontains $AccountSkuID){
$i | Add-Member -MemberType NoteProperty -Name isLicensed -Value "True"
$i | Add-Member -MemberType NoteProperty -Name HasPlan -Value "False"
$i | Add-Member -MemberType NoteProperty -Name EXCHANGE_S_ENTERPRISE -Value "NA"
$i | Add-Member -MemberType NoteProperty -Name MCOSTANDARD -Value "NA"
}
if ($msoluser.isLicensed -eq $true -and $msoluser.licenses.AccountSkuId -contains $AccountSkuID){
$i | Add-Member -MemberType NoteProperty -Name isLicensed -Value "True"
$i | Add-Member -MemberType NoteProperty -Name HasPlan -Value "True"
foreach($msoluserlicense in ($msoluser.licenses | ?{$_.accountskuid -eq $AccountSkuID})){
[INT]$servicestatuscount = ($msoluserlicense.servicestatus).count
0..($servicestatuscount - 1)| ForEach-Object{
if(($msoluserlicense.servicestatus[$_]).ServicePlan.ServiceName -eq "EXCHANGE_S_ENTERPRISE"){
[string]$status = ($msoluserlicense.servicestatus[$_]).provisioningstatus
$i | Add-Member -MemberType NoteProperty -Name EXCHANGE_S_ENTERPRISE -Value $status
}
if(($msoluserlicense.servicestatus[$_]).ServicePlan.ServiceName -eq "MCOSTANDARD"){
[string]$status = ($msoluserlicense.servicestatus[$_]).provisioningstatus
$i | Add-Member -MemberType NoteProperty -Name MCOSTANDARD -Value $status
}
}
}
}
$i | export-csv $outputfilename1 -NoTypeInformation -Append -Force
}
PS:
[string]$DateTime = (Get-Date).Tostring("dd-MM-yyyy_HHmmss")
[string]$FilePath = "C:\Temp\"
[string]$Filename1 = "MSOL_LicenseCheck"
[string]$OutputFilename1 = [string]::Format($FilePath + $Filename1 + "_{0}.csv",$DateTime)
[string]$AccountSkuID = "#######"
$msolUsername = "########@########.onmicrosoft.com"
$msolpassword = Get-Content "C:\TEMP\EncryptedPasswords\########.txt" | ConvertTo-SecureString
$msolcredential = new-object -typename System.Management.Automation.PSCredential -argumentlist $msolUsername, $msolpassword
Write-Progress -Activity "Connecting to MSOL" -Status "Working..."
Connect-MsolService -Credential $msolcredential -WarningAction SilentlyContinue | Out-Null
Write-Progress -Activity "Connecting to MSOL" -Status "Working..." -Completed
Write-Progress -Activity "Getting MSOL users" -Status "Working..."
$msolusers = Get-MSOLUser -ALL
Write-Progress -Activity "Getting MSOL users" -Status "Working..." -Completed
[INT]$c = 0
[INT]$msoluserscount = ($msolusers).count
foreach($msoluser in $msolusers){
$c++
Write-Progress -Activity "Examining license status" -Status "$c of $msoluserscount" -PercentComplete ($c/$msoluserscount * 100)
$i = New-Object -TypeName PSObject
$i | Add-Member -MemberType NoteProperty -Name UserPrincipalName -Value $msoluser.UserPrincipalName
if ($msoluser.isLicensed -eq $false){
$i | Add-Member -MemberType NoteProperty -Name isLicensed -Value "False"
$i | Add-Member -MemberType NoteProperty -Name HasPlan -Value "False"
$i | Add-Member -MemberType NoteProperty -Name EXCHANGE_S_ENTERPRISE -Value "NA"
$i | Add-Member -MemberType NoteProperty -Name MCOSTANDARD -Value "NA"
}
if ($msoluser.isLicensed -eq $true -and $msoluser.licenses.AccountSkuId -notcontains $AccountSkuID){
$i | Add-Member -MemberType NoteProperty -Name isLicensed -Value "True"
$i | Add-Member -MemberType NoteProperty -Name HasPlan -Value "False"
$i | Add-Member -MemberType NoteProperty -Name EXCHANGE_S_ENTERPRISE -Value "NA"
$i | Add-Member -MemberType NoteProperty -Name MCOSTANDARD -Value "NA"
}
if ($msoluser.isLicensed -eq $true -and $msoluser.licenses.AccountSkuId -contains $AccountSkuID){
$i | Add-Member -MemberType NoteProperty -Name isLicensed -Value "True"
$i | Add-Member -MemberType NoteProperty -Name HasPlan -Value "True"
foreach($msoluserlicense in ($msoluser.licenses | ?{$_.accountskuid -eq $AccountSkuID})){
[INT]$servicestatuscount = ($msoluserlicense.servicestatus).count
0..($servicestatuscount - 1)| ForEach-Object{
if(($msoluserlicense.servicestatus[$_]).ServicePlan.ServiceName -eq "EXCHANGE_S_ENTERPRISE"){
[string]$status = ($msoluserlicense.servicestatus[$_]).provisioningstatus
$i | Add-Member -MemberType NoteProperty -Name EXCHANGE_S_ENTERPRISE -Value $status
}
if(($msoluserlicense.servicestatus[$_]).ServicePlan.ServiceName -eq "MCOSTANDARD"){
[string]$status = ($msoluserlicense.servicestatus[$_]).provisioningstatus
$i | Add-Member -MemberType NoteProperty -Name MCOSTANDARD -Value $status
}
}
}
}
$i | export-csv $outputfilename1 -NoTypeInformation -Append -Force
}
Exchange online PS connection
PS:
#(Refer to post regarding encrypting credentials)
#Modify accordingly and save in PSProfile
[string]$ExchOnline = "outlook.office365.com"
$exolusername = "######@######.onmicrosoft.com"
$exolpassword = Get-Content "C:\TEMP\EncryptedPasswords\######.txt" | ConvertTo-SecureString
$Excredential = new-object -typename System.Management.Automation.PSCredential -argumentlist $exolusername, $exolpassword
#Called via a function:
Function EOL-Connect($Prefix){
$EXOnlineSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://$ExchOnline/powershell-liveid/ -Credential $Excredential -Authentication Basic -AllowRedirection -ErrorAction Stop
$warningPreference = "SilentlyContinue"
if($Prefix){Import-PSSession $EXOnlineSession -prefix $Prefix -warningaction silentlycontinue -erroraction silentlycontinue | Out-Null
write-host -backgroundcolor red -foregroundcolor yellow "Use command prefix: $Prefix"
}
else{Import-PSSession $EXOnlineSession -warningaction silentlycontinue -erroraction silentlycontinue | Out-Null}
$warningPreference = "Continue"
}
#(Refer to post regarding encrypting credentials)
#Modify accordingly and save in PSProfile
[string]$ExchOnline = "outlook.office365.com"
$exolusername = "######@######.onmicrosoft.com"
$exolpassword = Get-Content "C:\TEMP\EncryptedPasswords\######.txt" | ConvertTo-SecureString
$Excredential = new-object -typename System.Management.Automation.PSCredential -argumentlist $exolusername, $exolpassword
#Called via a function:
Function EOL-Connect($Prefix){
$EXOnlineSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://$ExchOnline/powershell-liveid/ -Credential $Excredential -Authentication Basic -AllowRedirection -ErrorAction Stop
$warningPreference = "SilentlyContinue"
if($Prefix){Import-PSSession $EXOnlineSession -prefix $Prefix -warningaction silentlycontinue -erroraction silentlycontinue | Out-Null
write-host -backgroundcolor red -foregroundcolor yellow "Use command prefix: $Prefix"
}
else{Import-PSSession $EXOnlineSession -warningaction silentlycontinue -erroraction silentlycontinue | Out-Null}
$warningPreference = "Continue"
}
Encrypt password (e.g. for use in PowerShell)
PS:
Defined as a function (e.g. to use in PSProfile)
function fcreds(){
$GetCredential = Get-Credential
[string]$usr = $GetCredential.username
[string]$Credfilename = $usr.split("@")[0]
$loc = "C:\TEMP\EncryptedPasswords\"
$out = $loc + $Credfilename + ".txt"
$GetCredential.Password | ConvertFrom-SecureString | Out-File $out
}
Defined as a function (e.g. to use in PSProfile)
function fcreds(){
$GetCredential = Get-Credential
[string]$usr = $GetCredential.username
[string]$Credfilename = $usr.split("@")[0]
$loc = "C:\TEMP\EncryptedPasswords\"
$out = $loc + $Credfilename + ".txt"
$GetCredential.Password | ConvertFrom-SecureString | Out-File $out
}
PowerShell profile
As per: https://technet.microsoft.com/en-us/library/ff461033.aspx (almost - just skip step 6)
PS:
$check = test-path $profile
if($check -eq $false){New-item –type file –force $profile}
Set-ExecutionPolicy RemoteSigned
PS:
$check = test-path $profile
if($check -eq $false){New-item –type file –force $profile}
Set-ExecutionPolicy RemoteSigned
One-liners
Re-vamping this blog a bit. You'll notice that I do often like to squeeze my scripts into one-liners a lot of the time.
$T1="Processing ";$T2=" (";$T3=" of ";$T4=")";$cnt=0
$cnt++;$Act=$T1+$var.identity+$T2+$cnt+$T3+$vars.count+$T4;$pc=(($cnt/$vars.count)*100);$pcs=[String]([System.Math]::Round($pc,0))+"`% complete";Write-Progress -PercentComplete $pc -Activity $Act -Status $pcs
Here is an example. This will get the mailbox databases in the Org and check whether they are on their Activation Preference 1 and provide output to the screen. I have more elaborate scripts but this is just to show how the progress bar works. Exchange 2007 & later, EMS - PS 2.0
$T1="Processing ";$T2=" (";$T3=" of ";$T4=")";$cnt=0
$dbs=get-mailboxdatabase | ?{$_.ReplicationType -ne "None"} | sort -unique | sort name
foreach ($db in $dbs){
$cnt++;$Act=$T1+$db.name+$T2+$cnt+$T3+$dbs.count+$T4;$pc=(($cnt/$dbs.count)*100);$pcs=[String]([System.Math]::Round($pc,0))+"`% complete";Write-Progress -PercentComplete $pc -Activity $Act -Status $pcs
$mdb = Get-MailboxDatabase $db | Select ActivationPreference,Server
$DbPrefSvr=$mdb.ActivationPreference | ?{$_.value -eq 1}
$DbPref=$DbPrefSvr.key.name;$DbNowSrv=$mdb.Server.name
If ($DbPref -ne $DbNowSrv){write-host -foregroundcolor yellow $DB "is on" $DbNowSrv "but should be on" $DbPref}
}
$CheckADServerSettings = Get-AdServerSettings; if(($CheckADServerSettings).ViewEntireForest -ne $true){Set-ADServerSettings -viewentireforest $true}
Basic Progress bar
$T1="Processing ";$T2=" (";$T3=" of ";$T4=")";$cnt=0
$cnt++;$Act=$T1+$var.identity+$T2+$cnt+$T3+$vars.count+$T4;$pc=(($cnt/$vars.count)*100);$pcs=[String]([System.Math]::Round($pc,0))+"`% complete";Write-Progress -PercentComplete $pc -Activity $Act -Status $pcs
Here is an example. This will get the mailbox databases in the Org and check whether they are on their Activation Preference 1 and provide output to the screen. I have more elaborate scripts but this is just to show how the progress bar works. Exchange 2007 & later, EMS - PS 2.0
$T1="Processing ";$T2=" (";$T3=" of ";$T4=")";$cnt=0
$dbs=get-mailboxdatabase | ?{$_.ReplicationType -ne "None"} | sort -unique | sort name
foreach ($db in $dbs){
$cnt++;$Act=$T1+$db.name+$T2+$cnt+$T3+$dbs.count+$T4;$pc=(($cnt/$dbs.count)*100);$pcs=[String]([System.Math]::Round($pc,0))+"`% complete";Write-Progress -PercentComplete $pc -Activity $Act -Status $pcs
$mdb = Get-MailboxDatabase $db | Select ActivationPreference,Server
$DbPrefSvr=$mdb.ActivationPreference | ?{$_.value -eq 1}
$DbPref=$DbPrefSvr.key.name;$DbNowSrv=$mdb.Server.name
If ($DbPref -ne $DbNowSrv){write-host -foregroundcolor yellow $DB "is on" $DbNowSrv "but should be on" $DbPref}
}
View entire forest
$CheckADServerSettings = Get-AdServerSettings; if(($CheckADServerSettings).ViewEntireForest -ne $true){Set-ADServerSettings -viewentireforest $true}
This one is useful if you have a Forest Root and you're working from a sub domain. I get that more often than you'd think. Exchange 2007 & later, EMS - PS 2.0
Full mailbox access, send as
EMS:
FULL MAILBOX ACCESS
Add full mailbox access for a user:
Add full mailbox access for a user (without automapping):
FULL MAILBOX ACCESS
Add full mailbox access for a user:
$mailbox = Read-host "Mailbox to be actioned upon"; $user = Read-host "User to be assigned full mailbox access"; Add-MailboxPermission -User $user -AccessRights
'FullAccess' -Identity $mailbox
$mailbox = Read-host "Mailbox to be actioned upon"; $user = Read-host "User to be assigned full mailbox access"; Add-MailboxPermission -User $user -AccessRights 'FullAccess' -Identity $mailbox -Automapping $false
Remove full mailbox access for a user:
$mailbox = Read-host "Mailbox to be actioned upon"; $user = Read-host "User to have full mailbox access REMOVED"; Remove-MailboxPermission -User $user -AccessRights 'FullAccess' -Identity $mailbox -Confirm:$false
SEND AS
Add 'send as' permission for a user:
$mailbox = Read-host "Mailbox to be actioned upon"; $user = Read-host "User to be assigned send-as permission"; Get-Mailbox $mailbox | Add-ADPermission -User $user -Extendedrights "Send As"
Remove 'send as' permission for a user:
$mailbox = Read-host "Mailbox to be actioned upon"; $user = Read-host "User to have send-as permission REMOVED"; Get-Mailbox $mailbox | Remove-ADPermission -User $user -Extendedrights "Send As" -Confirm:$false
Monitor message queues & alert
EMS:
[string]$smtpserver = <HTServer>
[string]$recipient = <e-mail of recipient for alerts>
[string]$hostserver = $env:computername
[string]$sender = $hostname + "@" + ($recipient -split ("@"))[1]
[string]$smtpserver = <HTServer>
[string]$recipient = <e-mail of recipient for alerts>
[string]$hostserver = $env:computername
[string]$sender = $hostname + "@" + ($recipient -split ("@"))[1]
write-host -foregroundcolor Cyan "This script will monitor message queues and create an alert if the queue message count threshold is exceeded"
$threshold = read-host "Specify a value for the threshold"
write-host -foregroundcolor Cyan "The timeout between messages is configurable"
$timeout = read-host "Specify a timeout in seconds"
$mins = $timeout/60
$HTS = (Get-ExchangeServer | ?{$_.IsHubTransportServer -eq "True"})
while($true){foreach ($HT in $HTS){Get-queue -server $HT | ?{$_.MessageCount -gt $threshold -and $_.DeliveryType -ne "ShadowRedundancy"}
$Queue = Get-queue -server $HT | ?{$_.MessageCount -gt $threshold -and $_.DeliveryType -ne "ShadowRedundancy"}
if ($Queue.MessageCount -gt $threshold -and $Queue.DeliveryType -ne "ShadowRedundancy"){write-host -foregroundcolor yellow "Sent mail"; $MSGQueue = $Queue | out-string; Send-MailMessage -To $recipient -From $sender -Subject "Queues alert - threshold=$threshold, timeout to next alert $mins minute(s)" -body "A message queue has triggered an alert: $MSGQueue" -SmtpServer $smtpserver; sleep $timeout}}; write-host -foregroundcolor green "Script running... Timeout="$timeout" second(s), Queue message threshold= "$threshold; sleep 5}
$threshold = read-host "Specify a value for the threshold"
write-host -foregroundcolor Cyan "The timeout between messages is configurable"
$timeout = read-host "Specify a timeout in seconds"
$mins = $timeout/60
$HTS = (Get-ExchangeServer | ?{$_.IsHubTransportServer -eq "True"})
while($true){foreach ($HT in $HTS){Get-queue -server $HT | ?{$_.MessageCount -gt $threshold -and $_.DeliveryType -ne "ShadowRedundancy"}
$Queue = Get-queue -server $HT | ?{$_.MessageCount -gt $threshold -and $_.DeliveryType -ne "ShadowRedundancy"}
if ($Queue.MessageCount -gt $threshold -and $Queue.DeliveryType -ne "ShadowRedundancy"){write-host -foregroundcolor yellow "Sent mail"; $MSGQueue = $Queue | out-string; Send-MailMessage -To $recipient -From $sender -Subject "Queues alert - threshold=$threshold, timeout to next alert $mins minute(s)" -body "A message queue has triggered an alert: $MSGQueue" -SmtpServer $smtpserver; sleep $timeout}}; write-host -foregroundcolor green "Script running... Timeout="$timeout" second(s), Queue message threshold= "$threshold; sleep 5}
Show Queues
EMS one liner:
$HTS = (Get-ExchangeServer | ?{$_.IsHubTransportServer -eq "True"}); while ($true){foreach ($HT in $HTS){Get-queue -server $HT | ?{$_.MessageCount -gt "0" -and $_.DeliveryType -ne "ShadowRedundancy"}}; write-host -foregroundcolor green "Next..."; sleep 15}
Subscribe to:
Posts (Atom)