-
Notifications
You must be signed in to change notification settings - Fork 59
PowerShellPlusRobocopy
candera edited this page Jan 21, 2012
·
1 revision
###########################################################################################
# Backup PST files using ShadowSpawn/Robocopy
# Created 2011-05-09 - Benjamin Meis
# Updated 2011-11-03 - Benjamin Meis
# This script requires the following directory structure on where the script is hosted:
# \
# --PST_Backup_Script.ps1
# --Tools\
# --robocopy.exe (xp version)
# --vcredist-2010_x64.exe
# --vcredist-2010_x64.exe
# --ShadowSpawn_winxp\
# --ShadowSpawn.exe
# --ShadowSpawn.pdb
# --ShadowSpawn_win7\
# --64-bit\
# --ShadowSpawn.exe
# --ShadowSpawn.pdb
# --32-bit\
# --ShadowSpawn.exe
# --ShadowSpawn.pdb
# Note: Execution policy on your machine must be set to allow the running of Powershell Scripts
# e.g. Set-ExecutionPolicy Unrestricted -Force (your own security policies may not allow for unrestricted, please be sure to check with your sysadmin)
###########################################################################################
# Initiate variables
$curDate = $(Get-Date -UFormat "%Y%m%d")
$companyDir = "some_local_directory"
$logDir = "$companyDir\Logs\PST_Backups"
if (!(Test-Path -PathType Container -Path $logDir)) {New-Item -Path $logDir -ItemType Container}
Start-Transcript -Path "$logDir\PST_Backup_Log_$curDate.txt"
Write-Host "$(Get-Date -format g) Beginning PST Backup `r"
Write-Host "$(Get-Date -format g) Setting Variables `r"
$wmiWinVer = (Get-WmiObject Win32_OperatingSystem).Caption
$wmiWinArch = (Get-WmiObject Win32_OperatingSystem).OSArchitecture
$backupServer = "server_for_pst_backups"
$backupShare = "share_for_pst_backups"
$scrSvr = "server_for_script"
$scrShare = "share_for_script"
$scrFolder = "script_folder_on_share"
$scriptDir="\\$scrSvr\$scrShare\$scrFolder"
$compName = $env:computername
$winVer = "" #Left blank intentionally
$userDirs = "" #Left blank intentionally
$appDataDir = "" #Left blank intentionally
$shadowDir = "" #Left blank intentionally
$toolsDir = "$scriptDir\Tools"
$errCode = 0
$errServer = "server_for_error_logs"
$errShare = "share_for_error_logs"
$sucServer = "server_for_success_logs"
$sucShare = "share_for_success_logs"
$copyStatus = "" #Left blank intentionally
switch -regex ($wmiWinVer)
{
"Microsoft Windows 7*" {$winVer = "win7"; $userDirs = "C:\Users"; $appDataDir = "AppData\Local"; $shadowDir = "\\$scrSvr\$scrShare\$scrFolder\ShadowSpawn_win7\$wmiWinArch"}
"Microsoft Windows XP*" {$winVer = "winxp"; $userDirs = "C:\Documents And Settings"; $appDataDir = "Local Settings\Application Data"; $shadowDir = "\\$scrSvr\$scrShare\$scrFolder\ShadowSpawn_winxp"}
default {$winVer = "Unknown"}
}
#Checking for VS 2010 C++ Redistributable (and installing if necessary)
function Get-RegInstalledPrograms($computer = '.') {
$programs_installed = @{};
$error_action = 'Stop';
$reg_uninstall_paths = @('Software\Microsoft\Windows'`
+ '\CurrentVersion\Uninstall');
$reg_uninstall_paths += @('Software\Wow6432Node\Microsoft'`
+ '\Windows\CurrentVersion\Uninstall');
$pattern_valid_name = '^{[\w\W}]+\Z';
$hkey = 'LocalMachine';
$registry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($hkey, $computer);
foreach ($reg_uninstall_path in $reg_uninstall_paths) {
$reg_uninstall_key = $registry.OpenSubKey($reg_uninstall_path);
if ($reg_uninstall_key -eq $null) {
continue;
}
$key_names = $reg_uninstall_key.GetSubKeyNames();
foreach ($key_name in $key_names) {
$key_properties = $reg_uninstall_key.OpenSubKey($key_name);
$name = $key_properties.GetValue('DisplayName');
$version = $key_properties.GetValue('DisplayVersion');
if (($key_name -imatch $pattern_valid_name) `
-and ($name -ne $null)) {
$programs_installed.$name = $version;
}
$key_properties.close();
}
$reg_uninstall_key.close();
}
$registry.close();
return $programs_installed;
}
if ($(Get-Service -Name RemoteRegistry).Status -eq "Stopped") {Set-Service -Name RemoteRegistry -Status Running -StartupType Automatic; Start-Sleep -Seconds 5}
$instPrograms = Get-RegInstalledPrograms
$x64InstFlag = "No"
$x86InstFlag = "No"
$instPrograms | foreach {$_.GetEnumerator()} | foreach {if ($_.Key -like "Microsoft Visual C++ 2010 x64 Redistributable*") {$x64InstFlag = "Yes"; Write-Host "$(Get-Date -format g) x64 VS Redistributable Found."}}
$instPrograms | foreach {$_.GetEnumerator()} | foreach {if ($_.Key -like "Microsoft Visual C++ 2010 x86 Redistributable*") {$x86InstFlag = "Yes"; Write-Host "$(Get-Date -format g) x86 VS Redistributable Found."}}
if ($wmiWinArch -eq "64-bit")
{
if ($x86InstFlag -eq "No")
{
Write-Host "$(Get-Date -format g) VS C++ x86 Redistributable not detected, installing..."
Start-Process -Wait -FilePath "$toolsDir\vcredist-2010_x86.exe" -ArgumentList "/q /noreboot"
}
if ($x64InstFlag -eq "No")
{
Write-Host "$(Get-Date -format g) VS C++ x64 Redistributable not detected, installing..."
Start-Process -Wait -FilePath "$toolsDir\vcredist-2010_x64.exe" -ArgumentList "/q /noreboot"
}
}
else
{
if ($x86InstFlag -eq "No")
{
Write-Host "$(Get-Date -format g) VS C++ x86 Redistributable not detected, installing..."
Start-Process -Wait -FilePath "$toolsDir\vcredist-2010_x86.exe" -ArgumentList "/q /noreboot"
}
}
Write-Host "$(Get-Date -format g) This computer is a $wmiWinVer computer and its user directories are located in $userDirs `r"
$userList = (Get-ChildItem $userDirs -Name)
Write-Host "$(Get-Date -format g) These users have profiles on this computer: `r"
Write-Host "$userList `r"
# Looping through users directories
foreach ($user in $userList)
{
Write-Host "$(Get-Date -format g) Testing for $userDirs\$user\$appDataDir\Microsoft\Outlook `r"
# If Outlook directory found, back it up
if (Test-Path -PathType Container -Path $userDirs\$user\$appDataDir\Microsoft\Outlook)
{
Write-Host "$(Get-Date -format g) $user has an Outlook folder. `r"
$sourceDir = "$userDirs\$user\$appDataDir\Microsoft\Outlook"
$destDir = "\\$backupServer\$backupShare\$user\$compName"
if (!(Test-Path -PathType Container -Path $destDir)) {New-Item -Path $destDir -ItemType Container}
Write-Host "$(Get-Date -format g) Copying Outlook folder to backup location at $destDir `r"
switch ($winVer)
{
"win7" {
. $shadowDir\ShadowSpawn.exe /verbosity=4 $sourceDir Q: robocopy /E /Z /NP /COPYALL /PURGE Q:\ $destDir | Out-Host
$copyStatus = $LastExitCode }
"winxp" {
. $shadowDir\ShadowSpawn.exe /verbosity=4 $sourceDir Q: $toolsDir\robocopy /E /Z /NP /COPYALL /PURGE Q:\ $destDir | Out-Host
$copyStatus = $LastExitCode }
default {
Write-Host "Unable to determine Windows version, copy cannot procede"
$copyStatus = 1 }
}
If ($copyStatus -eq 0)
{
Write-Host "$(Get-Date -format g) Copy complete. `r"
}
Else
{
# Determine exit code for log flagging
switch ($copyStatus)
{
1 { Write-Host "$(Get-Date -format g) ShadowSpawn failed with error code $copyStatus. Will copy log of this to \\$errServer\$errShare\$curDate\PST_Backup_Log_$compName.txt `r"
$errCode = $copyStatus }
2 { Write-Host "$(Get-Date -format g) ShadowSpawn failed with error code $copyStatus. Will copy log of this to \\$errServer\$errShare\$curDate\PST_Backup_Log_$compName.txt `r"
$errCode = $copyStatus }
32769 { Write-Host "$(Get-Date -format g) Copy complete. `r" }
32770 { Write-Host "$(Get-Date -format g) Copy complete, but extra files/directories detected. May need to double-check log `r" }
32771 { Write-Host "$(Get-Date -format g) Copy complete, but extra files/directories detected. May need to double-check log `r" }
32772 { Write-Host "$(Get-Date -format g) Copy complete, but mismatched files/directories detected. May need to double-check log `r" }
32773 { Write-Host "$(Get-Date -format g) Copy complete, but mismatched files/directories detected. May need to double-check log `r" }
32774 { Write-Host "$(Get-Date -format g) Copy complete, but mismatched files/directories detected. May need to double-check log `r" }
32775 { Write-Host "$(Get-Date -format g) Copy complete, but mismatched files/directories detected. May need to double-check log `r" }
default { Write-Host "$(Get-Date -format g) Copy failed with error code $($copyStatus - 32768). Will copy log of this to \\$errServer\$errShare\$curDate\PST_Backup_Log_$compName.txt `r"
$errCode = $($copyStatus - 32768) }
}
}
}
else
{
Write-Host "$(Get-Date -format g) $user does not have an Outlook folder. `r"
}
}
Write-Host "$(Get-Date -format g) PST Backup complete. `r"
# Delete old log files to save space
Write-Host "$(Get-Date -format g) Beginning log rotation `r"
$fileList = Get-ChildItem $logDir
foreach ($file in $fileList) {
Set-Variable -Name fileCreated -Scope Local -Value $(Get-ChildItem $logDir\$file)
Set-Variable -Name fileAge -Scope Local -Value $(New-TimeSpan $fileCreated.CreationTime $(Get-Date))
if ($fileAge.Days -gt 14)
{
Write-Host "$(Get-Date -format g) $file is old, deleting `r"
Remove-Item $logDir\$file
}
}
Write-Host "$(Get-Date -format g) Log rotation complete `r"
Stop-Transcript
# Copy log files to appropriate location based on success or error and exit appropriately
If ($errCode -eq 0)
{
if (!(Test-Path -PathType Container -Path "\\$sucServer\$sucShare\$curDate\")) {New-Item -Path "\\$sucServer\$sucShare\$curDate\" -ItemType Container}
Copy-Item "$logDir\PST_Backup_Log_$curDate.txt" "\\$sucServer\$sucShare\$curDate\PST_Backup_Log_$compName.txt"
exit 0
}
Else
{
if (!(Test-Path -PathType Container -Path "\\$errServer\$errShare\$curDate\")) {New-Item -Path "\\$errServer\$errShare\$curDate\" -ItemType Container}
Copy-Item "$logDir\PST_Backup_Log_$curDate.txt" "\\$errServer\$errShare\$curDate\PST_Backup_Log_$compName.txt"
exit $errCode
}