Link to home
Start Free TrialLog in
Avatar of MichaelOBrien
MichaelOBrien

asked on

Powershell Script to move 10GB of Exchange 2007 mailboxes

I want to be able to move a certain amount of mailboxes at night using a Powershell script.
The amount is up to but not exceeding my log file size which is currently 18GB.
I have about 40 SG/DB's and for various reasons they can grow.
I easily list mailbox sizes using something like:
Get-MailboxStatistics -database 'exmbox\sg4\db4' | Sort-Object TotalItemSize -Desc | Select -First 10 | ft DisplayName,@{label="TotalItemSize(KB)";expression={$_.TotalItemSize.Value.ToKB()}}, ItemCount
and can move some like this:
Get-MailboxStatistics -database 'exmbox\sg20\db20' | Sort-Object TotalItemSize -Desc | Select -First 2 | Move-Mailbox -TargetDatabase "exmbox\sg10\db10"

but what i don't know how to do is to count the size up to a certain size, putting each userid in an array to be perhaps piped into a move-mailbox command.

I also have some good example scripts for sanity checking, logging, e-mail reports but i lack the logic/syntax understand to do the counting part.  

Has anyone thought about this or have any suggestions??
Thanks, Michael
#############################
#                           #
#  Exchange 2007 Migration  #
#  Move-mailbox script      #
#  Date & Author            #
#			    #
#############################

# NOTE: to run PowerShell scripts, you need to set the PS execution poloicy "set-executionpolicy unrestricted"
 
# load the list of users - this must be 1 user alias per line
# the user list file must be in the same directory as this script
 
$users = get-content MoveMbx1.txt
# move em to a specific target database using 10 threads
$users | move-mailbox -TargetDatabase "MailboxServer\StorageGroup01\MailboxStore01" -MaxThreads 10 -confirm:$false
 
# put today's date in a variable
$date=get-date -uformat "%Y%m%d"
 
# read today's migration log and store it as $EMailBody
$EmailBody = get-content "C:\Program Files\Microsoft\Exchange Server\Logging\MigrationLogs\*$date*.xml"
 
# when done, send us an email with the log text
$SmtpClient = new-object system.net.mail.smtpClient 
$MailMessage = New-Object system.net.mail.mailmessage 
$SmtpClient.Host = "smtpserver.domain.com" 
$mailmessage.from = ("<emailaddress>@domain.com") 
$mailmessage.To.add("<emailaddress>@domain.com") 
$mailmessage.Subject = “MoveMbx1.ps1 script has completed” 
$mailmessage.Body = $EmailBody 
$smtpclient.Send($mailmessage)




# http://blogs.msdn.com/adamfazio/archive/2007/10/27/hey-exchange-2007-move-the-mailboxes-email-me-the-log-when-you-re-done.aspx

AND
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin 
  
$TargetDatabase = "Server\First Storage Group\Mailbox Database" 
$SourceFile = "c:\powershells\MoveMailbox\users.txt" 
$LogFile =  "c:\scripts\logs\MoveMailboxLog.txt" 
$error.Clear() 
  
write-output "*********************************************************************************************" | out-file -filepath $LogFile -append -noClobber 
write-output "" | out-file -filepath $LogFile -append -noClobber 
  
$UserList = Get-Content $SourceFile 
foreach($user in $UserList) 
{ 
     $message = "$(Get-Date) - Migrating User '$user' to " + $TargetDatabase 
     write-output $message | out-file -filePath $LogFile -append -noClobber  
     Get-Mailbox $user | Move-Mailbox -TargetDatabase $TargetDatabase -maxthreads 8 -BadItemLimit 5000 -SourceMailboxCleanupOptions DeleteSourceMailbox -IgnorePolicyMatch -confirm:$false  
     if($error.Count -ne 0) 
     { 
           write-output "$(Get-Date) - User '$user' failed migration" | out-file -filePath $logfile -append -noClobber 
           write-output "Error: " + $error[0].ToString() | out-file -filePath $logfile -append -noClobber 
           $error.Clear() 
     }  
     else 
     { 
           write-output "$(Get-Date) - Migration complete for user '$user'." | out-file -filepath $logfile -append -noclobber 
     } 
     write-output "" | out-file -filepath $LogFile -append -noClobber 
}

# XML file logging examples:
# Get-Mailbox ... | Move-Mailbox -TargetDataBase $DBtoUse -confirm:$false -maxthreads:10 -PreserveMailboxSizeLimit:$true -ReportFile "C:\temp\MoveMailbox\move.xml"
#
# Get-Content $SourceFile | Get-Mailbox | Move-Mailbox -TargetDatabase $TargetDatabase -maxthreads 8 -BadItemLimit 5000 -SourceMailboxCleanupOptions DeleteSourceMailbox -IgnorePolicyMatch -confirm:$false
#dir *.xml | foreach { 
#$xml = [xml](cat $_.fullname) 
#$xml."move-Mailbox".TaskFooter.Result | Select-Object @{n="MailboxName";e={$xml."move-Mailbox".TaskDetails.Item.MailboxName}},ErrorCount,CompletedCount,WarningCount 
#} 


# sample result 

#MailboxName ErrorCount CompletedCount WarningCount 
#----------- ---------- -------------- ------------ 
#joe bloggs1 0 1 0 
#joe bloggs2 0 1 0 
#joe bloggs3 0 1 0 
#
# http://powershellcommunity.org/Forums/tabid/54/aff/3/aft/4196/afv/topic/Default.aspx
#
# or filter
# ...|where {$_.ErrorCount -ne 0} 
# or
# ...|where {($_.ErrorCount -ne 0) -and ($_.WarningCount -ne 0)}

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of endital1097
endital1097
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of MichaelOBrien
MichaelOBrien

ASKER

That helped.  This is what I came up with:
Param($SourceDatabase,$TargetDatabase,$LogFile = "C:\scripts\logs\MailboxMoveLog.txt",$MoveAmountGB = 10)
$MailboxesInDB = Get-MailboxStatistics -database $SourceDatabase | Sort-Object TotalItemSize -Desc | Where {$_.TotalItemSize -lt 2GB} | Select -First 10
foreach ($Mailbox in $MailboxesInDB)
{  
    if (($MovedTotal += $Mailbox.TotalItemSize) -lt 10GB)             {                                                                 $Mailbox | Move-Mailbox -TargetDatabase $TargetDatabase -maxthreads 8 -BadItemLimit 5000 -confirm:$false

Open in new window