Robocopy is a free tool from Microsoft that was originally part of Windows Resource Kit for Windows NT 4. It was then included as a standard feature with Windows Server 2003 and each subsequent release of Windows Server. It is a powerful tool for transferring data from 1 place to another. You can transfer data from 1 folder to another on the same server or between 2 servers provided you use an account with permissions on both servers. There are extensive command switches available to control how the data transferred such as preserving ACL permissions, directory structures, and even empty folders. The basic syntax is as follows:
robocopy Source Destination [File[ ...]] [Options]
Recently I had to transfer nearly 50 GB of data from a legacy server to a new server. This migration was occurring on 2 production mail servers and there would be a impact to users so downtime needed to be minimal. I had done thorough testing so I knew it was going to take approximately 3 hours to transfer the data.
Since I was transferring the data from a legacy server to a new Windows 2008 R2 server I planned to initiate robcopy from the new server. By doing this I was able to use the /MT multi-threading switch. I had done several tests using different values for this switch and settled on 32. Increasing the value beyond 32 did not produce any noticeable difference in transfer speed. Without using the switch I was consistently seeing 150 MB/min transfer speeds. Here is the syntax that I used:
robocopy.exe "\\oldserver\bigfolder" "D:\newfolder" /LOG:d:\temp\log.txt /MT:32 /E /W:5 /Z /V /R:6
I knew that once I initiated the robocopy job there was nothing else I could do other than wait for the data transfer to finish. Furthermore, I did not want to have to frequently check the destination server to know how the transfer was progressing. So I needed a way to count the folders as they showed up on the destination server and then send me an email.
The solution to this was to leverage the power of Windows Script Host which is native to Windows 2008 servers. Using Vbscript I could easily create a script to count folders in a directory and then send myself an email. The 2nd half of this challenge was to have that script run every 10 minutes which I explain later in this post.
Using Vbscript I create a function that will check a folder and return count of folders it contains.
function countFolders(strPath) dim objShell dim objFolder dim folderCount set objShell = CreateObject("shell.application") set objFolder = objShell.NameSpace(strPath) if (not objFolder is nothing) then dim objFolderItems set objFolderItems = objFolder.Items if (not objFolderItems Is Nothing) then folderCount=objFolderItems.Count end if set objFolderItem = nothing end if set objFolder = nothing set objShell = nothing countFolders=folderCount end functionNext I needed to create a function that would send an email with the folder count. I format the message so that the pertinent details are in the subject line.
Function SendCount(strCount) Set objMessage = CreateObject("CDO.Message") objMessage.Subject = strCount objMessage.From = "email@example.com" objMessage.To = "firstname.lastname@example.org" objMessage.TextBody = strCount objMessage.Configuration.Fields.Item _ ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2 'Name or IP of Remote SMTP Server objMessage.Configuration.Fields.Item _ ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "mail.mydomain.com" 'Server port (typically 25) objMessage.Configuration.Fields.Item _ ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25 objMessage.Configuration.Fields.Item _ ("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 1 objMessage.Configuration.Fields.Item _ ("http://schemas.microsoft.com/cdo/configuration/smtpusessl") = false objMessage.Configuration.Fields.Item _ ("http://schemas.microsoft.com/cdo/configuration/sendusername") = "email@example.com" objMessage.Configuration.Fields.Item _ ("http://schemas.microsoft.com/cdo/configuration/sendpassword") = "xyz123" objMessage.Configuration.Fields.Update objMessage.Send End FunctionSo now that I’ve got my two functions I need to code how they’ll be used. I create local variables for the destination path that is going to be monitored, the total number of folders being copied, and a counter.
Option Explicit Dim destFolder Dim maxFolders Dim folderCount destFolder="d:\destinationfolder" maxFolders=500 folderCount=countFolders(destFolder) sendCount("F: " & folderCount & " " & FormatPercent(folderCount/maxFolders))At this point the script is ready to run. I knew there were 500 folders being copied to the new server so each time the script was run it would send me an email with the number of folders copied and the % complete. In the beginning of this post I indicated I need this to be automated so the next step is to login to the destination server and create a scheduled task to run our new script. Since I know from testing this transfer will take approximately 3 hours I schedule the task to end after 3 hours but I want it to run every 10 minutes until then.