#\r
# Author: Patrick Canterino <patrick@patrick-canterino.de>\r
# WWW: https://www.patrick-canterino.de/\r
-# https://github.com/pcanterino/dsmonrot/\r
+# https://github.com/pcanterino/dsmonrot\r
# License: 2-Clause BSD License\r
#\r
# Drive Snapshot is copyright by Tom Ehlert\r
\r
# Path to backup directory\r
[String]$backupDir = "Z:\"\r
-# Keep backup for this amount of months (excluding the current month), -1 for indefinite\r
+# Keep backup for this amount of months (excluding the current month),\r
+# -1 for indefinite\r
[Int32]$keepMonths = 2\r
+# Rotate BEFORE the beginning of a full backup (default is after a successful\r
+# full backup)\r
+# WARNING: If this option is set to $True and the full backup fails you could\r
+# have NO backup\r
+$rotateBeforeBackup = $False\r
# Path to Drive Snapshot\r
[String]$dsPath = "C:\Users\Patrick\Desktop\DSMonRot\snapshot.exe"\r
-# Path to Drive Snapshot log file\r
-[String]$dsLogFile = "C:\Users\Patrick\Desktop\DSMonRot\snapshot.log"\r
+# Path to Drive Snapshot log file (specify only the file name if you set\r
+# $dsLogFileToBackup to $True)\r
+#[String]$dsLogFile = "C:\Users\Patrick\Desktop\DSMonRot\snapshot.log"\r
+[String]$dsLogFile = "snapshot.log"\r
+# Set to $True if you want to put the log file of Drive Snapshot into the same\r
+# directory as the backup\r
+[Boolean]$dsLogFileToBackup = $True\r
# Disks to backup, see http://www.drivesnapshot.de/en/commandline.htm\r
[String]$disksToBackup = "HD1:1"\r
# Path to DSMonRot log file\r
# To address of email notification\r
[String]$emailToAddress = "patrick@test.local"\r
# Subject of email notification\r
-[String]$emailSubject = "DSMonRot"\r
+[String]$emailSubject = "DSMonRot on $env:computername"\r
# Mail server\r
[String]$emailMailserver = "localhost"\r
# SMTP Port\r
\r
# End of config\r
\r
-$dsAdditionalArgs = @("--logfile:$dsLogFile", "--UseVSS")\r
+$dsAdditionalArgs = @("--UseVSS")\r
\r
# Allow SMTP with SSL and SMTP Auth\r
# see: http://petermorrissey.blogspot.de/2013/01/sending-smtp-emails-with-powershell.html\r
Write-Host "Sending email: $emailToAddress, $body"\r
\r
try {\r
- $smtp = New-Object System.Net.Mail.SmtpClient($emailMailServer, $emailPort);\r
+ $smtp = New-Object System.Net.Mail.SmtpClient($emailMailServer, $emailPort)\r
\r
$smtp.EnableSSL = $emailSSL\r
\r
if($emailAuth) {\r
- $smtp.Credentials = New-Object System.Net.NetworkCredential($emailUser, $emailPassword);\r
+ $smtp.Credentials = New-Object System.Net.NetworkCredential($emailUser, $emailPassword)\r
}\r
\r
- $smtp.Send($emailFromAddress, $emailToAddress, $emailSubject, $body);\r
+ $smtp.Send($emailFromAddress, $emailToAddress, $emailSubject, $body)\r
}\r
catch {\r
Write-Host "Could not send email: $_.Exception.Message"\r
}\r
}\r
\r
+function Rotate-Backup {\r
+ if($keepMonths -lt 0) {\r
+ return\r
+ }\r
+\r
+ Write-Host "Rotating"\r
+ \r
+ $keepMonthsCount = $keepMonths\r
+ \r
+ Get-ChildItem $backupDir -Directory | Where-Object {($_.Name -ne $currMonth) -and ($_.Name -match "^\d{4,}-\d{2}$")} | Sort-Object -Descending |\r
+ Foreach-Object {\r
+ Write-Host $_ "=>" $_.FullName\r
+ \r
+ if($keepMonthsCount -ge 0) {\r
+ $keepMonthsCount--\r
+ }\r
+ \r
+ if($keepMonthsCount -eq -1) {\r
+ Write-Host "Deleting $_"\r
+ Remove-Item -Recurse -Force $_.FullName\r
+ }\r
+ }\r
+}\r
+\r
+$startTime = Get-Date -format "yyyy-MM-dd HH:mm:ss"\r
+Write-Host "Started at $startTime"\r
+\r
$errorMessages = @()\r
\r
$smbConnected = $False\r
$success = $False\r
+$isDiff = $False\r
+$dsCommand = ""\r
\r
if($smbDrive) {\r
- Try {\r
+ try {\r
Write-Host "Connecting network drive"\r
\r
if($smbUser -and $smbPassword) {\r
$secSmbPassword = $smbPassword | ConvertTo-SecureString -asPlainText -Force\r
$smbCredential = New-Object System.Management.Automation.PSCredential($smbUser, $secSmbPassword)\r
\r
- New-PSDrive -Name $smbDrive -PSProvider "FileSystem" -Root $smbPath -Credential $smbCredential -Persist -ErrorAction Stop\r
- #net use "$smbDrive`:" $smbPath $smbPassword /user:$smbUser\r
+ New-PSDrive -Name $smbDrive -PSProvider "FileSystem" -Root $smbPath -Credential $smbCredential -Persist -ErrorAction Stop | Out-Null\r
}\r
else {\r
Write-Host "Without credentials"\r
\r
- New-PSDrive -Name $smbDrive -PSProvider "FileSystem" -Root $smbPath -Persist -ErrorAction Stop\r
- #net use "$smbDrive`:" $smbPath\r
+ New-PSDrive -Name $smbDrive -PSProvider "FileSystem" -Root $smbPath -Persist -ErrorAction Stop | Out-Null\r
}\r
\r
$smbConnected = $True\r
}\r
- Catch {\r
- Write-Host "Could not connect to network drive: $_.Exception.Message"\r
- exit\r
+ catch {\r
+ Write-Host "Could not connect to network drive $smbDrive`: $_.Exception.Message"\r
+ $errorMessages += "Could not connect to network drive $smbDrive`: $_.Exception.Message"\r
}\r
}\r
\r
if(!(Test-Path $backupDir)) {\r
Write-Host "Directory $backupDir does not exist!"\r
- exit\r
+ $errorMessages += "Directory $backupDir does not exist!"\r
}\r
\r
-$currMonth = Get-Date -format "yyyy-MM"\r
-$currDay = Get-Date -format "yyyy-MM-dd"\r
-\r
-Write-Host $currMonth\r
+if($errorMessages.Count -eq 0) {\r
+ $currMonth = Get-Date -format "yyyy-MM"\r
+ $currDay = Get-Date -format "yyyy-MM-dd"\r
\r
-$backupTarget = $backupDir + "\" + $currMonth\r
-$backupTargetFull = $backupTarget + "\" + "Full"\r
+ Write-Host $currMonth\r
\r
-$backupTargetDiff = $backupTarget + "\" + "Diff-" + $currDay\r
+ $backupTarget = $backupDir + "\" + $currMonth\r
+ $backupTargetFull = $backupTarget + "\" + "Full"\r
\r
-Write-Host $backupTarget\r
+ $backupTargetDiff = $backupTarget + "\" + "Diff-" + $currDay\r
\r
-$isDiff = $False\r
+ Write-Host $backupTarget\r
\r
-if((Test-Path $backupTarget) -and (Test-Path $backupTargetFull) -and (Test-Path "$backupTargetFull\*.hsh")) {\r
- Write-Host "Differential backup"\r
- \r
- $isDiff = $True\r
- \r
- if(!(Test-Path $backupTargetDiff)) {\r
- Write-Host "Creating directory $backupTargetDiff"\r
+ if((Test-Path $backupTarget) -and (Test-Path $backupTargetFull) -and (Test-Path "$backupTargetFull\*.hsh")) {\r
+ Write-Host "Differential backup"\r
\r
- try {\r
- New-Item -ItemType directory -Path $backupTargetDiff -ErrorAction Stop\r
+ $isDiff = $True\r
\r
- $success = $True\r
- }\r
- catch {\r
- Write-Host "Could not create directory $backupTargetDiff`: $_.Exception.Message"\r
- exit\r
+ if(!(Test-Path $backupTargetDiff)) {\r
+ Write-Host "Creating directory $backupTargetDiff"\r
+ \r
+ try {\r
+ New-Item -ItemType directory -Path $backupTargetDiff -ErrorAction Stop | Out-Null\r
+ }\r
+ catch {\r
+ Write-Host "Could not create directory $backupTargetDiff`: $_.Exception.Message"\r
+ $errorMessages += "Could not create directory $backupTargetDiff`: $_.Exception.Message"\r
+ }\r
+ \r
+ if($errorMessages.Count -eq 0) {\r
+ $dsLogPath = if($dsLogFileToBackup) { "$backupTargetDiff\$dsLogFile" } else { $dsLogFile }\r
+ \r
+ $dsArgs = @($disksToBackup, "--logfile:$dsLogPath", "$backupTargetDiff\`$disk.sna", "-h$backupTargetFull\`$disk.hsh") + $dsAdditionalArgs\r
+ Write-Host $dsPath ($dsArgs -join " ")\r
+ \r
+ $dsCommand = "$dsPath $dsArgs"\r
+ \r
+ & $dsPath $dsArgs\r
+ \r
+ if($LastExitCode -ne 0) {\r
+ Write-Host "Drive Snapshot failed to backup! Exit code: $LastExitCode"\r
+ $errorMessages += "Drive Snapshot failed to backup! Exit code: $LastExitCode"\r
+ }\r
+ else {\r
+ $success = $True\r
+ }\r
+ }\r
}\r
- \r
- $dsArgs = @($disksToBackup, "$backupTargetFull\`$disk.sna", "-h$backupTargetFull\`$disk.hsh") + $dsAdditionalArgs\r
- Write-Host $dsPath ($dsArgs -join " ")\r
- \r
- & $dsPath $dsArgs\r
- \r
- if($LastExitCode -ne 0) {\r
- Write-Host "Error code: $LastExitCode"\r
+ else {\r
+ Write-Host "Directory $backupTargetDiff already exists!"\r
+ $errorMessages += "Directory $backupTargetDiff already exists!"\r
}\r
}\r
else {\r
- Write-Host "Directory $backupTargetDiff already exists!"\r
- \r
- $errorMessages += "Directory $backupTargetDiff already exists!"\r
- }\r
-}\r
-else {\r
- Write-Host "Full backup"\r
- \r
- if(!(Test-Path $backupTarget)) {\r
- Write-Host "Creating directory $backupTarget"\r
- New-Item -ItemType directory -Path $backupTarget\r
- }\r
- \r
- if(!(Test-Path $backupTargetFull)) {\r
- Write-Host "Creating directory $backupTargetFull"\r
- New-Item -ItemType directory -Path $backupTargetFull\r
- }\r
+ Write-Host "Full backup"\r
\r
- $dsArgs = @($disksToBackup, "$backupTargetFull\`$disk.sna") + $dsAdditionalArgs\r
- Write-Host $dsPath ($dsArgs -join " ")\r
- \r
- & $dsPath $dsArgs\r
- \r
- if($LastExitCode -ne 0) {\r
- Write-Host "Error code: $LastExitCode"\r
- }\r
- \r
- $success = $False\r
-}\r
-\r
-if($isDiff -eq $False -and $success -eq $True -and $keepMonths -ge 0) {\r
- Write-Host "Rotating"\r
- \r
- $keepMonthsCount = $keepMonths\r
- \r
- Get-ChildItem $backupDir -Directory | Where-Object {($_.Name -ne $currMonth) -and ($_.Name -match "^\d{4,}-\d{2}$")} | Sort-Object -Descending |\r
- Foreach-Object {\r
- Write-Host $_ "=>" $_.FullName\r
- \r
- if($keepMonthsCount -ge 0) {\r
- $keepMonthsCount--\r
+ if(!(Test-Path $backupTarget)) {\r
+ Write-Host "Creating directory $backupTarget"\r
+ \r
+ try {\r
+ New-Item -ItemType directory -Path $backupTarget -ErrorAction Stop | Out-Null\r
+ }\r
+ catch {\r
+ Write-Host "Could not create directory $backupTarget`: $_.Exception.Message"\r
+ $errorMessages += "Could not create directory $backupTarget`: $_.Exception.Message"\r
+ }\r
}\r
\r
- Write-Host $keepMonthsCount\r
- \r
- if($keepMonthsCount -eq -1) {\r
- Write-Host "Deleting $_"\r
- Remove-Item -Recurse -Force $_.FullName\r
+ if($errorMessages.Count -eq 0) {\r
+ if(!(Test-Path $backupTargetFull)) {\r
+ Write-Host "Creating directory $backupTargetFull"\r
+ \r
+ try {\r
+ New-Item -ItemType directory -Path $backupTargetFull -ErrorAction Stop | Out-Null\r
+ }\r
+ catch {\r
+ Write-Host "Could not create directory $backupTargetFull`: $_.Exception.Message"\r
+ $errorMessages += "Could not create directory $backupTargetFull`: $_.Exception.Message"\r
+ }\r
+ }\r
+ \r
+ if($errorMessages.Count -eq 0) {\r
+ if($rotateBeforeBackup) {\r
+ Rotate-Backup\r
+ }\r
+ \r
+ $dsLogPath = if($dsLogFileToBackup) { "$backupTargetFull\$dsLogFile" } else { $dsLogFile }\r
+\r
+ $dsArgs = @($disksToBackup, "--logfile:$dsLogPath", "$backupTargetFull\`$disk.sna") + $dsAdditionalArgs\r
+ Write-Host $dsPath ($dsArgs -join " ")\r
+ \r
+ $dsCommand = "$dsPath $dsArgs"\r
+ \r
+ & $dsPath $dsArgs\r
+ \r
+ if($LastExitCode -ne 0) {\r
+ Write-Host "Drive Snapshot failed to backup! Exit code: $LastExitCode"\r
+ $errorMessages += "Drive Snapshot failed to backup! Exit code: $LastExitCode"\r
+ }\r
+ else {\r
+ $success = $True\r
+ }\r
+ \r
+ if($rotateBeforeBackup -eq $False -and $success -eq $True) {\r
+ Rotate-Backup\r
+ }\r
+ }\r
}\r
}\r
}\r
\r
if($smbConnected) {\r
Write-Host "Disconnecting network drive"\r
- Remove-PSDrive $smbDrive\r
- #net use "$smbDrive`:" /delete\r
+ \r
+ try {\r
+ Remove-PSDrive $smbDrive -ErrorAction Stop\r
+ }\r
+ catch {\r
+ Write-Host "Could not disconnect network drive $smbDrive`: $_.Exception.Message"\r
+ $errorMessages += "Could not disconnect network drive $smbDrive`: $_.Exception.Message"\r
+ }\r
}\r
\r
if($emailOnError -and $errorMessages.Count -gt 0) {\r
- Send-Email ("Error:`n"+($errorMessages -join "`n"))\r
-}
\ No newline at end of file
+ $emailBody = "This is DSMonRot on $env:computername, started at $startTime.`n"\r
+ $emailBody += "An error occured while performing a backup. Below are the error messages and some status information.`n`n"\r
+ $emailBody += "Backup directory: $backupDir`n"\r
+ $emailBody += "Differential backup: $isDiff`n"\r
+ $emailBody += "Backup successful: $success`n"\r
+ $emailBody += "Drive Snapshot command: $dsCommand`n`n"\r
+ $emailBody += ($errorMessages -join "`n")\r
+\r
+ Send-Email ($emailBody)\r
+}\r
+\r
+$endTime = Get-Date -format "yyyy-MM-dd HH:mm:ss"\r
+Write-Host "Ended at $endTime"
\ No newline at end of file