{"id":6910,"date":"2019-11-08T10:40:12","date_gmt":"2019-11-08T15:40:12","guid":{"rendered":"https:\/\/jdhitsolutions.com\/blog\/?p=6910"},"modified":"2019-11-08T10:40:19","modified_gmt":"2019-11-08T15:40:19","slug":"creating-a-powershell-backup-system-part-2","status":"publish","type":"post","link":"https:\/\/jdhitsolutions.com\/blog\/powershell\/6910\/creating-a-powershell-backup-system-part-2\/","title":{"rendered":"Creating a PowerShell Backup System Part 2"},"content":{"rendered":"<p><a title=\"read the previous article if you missed it\" href=\"https:\/\/jdhitsolutions.com\/blog\/?p=6905\" target=\"_blank\" rel=\"noopener noreferrer\">Yesterday I began a series<\/a> of articles documenting my PowerShell based backup system. The core of my system is using the System.IO.FileSystemWatcher as a means to track daily file changes so I know what to backup. However there are some challenges. I need to watch several folders, I need to have an easy way to know what to back up, and it needs to happen automatically without any effort on my part such as starting PowerShell and kicking off a process. My solution is to leverage a PowerShell scheduled job.<\/p>\n<h2>Creating the PowerShell Scheduled Job<\/h2>\n<p>A PowerShell Scheduled Job takes advantage of the Windows Task Scheduler to run a PowerShell scriptblock or script. You get the ease of using the task scheduler with the benefit or running PowerShell code. While it is simple enough to create a scheduled job from the console, I tend to save the command in a script file. Doing so provides me a documentation trail and makes it easier to recreate the job. While it is possible to edit an existing job, I find it easier to simply remove it and recreate it. Using a script file makes this an easy process.<\/p>\n<p>My scheduled job needs an action to perform. For backup purposes this means creating a FileSystemWatcher to monitor each directory and a corresponding event subscription. Each event needs to be able to log the file changes so that I know what needs to be backed up incrementally. To begin, I created a text file with the paths to monitor.<\/p>\n<pre class=\"lang:text mark:0 decode:true\">#comment out paths with a # symbol at the beginning of the line\n\nC:\\Scripts\nC:\\users\\jeff\\documents\nD:\\jdhit\nC:\\users\\jeff\\dropbox\nC:\\Users\\Jeff\\Google Drive\n<\/pre>\n<p>This is C:\\Scripts\\myBackupPaths.txt. In my scheduled job action I parse this file to get a list of paths.<\/p>\n<pre class=\"lang:ps mark:0 decode:true\">if (Test-Path c:\\scripts\\myBackupPaths.txt) {\n    #filter out commented lines and lines with just white space\n    $paths = Get-Content c:\\scripts\\myBackupPaths.txt | Where-Object {$_ -match \"(^[^#]\\S*)\" -and $_ -notmatch \"^\\s+$\"}\n  }\n  else {\n    Throw \"Failed to find c:\\scripts\\myBackupPaths.txt\"\n    #bail out\n    Return\n  }\n<\/pre>\n<p>I added some filtering to strip out empty and commented lines. For each path, I'm going to create a watcher and event subscription. As I'll show you in a bit, when an event fires, meaning a file was changed,\u00a0 I intend to log it to a CSV file. The action for each event subscription will be to run a PowerShell script file.<\/p>\n<pre class=\"lang:ps mark:0 decode:true\">Foreach ($Path in $Paths.Trim()) {\n\n    #get the directory name from the list of paths\n    $name = ((Split-Path $path -Leaf).replace(' ', ''))\n\n    #specify the directory for the CSV log files\n    $log = \"D:\\Backup\\{0}-log.csv\" -f $name\n    \n    #define the watcher object\n    Write-Host \"Creating a FileSystemWatcher for $Path\" -ForegroundColor green\n    $watcher = [System.IO.FileSystemWatcher]($path)\n    $watcher.IncludeSubdirectories = $True\n    #enable the watcher\n    $watcher.EnableRaisingEvents = $True\n\n    #the Action scriptblock to be run when an event fires\n    $sbtext = \"c:\\scripts\\LogBackupEntry.ps1 -event `$event -CSVPath $log\"\n\n    $sb = [scriptblock]::Create($sbtext)\n<\/pre>\n<p>The log file uses the last part of each folder path. If the name has a space, like ;Google Drive', I replace the space so that the name becomes 'GoogleDrive'. Thus I'll end up with several CSV files like D:\\Backup\\Scripts-log.csv.<\/p>\n<h2>Logging Files<\/h2>\n<p>The scriptblock text uses variable expansion so that $log will be replaced with the actual log name. And I'm escaping $event so that the text will keep it with a $ symbol. When I create the scriptblock it will look like<\/p>\n<pre>C:\\scripts\\LogBackupEntry.ps1 -event $event D:\\Backup\\Scripts-log.csv<\/pre>\n<p>The $event will be the fired event object. This is the object you get from <a title=\"Read online help for this command\" href=\"http:\/\/go.microsoft.com\/fwlink\/?LinkID=113453\" target=\"_blank\" rel=\"noopener noreferrer\">Get-Event.<\/a> The event if passed to this script.<\/p>\n<pre class=\"lang:ps mark:0 decode:true\">#requires -version 5.1\n\n[cmdletbinding()]\nParam(\n  [Parameter(Mandatory)]\n  [object]$Event,\n  [Parameter(Mandatory)]\n  [string]$CSVPath\n)\n\n#uncomment for debugging and testing\n# this will create a serialized version of each fired event\n# $event | export-clixml ([System.IO.Path]::GetTempFileName()).replace(\"tmp\",\"xml\")\n\nif (Test-Path $event.SourceEventArgs.fullpath) {\n\n  $f = Get-Item -path $event.SourceEventArgs.fullpath -force\n\n  #only save files and not a temp file\n  if ((-Not $f.psiscontainer) -AND ($f.basename -notmatch \"(^(~|__rar).*)|(.*\\.tmp$)\")) {\n\n    [pscustomobject]@{\n      ID        = $event.EventIdentifier\n      Date      = $event.timeGenerated\n      Name      = $event.sourceEventArgs.Name\n      IsFolder  = $f.PSisContainer\n      Directory = $f.DirectoryName\n      Size      = $f.length\n      Path      = $event.sourceEventArgs.FullPath\n    } | Export-Csv -NoTypeInformation -Path $CSVPath -Append\n\n  } #if not a container\n\n} #if test-path\n\n#end of script\n<\/pre>\n<p>The script file eventually will export a custom object to the appropriate CSV file. However, since sometimes a file may have been deleted after it was detected, such as a temp file, I use <a title=\"Read online help for this command\" href=\"http:\/\/go.microsoft.com\/fwlink\/?LinkID=113418\" target=\"_blank\" rel=\"noopener noreferrer\">Test-Path<\/a> to verify the file still exists. If it does, I get the file and then do some additional testing and filtering to only export files and only then if they aren't temp files. For example, when you are using PowerPoint, you'll get a number of temp files that will persist until you close the application. At that point the files are removed. I don't want to log those to the CSV file.<\/p>\n<p>Interesting side note regarding PowerPoint - the actual pptx file is never detected as having changed. In other words, when I edit a PowerPoint presentation, the file never gets logged.\u00a0 But that's ok because I can always manually update the CSV file with additional files.<\/p>\n<pre class=\"lang:ps mark:0 decode:true\">Function Add-BackupEntry {\n    [cmdletbinding(SupportsShouldProcess)]\n    Param(\n        [Parameter(Position = 0, Mandatory, ValueFromPipeline)]\n        [string]$Path,\n        [Parameter(Mandatory)]\n        [ValidateScript( { Test-Path $_ })]\n        [string]$CSVFile\n    )\n\n    Begin {\n        Write-Verbose \"[BEGIN  ] Starting: $($MyInvocation.Mycommand)\"\n        $add = @()\n    } #begin\n\n    Process {\n        Write-Verbose \"[PROCESS] Adding: $Path\"\n\n        $file = Get-Item $Path\n        $add += [pscustomobject]@{\n            ID        = 99999\n            Date      = $file.LastWriteTime\n            Name      = $file.name\n            IsFolder  = \"False\"\n            Directory = $file.Directory\n            Size      = $file.length\n            Path      = $file.FullName\n        }\n        \n    } #process\n    End {\n        Write-Verbose \"[END    ] Exporting to $CSVFile\"\n        $add | Export-Csv -Path $CSVFile -Append -NoTypeInformation\n        Write-Verbose \"[END    ] Ending: $($MyInvocation.Mycommand)\"\n    } #end\n}<\/pre>\n<p>I can check the CSV file at any time to see what files are going to be backed up.<\/p>\n<p><a href=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image-5.png\"><img loading=\"lazy\" decoding=\"async\" style=\"display: inline; background-image: none;\" title=\"\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-5.png\" alt=\"Checking pending files\" width=\"1028\" height=\"169\" border=\"0\" \/><\/a><\/p>\n<p>The FileSystemWatcher often fires several times for the same file. I'll handle that later.<\/p>\n<h2>Creating the Event Subscription<\/h2>\n<p>I still need to create the event subscription for each folder and watcher.<\/p>\n<pre class=\"lang:ps mark:0 decode:true\">$params = @{\n      InputObject      = $watcher\n      Eventname        = \"changed\"\n      SourceIdentifier = \"FileChange-$Name\"\n      MessageData      = \"A file was created or changed in $Path\"\n      Action           = $sb\n    }\n\n    $params.MessageData | Out-String | Write-Host -ForegroundColor cyan\n    $params.Action | Out-String | Write-Host -ForegroundColor Cyan\n    Register-ObjectEvent @params\n<\/pre>\n<p>Remember, all of this is going to be running as part of a PowerShell scheduled job. In other words, a runspace. In order for the event subscriber to persist, the runspace has to keep running.<\/p>\n<pre class=\"lang:ps mark:0 decode:true\">Do {\n    Start-Sleep -Seconds 1\n  } while ($True)\n<\/pre>\n<p>Maybe not the most elegant approach but it works.<\/p>\n<h2>Registering the PowerShell Scheduled Job<\/h2>\n<p>The last step is to create the scheduled job. Because I want this to run automatically and constantly, I created a job trigger to run the job at startup.<\/p>\n<pre class=\"lang:ps mark:0 decode:true\">$trigger = New-JobTrigger -AtStartup\n\nRegister-ScheduledJob -Name \"DailyWatcher\" -ScriptBlock $action -Trigger $trigger\n<\/pre>\n<p>I can now manually start the task in Task Scheduler or start it from PowerShell.<\/p>\n<pre class=\"lang:ps mark:0 decode:true\">Get-ScheduledTask.ps1 DailyWatcher | Start-ScheduledTask\n<\/pre>\n<p>Here is my complete registration script.<\/p>\n<pre class=\"lang:ps mark:0 decode:true\">#requires -version 5.1\n#requires -module PSScheduledJob\n\n#create filesystemwatcher job for my incremental backups.\n\n#scheduled job scriptblock\n$action = {\n\n  if (Test-Path c:\\scripts\\myBackupPaths.txt) {\n    #filter out commented lines and lines with just white space\n    $paths = Get-Content c:\\scripts\\myBackupPaths.txt | Where-Object {$_ -match \"(^[^#]\\S*)\" -and $_ -notmatch \"^\\s+$\"}\n  }\n  else {\n    Throw \"Failed to find c:\\scripts\\myBackupPaths.txt\"\n    #bail out\n    Return\n  }\n\n  #trim leading and trailing white spaces in each path\n  Foreach ($Path in $Paths.Trim()) {\n\n    #get the directory name from the list of paths\n    $name = ((Split-Path $path -Leaf).replace(' ', ''))\n\n    #specify the directory for the CSV log files\n    $log = \"D:\\Backup\\{0}-log.csv\" -f $name\n    \n    #define the watcher object\n    Write-Host \"Creating a FileSystemWatcher for $Path\" -ForegroundColor green\n    $watcher = [System.IO.FileSystemWatcher]($path)\n    $watcher.IncludeSubdirectories = $True\n    #enable the watcher\n    $watcher.EnableRaisingEvents = $True\n\n    #the Action scriptblock to be run when an event fires\n    $sbtext = \"c:\\scripts\\LogBackupEntry.ps1 -event `$event -CSVPath $log\"\n\n    $sb = [scriptblock]::Create($sbtext)\n\n    #register the event subscriber\n    \n    #possible events are Changed,Deleted,Created\n    $params = @{\n      InputObject      = $watcher\n      Eventname        = \"changed\"\n      SourceIdentifier = \"FileChange-$Name\"\n      MessageData      = \"A file was created or changed in $Path\"\n      Action           = $sb\n    }\n\n    $params.MessageData | Out-String | Write-Host -ForegroundColor cyan\n    $params.Action | Out-String | Write-Host -ForegroundColor Cyan\n    Register-ObjectEvent @params\n\n  } #foreach path\n\n  Get-EventSubscriber | Out-String | Write-Host -ForegroundColor yellow\n\n  #keep the job alive\n  Do {\n    Start-Sleep -Seconds 1\n  } while ($True)\n\n} #close job action\n\n$trigger = New-JobTrigger -AtStartup\n\nRegister-ScheduledJob -Name \"DailyWatcher\" -ScriptBlock $action -Trigger $trigger\n<\/pre>\n<h2>Next Steps<\/h2>\n<p>At this point I have a PowerShell scheduled job running essentially in the background, monitoring folders for file changes and logging to a CSV file. Next time I'll walk you through how I use that data.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Yesterday I began a series of articles documenting my PowerShell based backup system. The core of my system is using the System.IO.FileSystemWatcher as a means to track daily file changes so I know what to backup. However there are some challenges. I need to watch several folders, I need to have an easy way to&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"Just posted: Creating a #PowerShell Backup System Part 2","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[4],"tags":[201,617,534,540],"class_list":["post-6910","post","type-post","status-publish","format-standard","hentry","category-powershell","tag-backup","tag-filesystemwatcher","tag-powershell","tag-scripting"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Creating a PowerShell Backup System Part 2 &#8226; The Lonely Administrator<\/title>\n<meta name=\"description\" content=\"I continue my tutorial on how I use PowerShell to create a backup system using PowerShell Scheduled Jobs and event subscriptions.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/jdhitsolutions.com\/blog\/powershell\/6910\/creating-a-powershell-backup-system-part-2\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Creating a PowerShell Backup System Part 2 &#8226; The Lonely Administrator\" \/>\n<meta property=\"og:description\" content=\"I continue my tutorial on how I use PowerShell to create a backup system using PowerShell Scheduled Jobs and event subscriptions.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/jdhitsolutions.com\/blog\/powershell\/6910\/creating-a-powershell-backup-system-part-2\/\" \/>\n<meta property=\"og:site_name\" content=\"The Lonely Administrator\" \/>\n<meta property=\"article:published_time\" content=\"2019-11-08T15:40:12+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-11-08T15:40:19+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-5.png\" \/>\n<meta name=\"author\" content=\"Jeffery Hicks\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@JeffHicks\" \/>\n<meta name=\"twitter:site\" content=\"@JeffHicks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jeffery Hicks\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/6910\\\/creating-a-powershell-backup-system-part-2\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/6910\\\/creating-a-powershell-backup-system-part-2\\\/\"},\"author\":{\"name\":\"Jeffery Hicks\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\"},\"headline\":\"Creating a PowerShell Backup System Part 2\",\"datePublished\":\"2019-11-08T15:40:12+00:00\",\"dateModified\":\"2019-11-08T15:40:19+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/6910\\\/creating-a-powershell-backup-system-part-2\\\/\"},\"wordCount\":803,\"commentCount\":3,\"publisher\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\"},\"image\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/6910\\\/creating-a-powershell-backup-system-part-2\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/11\\\/image_thumb-5.png\",\"keywords\":[\"Backup\",\"FileSystemWatcher\",\"PowerShell\",\"Scripting\"],\"articleSection\":[\"PowerShell\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/6910\\\/creating-a-powershell-backup-system-part-2\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/6910\\\/creating-a-powershell-backup-system-part-2\\\/\",\"url\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/6910\\\/creating-a-powershell-backup-system-part-2\\\/\",\"name\":\"Creating a PowerShell Backup System Part 2 &#8226; The Lonely Administrator\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/6910\\\/creating-a-powershell-backup-system-part-2\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/6910\\\/creating-a-powershell-backup-system-part-2\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/11\\\/image_thumb-5.png\",\"datePublished\":\"2019-11-08T15:40:12+00:00\",\"dateModified\":\"2019-11-08T15:40:19+00:00\",\"description\":\"I continue my tutorial on how I use PowerShell to create a backup system using PowerShell Scheduled Jobs and event subscriptions.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/6910\\\/creating-a-powershell-backup-system-part-2\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/6910\\\/creating-a-powershell-backup-system-part-2\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/6910\\\/creating-a-powershell-backup-system-part-2\\\/#primaryimage\",\"url\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/11\\\/image_thumb-5.png\",\"contentUrl\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/11\\\/image_thumb-5.png\",\"width\":1028,\"height\":169},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/6910\\\/creating-a-powershell-backup-system-part-2\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"PowerShell\",\"item\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/category\\\/powershell\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Creating a PowerShell Backup System Part 2\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/\",\"name\":\"The Lonely Administrator\",\"description\":\"Practical Advice for the Automating IT Pro\",\"publisher\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\",\"name\":\"Jeffery Hicks\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\",\"caption\":\"Jeffery Hicks\"},\"logo\":{\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Creating a PowerShell Backup System Part 2 &#8226; The Lonely Administrator","description":"I continue my tutorial on how I use PowerShell to create a backup system using PowerShell Scheduled Jobs and event subscriptions.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/jdhitsolutions.com\/blog\/powershell\/6910\/creating-a-powershell-backup-system-part-2\/","og_locale":"en_US","og_type":"article","og_title":"Creating a PowerShell Backup System Part 2 &#8226; The Lonely Administrator","og_description":"I continue my tutorial on how I use PowerShell to create a backup system using PowerShell Scheduled Jobs and event subscriptions.","og_url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/6910\/creating-a-powershell-backup-system-part-2\/","og_site_name":"The Lonely Administrator","article_published_time":"2019-11-08T15:40:12+00:00","article_modified_time":"2019-11-08T15:40:19+00:00","og_image":[{"url":"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-5.png","type":"","width":"","height":""}],"author":"Jeffery Hicks","twitter_card":"summary_large_image","twitter_creator":"@JeffHicks","twitter_site":"@JeffHicks","twitter_misc":{"Written by":"Jeffery Hicks","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/6910\/creating-a-powershell-backup-system-part-2\/#article","isPartOf":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/6910\/creating-a-powershell-backup-system-part-2\/"},"author":{"name":"Jeffery Hicks","@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9"},"headline":"Creating a PowerShell Backup System Part 2","datePublished":"2019-11-08T15:40:12+00:00","dateModified":"2019-11-08T15:40:19+00:00","mainEntityOfPage":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/6910\/creating-a-powershell-backup-system-part-2\/"},"wordCount":803,"commentCount":3,"publisher":{"@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9"},"image":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/6910\/creating-a-powershell-backup-system-part-2\/#primaryimage"},"thumbnailUrl":"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-5.png","keywords":["Backup","FileSystemWatcher","PowerShell","Scripting"],"articleSection":["PowerShell"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/jdhitsolutions.com\/blog\/powershell\/6910\/creating-a-powershell-backup-system-part-2\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/6910\/creating-a-powershell-backup-system-part-2\/","url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/6910\/creating-a-powershell-backup-system-part-2\/","name":"Creating a PowerShell Backup System Part 2 &#8226; The Lonely Administrator","isPartOf":{"@id":"https:\/\/jdhitsolutions.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/6910\/creating-a-powershell-backup-system-part-2\/#primaryimage"},"image":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/6910\/creating-a-powershell-backup-system-part-2\/#primaryimage"},"thumbnailUrl":"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-5.png","datePublished":"2019-11-08T15:40:12+00:00","dateModified":"2019-11-08T15:40:19+00:00","description":"I continue my tutorial on how I use PowerShell to create a backup system using PowerShell Scheduled Jobs and event subscriptions.","breadcrumb":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/6910\/creating-a-powershell-backup-system-part-2\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/jdhitsolutions.com\/blog\/powershell\/6910\/creating-a-powershell-backup-system-part-2\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/6910\/creating-a-powershell-backup-system-part-2\/#primaryimage","url":"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-5.png","contentUrl":"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-5.png","width":1028,"height":169},{"@type":"BreadcrumbList","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/6910\/creating-a-powershell-backup-system-part-2\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"PowerShell","item":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},{"@type":"ListItem","position":2,"name":"Creating a PowerShell Backup System Part 2"}]},{"@type":"WebSite","@id":"https:\/\/jdhitsolutions.com\/blog\/#website","url":"https:\/\/jdhitsolutions.com\/blog\/","name":"The Lonely Administrator","description":"Practical Advice for the Automating IT Pro","publisher":{"@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/jdhitsolutions.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9","name":"Jeffery Hicks","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg","url":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg","caption":"Jeffery Hicks"},"logo":{"@id":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg"}}]}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":6974,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/6974\/watching-the-watcher-with-powershell\/","url_meta":{"origin":6910,"position":0},"title":"Watching the Watcher with PowerShell","author":"Jeffery Hicks","date":"November 14, 2019","format":false,"excerpt":"If you followed along with my recent articles about my PowerShell based backup system, you may recall that I used a PowerShell scheduled job an an event subscriber to monitor for file changes in key folders that I want to back up. I created the scheduled task to run at\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-14.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-14.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-14.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-14.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":6905,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/6905\/creating-a-powershell-backup-system\/","url_meta":{"origin":6910,"position":1},"title":"Creating a PowerShell Backup System","author":"Jeffery Hicks","date":"November 7, 2019","format":false,"excerpt":"If you follow me on Twitter, you know that I have a monthly tweet reminder about running and testing backups. I have to say that the concept of a backup is different today than it was when I started in IT. Now we have cheap disk storage and cloud services.\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-4.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-4.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-4.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-4.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":6955,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/6955\/creating-a-powershell-backup-system-part-3\/","url_meta":{"origin":6910,"position":2},"title":"Creating a PowerShell Backup System &#8211; Part 3","author":"Jeffery Hicks","date":"November 11, 2019","format":false,"excerpt":"Let's continue exploring my PowerShell based backup system. If you are just jumping in, be sure to read part 1 and part 2 first. At the end of the previous article I have set up a scheduled job that is logging changed files in key folders to CSV files. The\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-9.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-9.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-9.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-9.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":6962,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/6962\/creating-a-powershell-backup-system-part-4\/","url_meta":{"origin":6910,"position":3},"title":"Creating a PowerShell Backup System &#8211; Part 4","author":"Jeffery Hicks","date":"November 12, 2019","format":false,"excerpt":"We're almost to the end of my PowerShell backup system. Last time I showed you how I handle my daily incremental backups. Today I figured I should circle back and go over how I handle weekly full backups. Remember, I am only concerned about backing up a handful of critical\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-11.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-11.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-11.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-11.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":2833,"url":"https:\/\/jdhitsolutions.com\/blog\/scripting\/2833\/get-scheduled-job-results\/","url_meta":{"origin":6910,"position":4},"title":"Get Scheduled Job Results","author":"Jeffery Hicks","date":"March 5, 2013","format":false,"excerpt":"One of my favorite features in PowerShell 3.0 is the ability to run a PowerShell job as a scheduled task. I can easily setup a PowerShell background job to run a script but have it registered as a scheduled task. All you need is PowerShell 3.0. The job results are\u2026","rel":"","context":"In &quot;Powershell 3.0&quot;","block_context":{"text":"Powershell 3.0","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell-3-0\/"},"img":{"alt_text":"talkbubble-v3","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2012\/05\/talkbubble-v3-150x150.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":6996,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/6996\/powershell-controller-scripts\/","url_meta":{"origin":6910,"position":5},"title":"PowerShell Controller Scripts","author":"Jeffery Hicks","date":"November 26, 2019","format":false,"excerpt":"When it comes to PowerShell scripting we tend to focus a lot on functions and modules. We place an emphasis on building re-usable tools. The idea is that we can then use these tools at a PowerShell prompt to achieve a given task. More than likely, these tasks are repetitive.\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-21.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-21.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-21.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/11\/image_thumb-21.png?resize=700%2C400&ssl=1 2x"},"classes":[]}],"_links":{"self":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/6910","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/comments?post=6910"}],"version-history":[{"count":0,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/6910\/revisions"}],"wp:attachment":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/media?parent=6910"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/categories?post=6910"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/tags?post=6910"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}