PowerShell: Scripted RoboCopy

Sometimes you might have a server on a weak network link, or even a remote server with a slow connection. CommVault and other backup suites a lot of times will have difficulty dealing with these slow links and timing out. This is where the good ol’ robocopy program from Microsoft themselves comes in handy. Of course you can just run RoboCopy straight as a scheduled task, but you might want to get better tabs on what’s going on. One was to do this is through the PowerShell. It’s also a great script to get started with the powerful PowerShell and learn some basics. This script in particular backs up an entire partition (ignoring some system folders) which just hosted data to a centralized server and then e-mailed someone about the outcome and why. It also makes a log of everything it did, then keeps the logs in check so they don’t get out of control. Take a look, copy, paste, and enjoy!

#Function to define how to send an email. Must be available to the account used by the script.
function sendMail($message){
    #SMTP server name
    $smtpServer = "mail.domain.com"
    #Creating a Mail object
    $msg = new-object Net.Mail.MailMessage
    #Creating SMTP server object
    $smtp = new-object Net.Mail.SmtpClient($smtpServer)
    #Email structure
    $msg.From = "serverName@domain.com"
    $msg.ReplyTo = "serverName@domain.com"
    $msg.subject = "ServerName Backup"
    $msg.body = $message
    #Sending email

$logpath = "c:\log\robocopy-$date.txt"
$date = Get-Date -UFormat "%Y%m%d"
If (!(Test-Path $logpath)){ New-Item -ItemType file $logpath }
$timerun = Measure-Command {$process = Start-Process robocopy -ArgumentList "d:\ \\remoteserver\remoteshare /np /mir /mt64 /log:$logpath /xd 'D:\System Volume Information' 'D:\$RECYCLE.BIN' 'D:\RECYCLER'" -wait -NoNewWindow -PassThru}
$log = Get-Content $logpath -raw

if ($process.ExitCode -eq 0) {
        sendMail("Successful. Exit code 0. No files were copied. No failure was encountered. No files were mismatched. The files already exist in the destination directory; therefore, the copy operation was skipped. Backup completed in $timerun")
    elseif ($process.ExitCode -eq 1) {
        sendMail("Successful. Exit code 1. Backup completed successfully in $timerun")
    elseif ($process.ExitCode -eq 2) {
        sendMail("Successful. Exit code 2. There are some additional files in the destination directory that are not present in the source directory. No files were copied. Backup completed in $timerun")
    elseif ($process.ExitCode -eq 3) {
        sendMail("Successful. Exit code 3. Some files were copied. Additional files were present. No failure was encountered. Backup completed in $timerun")
    elseif ($process.ExitCode -eq 5) {
        sendMail("Successful. Exit code 5. Some files were copied. Some files were mismatched. No failure was encountered. Backup completed in $timerun")
    elseif ($process.ExitCode -eq 6) {
        sendMail("Successful. Exit code 6. Additional files and mismatched files exist. No files were copied and no failures were encountered. This means that the files already exist in the destination directory. Backup completed in $timerun")
    elseif ($process.ExitCode -eq 7) {
        sendMail("Successful. Exit code 7. Files were copied, a file mismatch was present, and additional files were present. Backup completed in $timerun")
    elseif ($process.ExitCode -eq 8) {
        sendMail("Warning. Exit code 8. Several files did not copy. Backup completed in $timerun")
    else {
        sendMail("Error. Backup did not complete successfully." + "`r`n`n" + $log)

#Now clean up log history so it doesn't get overgrown.
$Now = Get-Date 
$Days = "14"
$TargetFolder = "c:\logs"
$Extension = "*.txt"
$LastWrite = $Now.AddDays(-$Days)
$Files = Get-Childitem $TargetFolder -Include $Extension -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}
foreach ($File in $Files) {
    if ($File -ne $NULL) {
        Remove-Item $File.FullName | Out-Null