Wednesday, September 11, 2013

Desktop Backup (PowerShell plus Scheduled Task)

So, I test A LOT of stuff daily on my own workstation.  I suspect that most SCCM folks do.  I also have A LOT of data in my profile that it would take YEARS to rebuild.  Not something I want to accidentally blow up.  We do have pretty copious SAN storage, so I figured I'd continue with my learning PowerShell program and do a quick backup script.  Well, OK I copied most of it from another backup script we had but I still learned something.  The requirements were that it had to run fully with user rights only, and I don't want to copy 12GB or so daily over the network so it has to only copy new files.  And it has to be fast.  So here we go (beware the word wrap):

# Script to back up my stuff
# THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
# KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
# PURPOSE.   
 
# Define starting variables
$StartingDir = "C:\Users\<MyUserName>"
$DestDir = "\\Path\To\Our\Users\Storage\Space\<MyUserName"
$maxprocess = 7
 
# Create the Collection Queue
$queue = [System.Collections.Queue]::Synchronized((New-Object System.Collections.Queue))
 
# Define the Directory List or Range
$DirList = (Get-ChildItem $StartingDir | ? {$_.PSIsContainer -eq $True})
 
# Queue the Directory List or Range
foreach ($Dir in $DirList){
    $Name = $Dir.name
    Switch ($Name) {
        "Applications" {$queue.Enqueue($Dir)}
        "Desktop"      {$queue.Enqueue($Dir)}  
        "Downloads"    {$queue.Enqueue($Dir)}
        "Favorites"    {$queue.Enqueue($Dir)}
        "Documents"    {$queue.Enqueue($Dir)}
        "Pictures"     {$queue.Enqueue($Dir)}
    }
}
 
# Function that pulls next object from the queue and starts a process with it
function CreateProcessFromQueue
{
    if ($queue.count -gt 0) {
   
        #write $queue.count
        $Dir = $queue.Dequeue()
        $SourceDir = $Dir.fullname
        $DirName = $Dir.BaseName
        $DestinationDir = $DestDir + "\" + $DirName
        $LogDir = """C:\Temp\"
        $RoboCopyArgs = "/E /PURGE /COPY:DATSO /XO /R:1 /W:1 /NP /FFT /LOG:" + $LogDir + "BAK" + $DirName + ".log"""
        #write $DirName       
       
        # Define process starting information       
        $psi = New-Object System.Diagnostics.ProcessStartInfo
        $psi.FileName = "robocopy.exe"
        $psi.Arguments = """$SourceDir""" + " " + """$DestinationDir""" + " $RoboCopyArgs" 
        $psi.CreateNoWindow = $true
        $psi.UseShellExecute = $false
        #write $psi.Arguments
       
        # Start new process
        $Robo = [System.Diagnostics.Process]::Start($psi)
    }
}
 
# Start max number of processes
for ($i = 0; $i -lt $maxprocess; $i++) {
    CreateProcessFromQueue
}
 
# Ensure max number of processes continue to run until queue is empty
while ($queue.count -gt 0) {
     start-sleep -s 5
    $robocount = get-process robocopy
         if ($robocount.count -lt $maxprocess) {
             CreateProcessFromQueue
         }
  }
 
Yeay!  It works, I'm a happy geek!  So after that I created a quick scheduled task.  Ran it as my user, only when I'm logged on, scheduled daily (when I'm at lunch since I have to be logged on).  The Actions tab has a gotcha.  Set it to 'Start a Program'.  The program name is PowerShell.exe, but the arguments are "-command c:\<path>\BackMeUp.ps1" (without quotes).  Conditions and settings are pretty much whatever you want.

No comments:

Post a Comment