Monitor-MoveRequest.ps1 v1.8

#MSExchange #PowerShell

I know, I know I’m a slacker .. w h a t e v e r

So here is the in final script in a my 3 part Exchange 2010 move mailbox process. Change the bits that say “<CHANGE THIS>” .. let me know what you think

<#
.NOTES
NAME: Monitor-MoveRequest.ps1
AUTHOR: Paul Flaherty
Last Edit: v1.8 [30 March 2011]
v1.0 sometime    : A script it born
v1.1 09 Jun 2011 : Added more Move-Request status checking
v1.2 16 Jun 2011 : Changed the loop ot use email address instead of name
v1.3 21 Jun 2011 : Updated to collect overall duration properly
v1.4 30 Jul 2011 : Updated with last item in report
v1.5  4 Aug 2011 : Updated so Moverequest report is generated and emailed
v1.6 22 Nov 2011 : Updated the output to put the summary at the top
                  : Updated with colours on output
v1.7 23 Nov 2011 : Update summary to include GB Transferred
v1.7 30 Mar 2012 : Cleaned up screen output
.LINK
blogs.flaphead.com
.SYNOPSIS
This script performs some preflight checks for mailboxes moves
and should be run before a mailbox move
.DESCRIPTION
This script Monitors Exchange Server 2010 move-requests by generating a webpage
and sending an email once it is complete.
.OUTPUTS
  None
.EXAMPLE
Monitor-MoveRequest.ps1
Run the checks using the default csv file
#>
##########################################################################################
PARAM([String]$BatchName = $args[0],
      [String]$HTMLOutFolder = "E:PsMonHTML",
      [String]$Mailbox="")
$Error.Clear()
#########################################################################################
$AppName    = "Monitor-MoveRequest.ps1"
$AppVer     = "v1.8 [30 March 2011]"
$Today      = Get-Date
$ServerName = hostname
$RunUser    = ([System.Security.Principal.WindowsIdentity]::GetCurrent()).Name
##########################################################################################
#Display script name and version
##########################################################################################
CLS
Write-host " " $AppName -NoNewLine -foregroundcolor Green
Write-Host ": " $AppVer -foregroundcolor Green
Write-host "`n Run on $ServerName at $Today by $RunUser" -foregroundcolor Yellow
Write-Host "|——————————————————————-|`n"
##########################################################################################
$xPsCheck = Get-PSSnapin | Select Name | Where {$_.Name -Like "*Exchange*"}
If ($xPsCheck -eq $Null) {Add-PsSnapin Microsoft.Exchange.Management.PowerShell.e2010}
$xBatchName =$BatchName
If ($xBatchName -eq ""){
  #Check Environment Variables
  Write-Host "Checking Environment Variables .. " -NoNewLine
  $envBatchName = [environment]::GetEnvironmentVariable(‘BatchName’,’User’)
  Write-Host $envBatchName -Foregroundcolor Green
  $xBatchName = $envBatchName
}
Write-Host "Batch Name:….."$xBatchName
Write-Host "Mailbox:…….."$Mailbox
Write-Host "Output Folder:.."$HTMLOutFolder
$xHTMLoutFolder = $HTMLOutFolder
$UserList      = @()
$users2Migrate = @()
$htmlHeader = "
<META HTTP-EQUIV=’refresh’ CONTENT=’60’>
<Style>
  TABLE{border-width: 1px;padding: 1px;border-style: solid;border-color: black;border-collapse: collapse;}
  TD{border-width: 1px;padding: 1px;border-style: solid;border-color: black;}
  TH{font-family:’Arial’;font-size:12px;border-width: 1px;padding: 1px;border-style: solid;border-color: black;background-color:peachpuff;}
  TR{font-family:’Arial’;font-size:10px}
  P{font-family:’Arial’;}
</Style>"
$x="<META HTTP-EQUIV=’refresh’ CONTENT=’300′><Style>TABLE{font-family:VERDANA;font-size: 10pt; border-width: 1px;padding: 1px;border-style: solid;border-color: black;border-collapse: collapse;}TD{border-width: 1px;padding: 1px;border-style: solid;border-color: black;}TH{border-width: 1px;padding: 1px;border-style: solid;border-color: black;background-color:peachpuff;}</Style>";
If ($xBatchName -ne ""){
  Write-Host "Batch Name: " $xBatchName
  Write-Host "`nGetting users from move request " -noNewLine
  $GMR = Get-MoveRequest -BatchName $xBatchName -ResultSize unlimited
  $msgSubject1 = "From Batch $xBatchName"
  $xattachdir = $xBatchname
} #If ($xBatchName -ne "")
If ($Mailbox -ne ""){
  Write-Host "Mailbox Name: " $Mailbox
  Write-Host "`nGetting users from move request " -noNewLine
  $GMR = Get-MoveRequest $Mailbox -ResultSize unlimited
  $msgSubject1 = "for $Mailbox "
  $xattachdir = $Mailbox
} #If ($Mailbox -ne "")
IF ($GMR -eq $Null){
  Write-Host "No Users in BatchName, Exiting" -foregroundcolor red
  Exit
}ELSE{
  Write-Host $GMR.count "Found" -Foregroundcolor Green
} #IF ($GMR -eq $Null)
Write-Host "Getting mailbox information for users"
$GMBX = $GMR | Get-Mailbox
$GMBX | ForEach{
  $xUser = "" | Select Email
  $xUser.EMail+= $_.PrimarySmtpAddress.ToString()
  $users2Migrate += $xUser
} #ForEach
Write-Host "Checking Users .."
ForEach($xUser in $Users2Migrate){
  $tmpemail = $xUser.email
  Write-Host "-" $tmpemail
  $xUser = "" | Select Name, Email, IsValid, MoveStatus, ActualStatus, Pct, Duration, MailboxSize, ItemCount, ItemDone, BadItemsEncountered, SourceDatabase, TargetDatabase, MRSServerName, Transferred, TransferredPerMinute, PiQ, Message, Status
  #Check User is Valid
  $tmpmbx = Get-Mailbox $tmpemail
  $xUser.Name = $tmpmbx.name
  $xUser.Email = $tmpemail
  $xUser.IsValid =  $tmpmbx.isvalid
  if ($tmpmbx.isvalid -eq $True){$xUser.MoveStatus = "Unknown"}ELSE{$xUser.MoveStatus = "ERR";$xUser.IsValid = $False}
  $UserList += $xUser
} #ForEach($xUser
$tmpLoop  = $true
$tmpcount = $UserList.count
$position = $host.ui.rawui.cursorposition
While ($tmploop){
  $now = Get-Date;
  $host.ui.rawui.cursorposition=$position;
  Write-Host "–> REFRESH                 " -Foregroundcolor Green
  For($i=0;$i -le $TmpCount-1;$i++){
    $tmpname
= $UserList[$i].email #v1.2 <- $UserList[$i].name
    $tmpgmr = Get-MoveRequestStatistics $tmpname -IncludeReport
    $tmpstatus = $tmpgmr.Status
    $UserList[$i].ActualStatus    = $tmpstatus
    $UserList[$i].Pct = $tmpgmr.PercentComplete
    switch ($tmpstatus) {
      "AutoSuspended"         {$UserList[$i].MoveStatus = $tmpstatus}
      "Completed"             {$UserList[$i].MoveStatus = $tmpstatus}
      "CompletedWithWarning"  {$UserList[$i].MoveStatus = $tmpstatus}
      "Failed"                {$UserList[$i].MoveStatus = $tmpstatus}
      "Suspended"             {$UserList[$i].MoveStatus = $tmpstatus}
      default                 {$UserList[$i].MoveStatus = "Unknown"}
    } #Switch
    $tmpDur  = $tmpgmr | select OverallDuration
    $UserList[$i].Duration       = $tmpDur.OverallDuration.ToString()
    $UserList[$i].BadItemsEncountered = $tmpgmr.BadItemsEncountered
    $UserList[$i].ItemDone       = $tmpgmr.ItemsTransferred
    $UserList[$i].MailboxSize    = $tmpgmr.TotalMailboxSize
    $UserList[$i].ItemCount      = $tmpgmr.TotalMailboxItemCount
    $UserList[$i].SourceDatabase = $tmpgmr.SourceDatabase
    $UserList[$i].TargetDatabase = $tmpgmr.TargetDatabase
    $UserList[$i].MRSServerName  = $tmpgmr.MRSServerName
    $UserList[$i].Transferred    = $tmpgmr.BytesTransferred
    $UserList[$i].TransferredPerMinute = $tmpgmr.BytesTransferredPerMinute
    $UserList[$i].Message = $tmpgmr.Message
    $tmpPiQ = ($tmpgmr.PositionInQueue).ToString()
    $tmpLog = $tmpgmr.report.Entries | ForEach{$_.ToString()}
    $UserList[$i].Status =  $tmpLog[-1]
    $UserList[$i].PiQ = ($tmpPiQ.Split(" "))[0]
  } #UserList
  $host.ui.rawui.cursorposition=$position;
  Write-Host "–>              " -Foregroundcolor Green
  $tmpchk = 0
  $UserList | where{$_.MoveStatus -eq "Unknown"} | ForEach {$tmpchk ++}
  $xsumHTML = $UserList | group ActualStatus | Select @{Expression={$Now};Label="Now"}, Name, @{Expression={"!AR!" + $_.Count};Label="Count"}, @{Expression={"!AR!" + (($_.Group | Measure-Object Transferred -Sum).sum/1024/1024).ToString("n")};Label="MBTransferred"},  @{Expression={"!AR!" + (($_.Group | Measure-Object MailboxSize -Sum).sum/1024/1024).ToString("n")};Label="TotalMB"} | Sort Name
  $xsum     = $UserList | group ActualStatus | Select @{Expression={$Now};Label="Now"}, Name, Count, @{Expression={(($_.Group | Measure-Object Transferred -Sum).sum/1024/1024).ToString("n")};Label="MBTransferred"},  @{Expression={ (($_.Group | Measure-Object MailboxSize -Sum).sum/1024/1024).ToString("n")};Label="TotalMB"}
  $xsum | ft *
  Write-host "<– WAITING:          <–" -Foregroundcolor Red
  $position=$host.ui.rawui.cursorposition
  $position.y = $position.y -1
  $xhtml += "
<hr><Style>
  TABLE{border-width: 1px;padding: 1px;border-style: solid;border-color: black;border-collapse: collapse;}
  TD{border-width: 1px;padding: 1px;border-style: solid;border-color: black;}
  TH{font-family:’Arial’;font-size:12px;border-width: 1px;padding: 1px;border-style: solid;border-color: black;background-color:peachpuff;}
  TR{font-family:’Arial’;font-size:10px}
  P{font-family:’Arial’;}
</Style>" 
  $xhtml2  = $xsumHTML | ConvertTo-Html -Fragment
  $today = Get-Date
  $z="<B><FONT size=’2′ face=’VERDANA’>Move Requests ($xBatchName)</B></FONT><BR><FONT size=’1′ face=’VERDANA’>Last updated: $today</FONT></FONT><HR size=6 color=Green>[INSERTHERE]<br>"
  $xhtml = $userlist | Select Name, Email, IsValid, MoveStatus, ActualStatus, Pct, MailboxSize, ItemCount, ItemDone, SourceDatabase, TargetDatabase, MRSServerName, Transferred, TransferredPerMinute, @{Expression={$_.BadItemsEncountered};Label="BadItems"}, PiQ, Status | sort @{Expression="ActualStatus";Descending=$False}, @{Expression="Pct";Descending=$True}, Name | ConvertTo-Html -head $HtmlHeader  -Title "Move Requests" -body $z
  #Colour the HTML table up
  $txtFAILED   = @()
  $i=0; $xHTML | foreach{IF ($_ -like "*<td>Failed*"){ $txtFAILED+= $i}; $i++}
  $txtFAILED   | ForEach{$xHTML[$_] = $xHTML[$_].Replace("<tr>","<tr bgcolor=Red>")}
  $txtINPROGRESS = @()
  $i=0; $xHTML   | foreach{IF ($_ -like "*<td>InProgress*"){ $txtINPROGRESS += $i}; $i++}
  $txtINPROGRESS | ForEach{$xHTML[$_] = $xHTML[$_].Replace("<tr>","<tr bgcolor=ORANGE>")}
  $txtCOMPLETED = @()
  $i=0; $xHTML  | foreach{IF ($_ -like "*<td>Completed*"){ $txtCOMPLETED += $i}; $i++}
  $txtCOMPLETED | ForEach{$xHTML[$_] = $xHTML[$_].Replace("<tr>","<tr bgcolor=Lime>")}
  $txtCOMPLETION = @()
  $i=0; $xHTML  | foreach{IF ($_ -like "*<td>CompletionInProgress*"){ $txtCOMPLETION  += $i}; $i++}
  $txtCOMPLETION  | ForEach{$xHTML[$_] = $xHTML[$_].Replace("<tr>","<tr bgcolor=Yellow>")}
  #Colour the Summary HTML table up
  $txtFAILED   = @()
  $i=0; $xhtml2 | foreach{IF ($_ -like "*<td>Failed*"){ $txtFAILED+= $i}; $i++}
  $txtFAILED   | ForEach{$xHTML2[$_] = $xHTML2[$_].Replace("<tr>","<tr bgcolor=Red>")}
  $txtINPROGRESS = @()
  $i=0; $xHTML2   | foreach{IF ($_ -like "*<td>InProgress*"){ $txtINPROGRESS += $i}; $i++}
  $txtINPROGRESS | ForEach{$xHTML2[$_] = $xHTML2[$_].Replace("<tr>","<tr bgcolor=ORANGE>")}
  $txtCOMPLETED = @()
  $i=0; $xHTML2  | foreach{IF ($_ -like "*<td>Completed*"){ $txtCOMPLETED += $i}; $i++}
  $txtCOMPLETED | ForEach{$xHTML2[$_] = $xHTML2[$_].Replace("<tr>","<tr bgcolor=Li
me>")}
  $txtCOMPLETION = @()
  $i=0; $xHTML2  | foreach{IF ($_ -like "*<td>CompletionInProgress*"){ $txtCOMPLETION  += $i}; $i++}
  $txtCOMPLETION  | ForEach{$xHTML2[$_] = $xHTML2[$_].Replace("<tr>","<tr bgcolor=Yellow>")}
  $txtAR = @()
  $i=0; $xHTML2 | foreach{IF ($_ -like "*>!AR!*"){ $txtAR += $i;}; $i++}
  $txtAR | ForEach{$xHTML2[$_] = $xHTML2[$_].Replace(">!AR!"," align=right>")}
  $tmpHere = @()
  $i=0; $xHTML | foreach{IF ($_ -like "*[INSERTHERE]*"){ $tmpHere += $i}; $i++}
  $tmpHere | ForEach{$xHTML[$_] = $xHTML[$_].Replace("[INSERTHERE]",$xhtml2)}
  $xhtml| Out-File $xHTMLoutFolderMoveRequestinProgress.html
  $tmpPosition = $position;
  $tmpPosition.x = $tmpPosition.x + 12
  If($tmpChk -eq 0){
    $tmpLoop = $False
  }ELSE{
    FOR($i=0;$i -le 10;$i++){
      Sleep 2
      $host.ui.rawui.cursorposition=$tmpposition; 
      Write-Host "#" -foregroundcolor Red
      $tmpPosition.x = $tmpPosition.x + 1
    } #FOR($i=0;$i -le 10;$i++)
  } #If($tmpChk -eq 0)
} #While ($tmploop)
$xsum = $UserList | group ActualStatus | Select Name, Count, @{Expression={(($_.Group | Measure-Object Transferred -Sum).sum/1024/1024/1024).ToString("n")};Label="GB Transferred"}
$xhtml2 = $xsum | ConvertTo-Html -Fragment
$today = Get-Date; $z="<B><FONT size=’2′ face=’VERDANA’>Move Requests ($xBatchName)</B></FONT><BR><FONT size=’1′ face=’VERDANA’>Last updated: $today</FONT></FONT><HR size=6 color=Green>"  + $xhtml2 + "<br>"
$OutHTML = $UserList | Select Name, Email, IsValid, MoveStatus, ActualStatus, Pct, Duration, MailboxSize, ItemCount, BadItemsEncountered, SourceDatabase, TargetDatabase, MRSServerName, message | ConvertTo-Html -head $HtmlHeader  -Title "Move Requests" -body $z
$xEnd = get-Date
$OutHTML += "
<HR size=6 color=Green>
<FONT size=’1′ face=’VERDANA’>Run by $CurrentUser. Script Completed: $xEnd</FONT>
</FONT><BR></BODY>
</HTML>
"
$OutHTML | Out-File $xHTMLoutFolderMoveRequestinProgress.html
$txtRED    = @()
$i=0; $OutHTML | foreach{IF ($_ -like "*<td>Failed*"){ $txtRED += $i}; $i++}
$txtRED | ForEach{$OutHTML[$_] = $OutHTML[$_].Replace("<tr>","<tr bgcolor=Red>")}
$logfiles=@()
ForEach($yUser in $UserList){
  $logfile = $Datefolder+""+$xBatchname+"_MoveRequestReport_" + $yuser.email + ".txt"
  $movereport=(Get-MoveRequestStatistics $yUser.email -IncludeReport).report
  $log = $movereport.Entries | ForEach{$_.ToString()}
  $log | Out-File $logfile
  $logfiles += $logfile
}
  Write-Host "`nSending Email" -Foregroundcolor Red
  $emailTo    = "<CHANGE THIS>"
  $emailFrom  = "<CHANGE THIS>"
  $SMTPServer = "<CHANGE THIS>"
  $msgsubject  = "PSM: Move Request Information " + $msgSubject1
  $message = New-Object Net.Mail.MailMessage($emailFrom, $emailTo, $msgsubject, $outHTML)
  $message.IsBodyHTML = $True
  Write-Host "- Adding log attachments" -Foregroundcolor Green
  $logfiles | ForEach{
    $_
    $attachment = New-Object System.Net.Mail.Attachment $_
    $message.Attachments.Add($attachment)
  }
  $smtp = New-Object Net.Mail.SmtpClient($SMTPServer)
  $smtp.Send($message)
  [environment]::SetEnvironmentVariable(‘BatchName’, ”,’User’)
#End

Move-RequestFromCSV.ps1 v1.5

#MSExchange

I know, I should have posted this a few weeks back .. w h a t e v e r

So this is Script #2 of my 3 script process to move mailboxes.

The process is here: Moving Mailboxes the easy way and script #1 is here: Pre-FlightChecks.ps1 v1.4

<#
.NOTES
NAME: Move-RequestFromCSV.ps1
AUTHOR: Paul Flaherty
Last Edit: v1.5 [8 April 2012]
v1.0 sometime    : A script it born
v1.1 20 May 2011 : Remove monitoring bit from script
v1.2 01 Jul 2011 : Updated to take the BatchName and CSVin as Parameters
v1.3 12 Oct 2011 : Updated with auto switch to skip the read-host question
v1.4 13 Jan 2012 : Updated with BadItemLimit and MRSServer switch
v1.5 08 Apr 2012 : Added Database switch
                    Due to some issue running the monitor script at the end, the script now sets
                    an Environment Variable that the monitor script can use.
.LINK
blogs.flaphead.com
.SYNOPSIS
This script creates Move Requests from a csv file
.DESCRIPTION
This script imports a list of smtp addresses from a CSV file and generates new move requests.
The move requests have either an auto generated or manual batch name assosciated with them.
If the CSV file that is being used has two columns: Email and TargetDatabase, the script
will use the TargetDatabase as the destination of the move request.
If no TargetDatabase is specified it will let Exchange do what it does best an decide
.OUTPUTS
  None
.EXAMPLE
Move-RequestFromCSV.ps1
Run the checks using the default csv file
.EXAMPLE
Move-RequestFromCSV.ps1 -Auto
Run the checks using the default csv file, but skips the "press any key" prompt once the
user validation is complete
This is specially useful if the script is used from either a batch file or scheduled task
.EXAMPLE
Move-RequestFromCSV.ps1 -CSVin <csvfile>
Uses the provided CSV file for the list of users
.EXAMPLE
$DB=@();Get-MailboxDatabase DATABASE.UK07* | ForEach{$db += $_.name}
Move-RequestFromCSV.ps1 -Database $db
This will use the Databases found in $db and round robin the move request to the databases
.PARAMETER CSVin
Input csv file that contains a list of email addresses and has a single heading of email
Optionally, if the CSV file contains an additional heading of TargetDatabase the script
will use this value to specify the target database for the move
.PARAMETER BatchName
This switch will remove existing move requests if they already exist
.PARAMETER Auto
Enabling this switch stops the need to "press any key" once the users have  been checked
.PARAMETER BadItemCount
This is the BadItemCount for MoveRequests
Default value is 30
.PARAMETER MRSServer
If needed you can specify a specific MRSServer to use
.PARAMETER Database
Use this parameter to select the databases you want the moverequest to use.
The script will use the list of databases in round robin stylie for each of the
move requests
#>
##########################################################################################
PARAM([String]$CSVin="C:MigrationListmiguserlist.csv",
      [String]$BatchName,
      [Switch]$Auto=$False,
      [String]$BadItemLimit=30,
      [String]$MRSServer="",
      [String]$Database="")
$Error.Clear()
CLS
#########################################################################################
$AppName = "Move-RequestFromCSV.ps1"
$AppVer  = "v1.5 [8 April 2012]"
##########################################################################################
#Load Common Variables
$today      = Get-Date
$RunUser    = ([System.Security.Principal.WindowsIdentity]::GetCurrent()).Name
##########################################################################################
#Display script name and version
##########################################################################################
Write-host " " $AppName -NoNewLine -foregroundcolor Green
Write-Host ": " $AppVer -foregroundcolor Green
Write-host "`n Run on $ServerName at $Today by $RunUser" -foregroundcolor Yellow
Write-Host "|——————————————————————-|`n"
$xPsCheck = Get-PSSnapin | Select Name | Where {$_.Name -Like "*Exchange*"}
If ($xPsCheck -eq $Null) {Add-PsSnapin Microsoft.Exchange.Management.PowerShell.e2010}
If ($BatchName -ne ""){
  $xBatchName = $BatchName
} ELSE {
  $xBatchName = get-date -Format "yyyy-MMM-dd_HH-mmm-ss"
  $xBatchName = "UK-" + $xBatchName
}
Write-Host "Batch Name:….$xBatchName"
Write-Host "BadItemLimit:..$BadItemLimit"
Write-Host "MRSServer:…..$MRSServer"
Write-Host "Database:……$Database"
$UserList   = @()
$doMove     = $True
Write-Host "Checking to see if $csvin exists"
If(test-path $csvin){
  Write-host "$csvin found" -foregroundcolor Green
}else{
  Write-host "$csvin not found" -foregroundcolor red
  exit
}
$users2Migrate = import-csv $csvin
Write-Host "Checking Users .."
ForEach($yUser in $Users2Migrate){
  $tmpemail = $yUser.email
  $xUser = "" | Select Name, Email, IsValid, MoveStatus, ActualStatus, PercentComplete, Duration, MailboxSize, ItemCount, BadItemsEncountered, SourceDatabase, TargetDatabase, MRSServerName, Transferred, TransferredPerMinute
  #Check User is Valid
  $tmpmbx = Get-Mailbox $tmpemail
  $tmpmbx
  $xUser.Name = $tmpmbx.name
  $xUser.Email = $tmpemail
  $xUser.IsValid =  $tmpmbx.isvalid
  $xUser.TargetDatabase = $yUser.TargetDatabase
  if ($tmpmbx.isvalid -eq $True){$xUser.MoveStatus = "Unknown"}ELSE{$xUser.MoveStatus = "ERR";$xUser.IsValid = $False}
  $UserList += $xUser
}
$tmpInvalid = $UserList | Where {$_.IsValid -eq $False}
$tmpValid   = $UserList | Where {$_.IsValid -ne $False}
Write-Host "`nThe following users are InValid and will not be migrated" -Foregroundcolor Red
$tmpInvalid | Select Email
Write-Host "`nThe following users will be migrated" -Foregroundcolor Green
$tmpValid | Select Email, TargetDatabase
If($aut
o -eq $False){read-host "Press Enter to Generate Move Requests or CTRL C to exit"}
If ($Database -ne ""){
  $tmpDatabaseArray = $database.split(" ")
  $i=0
  $DatabaseHashTable = @{}
  ForEach($item in $tmpDatabaseArray){; $DatabaseHashTable.Add($i,$item); $i++}
}
Write-Host "Creating Move Requests"
Write-Host "BadItemLimit: "$BadItemLimit
$i=0
$UserList | Where {$_.IsValid} | ForEach{
  $tmpemail = $_.Email
  $tmpTargetDatabase = $_.TargetDatabase
  Write-Host $tmpname " – " $tmpemail
  $tmpcmdlet = "Get-Mailbox $tmpemail | New-MoveRequest -BatchName $xBatchName -BadItemLimit:$BadItemLimit"
  If ($MRSServer -ne ""){Write-Host "MRSServer: $MRSServer"; $tmpcmdlet += " -MRSServer $MRSServer "}
  If ($Database -ne ""){
    $tmpDatabase = $tmpDatabaseArray[$i]
    Write-Host "Database: $tmpDatabase";
    $tmpcmdlet += " -TargetDatabase $tmpDatabase"
    If($i -ge ($DatabaseHashTable.count)-1){$i=0}ELSE{$i++}
  }ELSE{
    If($tmpTargetDatabase -ne $null){    $tmpcmdlet += " -TargetDatabase $tmpTargetDatabase "}
  }
  Invoke-Expression $tmpcmdlet
}
Get-MoveRequest -BatchName $xBatchName
$csvRename = ($csvin.split("."))[0] + "_" + $xBatchName + ".csv"
Write-host "Renaming csv files to $csvrename" -foregroundcolor yellow
Ren $csvin $csvRename
Write-Host "Waiting 30 Seconds while AD Catches up!"
Sleep 30
Write-Host "You can now run:"
Write-Host "C:PSMigrationMonitor-MoveRequest.ps1 "$xBatchName
Write-Host "-or-"
Write-Host "C:PSMigrationMonitor-MoveRequest.ps1"
[environment]::SetEnvironmentVariable(‘BatchName’, $xBatchName,’User’)
[environment]::GetEnvironmentVariable(‘BatchName’,’User’)
#End

Exchange Server 2010 MCM

#MSExchange #MCM

So I worked for Microsoft for 6 1/2 years.  Then I had my first contracting gig designing and installing Exchange 2007 for a UK Bank.  Since then I have moved along on to Exchange 2010.

The MCM or Ranger program as it used to known (to me anyway) is the best of the best, the top gun of Microsoft Exchange!  Even when at Microsoft and now being an independent contractor, it is something I have always wanted to do, but the sheer cost of the course, excluding flights, accommodation and the unpaid holiday I would have to take, make it too rich for my blood.I totally understand the course costing and are fine with that, I suspect the thing that gets me is that “some” Microsoft partners are able to get a discount on the course cost!  Hey wonder if it would be done over live meeting, to a global audience, sitting at home or in a Microsoft office?

So I thought, how about the “poor mans” version, it could be interesting, and exam and a qual lab are doable!  So I paid the $500 for 088-974 and booked it for 18th April at Prometric in London.  So I take a day off and rock up at the allotted time, only to find out that my exam has been cancelled.  They said they hadn’t had the “training” to be able to run the exam for me .. WTF i thought, I had a go and waited for them to call me to rearrange.

So yesterday 2nd May I took another day off and went for the exam.  It appears I was the first to take it at Prometrc in London, so they have to run around to try and work out what they needed to do.  This started with a biometric check, and the a hunt for passwords, but then I was off.

So 60 Questions and 3hrs (I need just over 2), with everything from DAG design to RBAC to Powershell cmdlets, Lync integration and UM. It wasn’t easy, some answers where calculated finger in air answers, but it wasn’t as hard as I thought.  I would probably give a 7/10.  What I was disappointed about is my exam had no mention of any RFCs and the documented readiness and exam preparation was over kill.  I reckon you could get away with a good read of Microsoft Exchange Server 2010 Inside Out.  I would be nice to have a more concise list of stuff to read!

If I am honest to myself, I would be surprised if I passed, but I am going to have to wait 30 days to find out.

Its funny,thinking about my expectations for the exam, I’m not sure what they were. I know a few Exchange MCM and one in particular is awesome.  I suppose I was expecting more real world questions, like a bunch of scenarios and design decisions to agree with or not, but that can be hard to articulate with multi-choice answers.  Maybe some of the questions where you drag and drop answers or arrange things in order would be good.  Some of questions, in the real world I would have just searched for the answer.

My impression of an MCM is someone that is like a Swiss army knife.  They can standing in front of customers and sell exchange, they can design it, they can support it.  They can also parachute in to hostile customers Winking smile and fix issues, all knowing they have the backing and support of the Exchange Product Team. .. Doesn’t that just make you want to be one?!  You could be one of the GI Joe or Jane of the Exchange world Disappointed smile

I’ll get off my soap box now.  If your up for it, give it a go! .. but be afraid very afraid, its not a walk in the park and you have to know your sh1t. The Exam and Lab rock in at $3,000 but just look at the rewards .. and I will keep dreaming of 3 weeks in Redmond doing it the “proper way”