PowerShell: Backup documents on Dropbox securely with encryption

PowerShell: Backup documents on Dropbox securely with encryption

Like many other people out there, you’re probably looking for a way to backup your documents regularly, reliably, and securely on some sort of central storage service. Dropbox is a great option for this, since they provide a fair amount of storage for free, and their annual cost for additional storage is pretty fair. Unfortunately, there have been wide reports of privacy concerns around Dropbox’s ability to release information to the government, which are concerns that I also share. That’s alright though, because as we’ll see, we can still use the service to securely backup our files.

Advertisement: Please take a moment to check out Arvixe PersonalClassASP web hosting!

Since we cannot confidently store our files on Dropbox in plain sight, we should ensure that they are encrypted before they’re transferred to the backup service. There are built-in capabilities to encrypt files in Windows, but I prefer the security and performance of the popular, open-source 7-Zip application. 7-Zip is an ideal tool for compressing and encrypting documents, because it is fast, uses secure AES-256 encryption, and offers the option to encrypt the compressed file headers. The last option I mentioned is important to  prevent people from reading the file names inside the archive; by default, 7-Zip only encrypts the document data, and not the document metadata.

7-Zip is only part of the equation, however. We need to schedule these backup jobs to run on a regular schedule so that we are constantly getting up-to-date backups. Additionally, we may desire to add multiple folder paths to add to a single zip file, which isn’t easily done using 7-Zip by itself. This is where Microsoft Windows PowerShell comes into play. We can use PowerShell to make multiple calls to the 7-Zip executable, which is otherwise very command line friendly, and add files from multiple folders to the same aggregate (eg. daily) archive file.

I recently wrote a PowerShell script that will assist with creating automated backups of my information, and wanted to share it with the community. This script not only performs a daily backup of the specified folders (using the -Path parameter), but it also downloads and installs 7-Zip if the system it’s being executed on doesn’t have it installed already.

[cc height = “1000” lang=”powershell”]function Backup-FolderToDropbox {
[CmdletBinding()]
param (
[string] $Password
, [string[]] $Path
, [string] $BackupFolder
, [switch] $Force
)

Set-PSDebug -Strict;
# REQUIRES PowerShell version 3.0 CTP2 or later

# Define source and backup folder
$BackupName = ‘{0}Documents.7z’ -f (Get-Date -Format ‘yyyy-MM-dd’);
Remove-Item -Path “$env:TEMP\$BackupName” -Force:$Force -ErrorAction SilentlyContinue;

# Create a new System.Net.WebClient object
$WebClient = New-Object -TypeName System.Net.WebClient;
# Define URL to download 7-Zip if it’s unavailable
$7ZipUrl = ‘http://downloads.sourceforge.net/sevenzip/7z920-x64.msi’;
$7ZipDownloadPath = “$env:TEMP\7z920-x64.msi”;
$7ZipInstalled = $true;

try {
# Get path to 7-Zip executable
$7ZipPath = Resolve-Path `
-Path ((Get-Item -Path HKLM:\SOFTWARE\7-Zip -ErrorAction SilentlyContinue).GetValue(“Path”) + ‘\7z.exe’);
if (!$7ZipPath) {
$7ZipInstalled = $false;
}
}
catch {
$7ZipInstalled = $false;
}

# Download and install 7-Zip if it’s not installed
if (!$7ZipInstalled) {
# Download the 7-Zip installer
$WebClient.DownloadFile($7ZipUrl, $7ZipDownloadPath);

# Install 7-Zip package
Start-Process -Wait `
-FilePath msiexec.exe `
-ArgumentList (‘/package “{0}” /quiet /l*v “{1}”‘ -f $7ZipDownloadPath, “$env:TEMP\7-Zip Install.log”);

# Remove the downloaded installer file
Remove-Item -Path $7ZipDownloadPath -Force -ErrorAction SilentlyContinue;
}

foreach ($FolderPath in $Path) {
# Define command line arguments for 7-Zip
$Arguments = ‘a -y -p{0} -t7z -mhe=on -mtc=on “{1}” “{2}”‘ -f $Password, $BackupName, $FolderPath;
# For debugging: Write-Host -Object $Arguments;
Start-Process `
-RedirectStandardOutput “$env:TEMP\7-Zip Output.log” `
-WorkingDirectory $env:TEMP `
-NoNewWindow `
-Wait `
-FilePath $7ZipPath.Path `
-ArgumentList $Arguments;
};

# Copy backup file to Dropbox folder
Copy-Item -Path (‘{0}\{1}’ -f $env:TEMP, $BackupName) -Destination $BackupFolder -Force:$Force;
}

Clear-Host;
Backup-FolderToDropbox -Password foobar -Path c:\MyDocs -BackupFolder c:\Dropbox\Backups -Force;[/cc]