[{"data":1,"prerenderedAt":2635},["ShallowReactive",2],{"post:\u002F2025\u002F10\u002F15\u002Fpowershell-hyper-v-automate-vm-checkpoints-before-patch-tuesday\u002F":3},{"post":4,"newer":2587,"older":2596,"related":2607,"series":2633},{"id":5,"title":6,"body":7,"canonical":2568,"categories":2569,"date":2572,"description":2573,"extension":2574,"featured":2575,"hero":2576,"image":2576,"meta":2577,"navigation":638,"path":2578,"readingTime":365,"seo":2579,"series":2576,"seriesOrder":2576,"sites":2580,"source":2576,"stem":2581,"tags":2582,"updated":2576,"url":2585,"__hash__":2586},"blog\u002Fblog\u002F2025\u002F10\u002F15\u002Fpowershell-hyper-v-automate-vm-checkpoints-before-patch-tuesday.md","PowerShell: Hyper-V – Automate VM Checkpoints Before Patch Tuesday",{"type":8,"value":9,"toc":2560},"minimark",[10,19,24,56,60,185,195,199,202,229,232,279,282,290,293,315,322,432,436,2403,2407,2490,2494,2556],[11,12,13,14,18],"p",{},"Patch Tuesday should be boring. The way I make it boring on Hyper-V is to checkpoint every running VM right before the update window opens, so a bad driver or a broken service after reboot is a two-minute ",[15,16,17],"code",{},"Restore-VMSnapshot"," instead of a restore-from-backup ticket. This script takes the checkpoint, names it with a prefix and the date so it is easy to find, prunes the checkpoints its own earlier runs left behind, and works against a single host, a list of hosts or every node of a failover cluster. Microsoft publishes the monthly security release on the second Tuesday of each month (10:00 AM Pacific), so the script can also refuse to run outside that week.",[20,21,23],"h2",{"id":22},"requirements","Requirements",[25,26,27,43,46,49],"ul",{},[28,29,30,31,34,35,38,39,42],"li",{},"Windows PowerShell 5.1 on a host or management machine with the Hyper-V PowerShell module (",[15,32,33],{},"Hyper-V-PowerShell"," feature). Add ",[15,36,37],{},"RSAT-Clustering-PowerShell"," if you use ",[15,40,41],{},"-ClusterName",".",[28,44,45],{},"Hyper-V Administrators (or local Administrators) on every target host.",[28,47,48],{},"VMs at configuration version 6.2 or later for production checkpoints, and a guest whose Volume Shadow Copy Service (Windows) or file system freeze (Linux) works, since that is what makes the checkpoint data consistent.",[28,50,51,52,55],{},"Free space on each VM's volume or CSV for the differencing disk (",[15,53,54],{},".avhdx",") to grow during the patch window, and again for the merge when the checkpoint is deleted.",[20,57,59],{"id":58},"parameters","Parameters",[61,62,63,82],"table",{},[64,65,66],"thead",{},[67,68,69,73,76,79],"tr",{},[70,71,72],"th",{},"Name",[70,74,75],{},"Type",[70,77,78],{},"Required",[70,80,81],{},"Description",[83,84,85,105,125,138,153,170],"tbody",{},[67,86,87,93,99,102],{},[88,89,90],"td",{},[15,91,92],{},"VMName",[88,94,95,96],{},"string",[97,98],"span",{},[88,100,101],{},"No",[88,103,104],{},"Names of VMs to checkpoint. Defaults to every running VM on the target hosts.",[67,106,107,112,116,118],{},[88,108,109],{},[15,110,111],{},"ComputerName",[88,113,95,114],{},[97,115],{},[88,117,101],{},[88,119,120,121,124],{},"Hyper-V hosts to target. Defaults to the local computer. Ignored when ",[15,122,123],{},"ClusterName"," is set.",[67,126,127,131,133,135],{},[88,128,129],{},[15,130,123],{},[88,132,95],{},[88,134,101],{},[88,136,137],{},"Failover cluster whose nodes (those that are Up) are all targeted.",[67,139,140,145,148,150],{},[88,141,142],{},[15,143,144],{},"RetentionDays",[88,146,147],{},"int",[88,149,101],{},[88,151,152],{},"Checkpoints created by this script and older than this many days are removed before new ones are taken. Defaults to 7.",[67,154,155,160,162,164],{},[88,156,157],{},[15,158,159],{},"CheckpointPrefix",[88,161,95],{},[88,163,101],{},[88,165,166,167,42],{},"Prefix used to name and identify this script's checkpoints, so cleanup only ever touches its own. Defaults to ",[15,168,169],{},"PatchTuesday",[67,171,172,177,180,182],{},[88,173,174],{},[15,175,176],{},"RequirePatchWeek",[88,178,179],{},"switch",[88,181,101],{},[88,183,184],{},"Exit without doing anything unless today falls in the seven days starting on this month's second Tuesday.",[11,186,187,188,191,192,42],{},"The script also honours ",[15,189,190],{},"-WhatIf"," and ",[15,193,194],{},"-Verbose",[20,196,198],{"id":197},"usage","Usage",[11,200,201],{},"Checkpoint every running VM on the local host with the default seven-day retention, showing what it does.",[203,204,209],"pre",{"className":205,"code":206,"language":207,"meta":208,"style":208},"language-powershell shiki shiki-themes github-dark",".\\New-PrePatchCheckpoint.ps1 -Verbose\n","powershell","",[15,210,211],{"__ignoreMap":208},[97,212,215,218,222,226],{"class":213,"line":214},"line",1,[97,216,42],{"class":217},"s95oV",[97,219,221],{"class":220},"sDLfK","\\New-PrePatchCheckpoint.ps1",[97,223,225],{"class":224},"snl16"," -",[97,227,228],{"class":217},"Verbose\n",[11,230,231],{},"Checkpoint three VMs on a cluster and keep the checkpoints for only two days.",[203,233,235],{"className":205,"code":234,"language":207,"meta":208,"style":208},".\\New-PrePatchCheckpoint.ps1 -ClusterName 'hv-clu01' -VMName 'app-svr01', 'app-svr02', 'sql-svr01' -RetentionDays 2\n",[15,236,237],{"__ignoreMap":208},[97,238,239,241,243,245,248,252,254,257,260,263,266,268,271,273,276],{"class":213,"line":214},[97,240,42],{"class":217},[97,242,221],{"class":220},[97,244,225],{"class":224},[97,246,247],{"class":217},"ClusterName ",[97,249,251],{"class":250},"sU2Wk","'hv-clu01'",[97,253,225],{"class":224},[97,255,256],{"class":217},"VMName ",[97,258,259],{"class":250},"'app-svr01'",[97,261,262],{"class":224},",",[97,264,265],{"class":250}," 'app-svr02'",[97,267,262],{"class":224},[97,269,270],{"class":250}," 'sql-svr01'",[97,272,225],{"class":224},[97,274,275],{"class":217},"RetentionDays ",[97,277,278],{"class":220},"2\n",[11,280,281],{},"The script returns one object per action, so the output doubles as a change record.",[203,283,288],{"className":284,"code":286,"language":287,"meta":208},[285],"language-text","VM         Host       Action   Checkpoint              CheckpointType\n--         ----       ------   ----------              --------------\napp-svr01  HV-NODE01  Removed  PatchTuesday-2025-09-09 Production\napp-svr01  HV-NODE01  Created  PatchTuesday-2025-10-15 Production\napp-svr02  HV-NODE02  Created  PatchTuesday-2025-10-15 Production\nsql-svr01  HV-NODE02  Failed   PatchTuesday-2025-10-15 ProductionOnly\n","text",[15,289,286],{"__ignoreMap":208},[11,291,292],{},"Preview a cluster-wide run without changing anything.",[203,294,296],{"className":205,"code":295,"language":207,"meta":208,"style":208},".\\New-PrePatchCheckpoint.ps1 -ClusterName 'hv-clu01' -WhatIf\n",[15,297,298],{"__ignoreMap":208},[97,299,300,302,304,306,308,310,312],{"class":213,"line":214},[97,301,42],{"class":217},[97,303,221],{"class":220},[97,305,225],{"class":224},[97,307,247],{"class":217},[97,309,251],{"class":250},[97,311,225],{"class":224},[97,313,314],{"class":217},"WhatIf\n",[11,316,317,318,321],{},"Run it from Cluster-Aware Updating, so each node checkpoints its own VMs just before CAU drains and patches it. The pre-update script must be a ",[15,319,320],{},".ps1"," reachable from every node (a CSV or a highly available share), and PowerShell remoting must be enabled on each node.",[203,323,325],{"className":205,"code":324,"language":207,"meta":208,"style":208},"$parameters = @{\n    ClusterName           = 'hv-clu01'\n    CauPluginName         = 'Microsoft.WindowsUpdatePlugin'\n    PreUpdateScript       = 'C:\\ClusterStorage\\Volume1\\Scripts\\New-PrePatchCheckpoint.ps1'\n    MaxFailedNodes        = 1\n    MaxRetriesPerNode     = 3\n    RequireAllNodesOnline = $true\n    Force                 = $true\n}\nInvoke-CauRun @parameters\n",[15,326,327,341,352,363,374,385,396,407,417,423],{"__ignoreMap":208},[97,328,329,332,335,338],{"class":213,"line":214},[97,330,331],{"class":217},"$parameters ",[97,333,334],{"class":224},"=",[97,336,337],{"class":224}," @",[97,339,340],{"class":217},"{\n",[97,342,344,347,349],{"class":213,"line":343},2,[97,345,346],{"class":217},"    ClusterName           ",[97,348,334],{"class":224},[97,350,351],{"class":250}," 'hv-clu01'\n",[97,353,355,358,360],{"class":213,"line":354},3,[97,356,357],{"class":217},"    CauPluginName         ",[97,359,334],{"class":224},[97,361,362],{"class":250}," 'Microsoft.WindowsUpdatePlugin'\n",[97,364,366,369,371],{"class":213,"line":365},4,[97,367,368],{"class":217},"    PreUpdateScript       ",[97,370,334],{"class":224},[97,372,373],{"class":250}," 'C:\\ClusterStorage\\Volume1\\Scripts\\New-PrePatchCheckpoint.ps1'\n",[97,375,377,380,382],{"class":213,"line":376},5,[97,378,379],{"class":217},"    MaxFailedNodes        ",[97,381,334],{"class":224},[97,383,384],{"class":220}," 1\n",[97,386,388,391,393],{"class":213,"line":387},6,[97,389,390],{"class":217},"    MaxRetriesPerNode     ",[97,392,334],{"class":224},[97,394,395],{"class":220}," 3\n",[97,397,399,402,404],{"class":213,"line":398},7,[97,400,401],{"class":217},"    RequireAllNodesOnline ",[97,403,334],{"class":224},[97,405,406],{"class":220}," $true\n",[97,408,410,413,415],{"class":213,"line":409},8,[97,411,412],{"class":217},"    Force                 ",[97,414,334],{"class":224},[97,416,406],{"class":220},[97,418,420],{"class":213,"line":419},9,[97,421,422],{"class":217},"}\n",[97,424,426,429],{"class":213,"line":425},10,[97,427,428],{"class":220},"Invoke-CauRun",[97,430,431],{"class":217}," @parameters\n",[20,433,435],{"id":434},"script","Script",[203,437,439],{"className":205,"code":438,"language":207,"meta":208,"style":208},"\u003C#\n.SYNOPSIS\n    Creates a dated pre-patch checkpoint on running Hyper-V VMs and prunes the ones earlier runs created.\n.DESCRIPTION\n    Finds the target VMs (every running VM on the local host, on a list of hosts, or on every Up node of a\n    failover cluster, optionally filtered by name), removes this script's own checkpoints older than the\n    retention window, then takes a checkpoint named \u003Cprefix>-\u003Cyyyy-MM-dd> using each VM's configured\n    checkpoint type. Returns one object per action. A failure on one VM is reported and the run continues,\n    so the script is safe to use as a Cluster-Aware Updating pre-update script.\n.PARAMETER VMName\n    Names of VMs to checkpoint. Defaults to every running VM on the target hosts.\n.PARAMETER ComputerName\n    Hyper-V hosts to target. Defaults to the local computer. Ignored when ClusterName is set.\n.PARAMETER ClusterName\n    Failover cluster whose nodes (those that are Up) are all targeted.\n.PARAMETER RetentionDays\n    Checkpoints created by this script and older than this many days are removed before new ones are taken.\n.PARAMETER CheckpointPrefix\n    Prefix used to name and identify this script's checkpoints.\n.PARAMETER RequirePatchWeek\n    Exit unless today falls in the seven days starting on this month's second Tuesday.\n.EXAMPLE\n    .\\New-PrePatchCheckpoint.ps1 -ClusterName 'hv-clu01' -VMName 'app-svr01', 'app-svr02' -RetentionDays 2\n.NOTES\n    Author  : Thomas Lasswell (https:\u002F\u002Fwww.techcolumnist.com)\n    Version : 1.0 (2025-10-15)\n    Requires: Hyper-V PowerShell module; FailoverClusters module for -ClusterName\n#>\n\n[CmdletBinding(SupportsShouldProcess = $true)]\nparam (\n    [Parameter(Mandatory = $false)]\n    [string[]]$VMName,\n\n    [Parameter(Mandatory = $false)]\n    [string[]]$ComputerName = $env:COMPUTERNAME,\n\n    [Parameter(Mandatory = $false)]\n    [string]$ClusterName,\n\n    [Parameter(Mandatory = $false)]\n    [ValidateRange(0, 365)]\n    [int]$RetentionDays = 7,\n\n    [Parameter(Mandatory = $false)]\n    [string]$CheckpointPrefix = 'PatchTuesday',\n\n    [switch]$RequirePatchWeek\n)\n\nfunction Get-PatchTuesday {\n    param (\n        [datetime]$Date\n    )\n\n    # Second Tuesday of the month: find the first Tuesday, then add a week.\n    $firstOfMonth = [datetime]::new($Date.Year, $Date.Month, 1)\n    $daysToTuesday = ([int][System.DayOfWeek]::Tuesday - [int]$firstOfMonth.DayOfWeek + 7) % 7\n\n    return $firstOfMonth.AddDays($daysToTuesday + 7)\n}\n\n$now = Get-Date\n\nif ($RequirePatchWeek) {\n    $patchTuesday = Get-PatchTuesday -Date $now\n\n    if ($now.Date -lt $patchTuesday -or $now.Date -ge $patchTuesday.AddDays(7)) {\n        Write-Verbose \"Today is outside the patch week that starts $($patchTuesday.ToString('yyyy-MM-dd')); nothing to do\"\n        return\n    }\n}\n\n# Work out which hosts to query.\n$targetHosts = if ($ClusterName) {\n    (Get-ClusterNode -Cluster $ClusterName | Where-Object { $_.State -eq 'Up' }).Name\n} else {\n    $ComputerName\n}\n\n# Get-VM with no host falls back to the local computer, so stop rather than checkpoint the wrong machine.\nif ($ClusterName -and -not $targetHosts) {\n    throw \"No nodes of cluster $ClusterName are Up.\"\n}\n\n$allVMs = Get-VM -ComputerName $targetHosts\n\n$targetVMs = if ($VMName) {\n    $allVMs | Where-Object { $VMName -contains $_.Name }\n} else {\n    $allVMs | Where-Object { $_.State -eq 'Running' }\n}\n\nforeach ($name in $VMName) {\n    if ($targetVMs.Name -notcontains $name) {\n        Write-Warning \"VM '$name' was not found on $($targetHosts -join ', ')\"\n    }\n}\n\n$checkpointName = '{0}-{1:yyyy-MM-dd}' -f $CheckpointPrefix, $now\n$cutoffDate = $now.AddDays(-$RetentionDays)\n\nforeach ($vm in $targetVMs) {\n    if (\"$($vm.CheckpointType)\" -eq 'Disabled') {\n        Write-Warning \"Checkpoints are disabled on $($vm.Name), skipping\"\n        continue\n    }\n\n    if (\"$($vm.CheckpointType)\" -eq 'Standard') {\n        Write-Warning \"$($vm.Name) uses standard checkpoints, which capture memory state and are not application consistent\"\n    }\n\n    # Remove this script's own expired checkpoints before creating a new one.\n    $oldCheckpoints = Get-VMSnapshot -VM $vm |\n        Where-Object { $_.Name -like \"$CheckpointPrefix-*\" -and $_.CreationTime -lt $cutoffDate }\n\n    foreach ($old in $oldCheckpoints) {\n        if ($PSCmdlet.ShouldProcess(\"$($vm.Name) on $($vm.ComputerName)\", \"Remove checkpoint '$($old.Name)'\")) {\n            Write-Verbose \"Removing expired checkpoint '$($old.Name)' on $($vm.Name)\"\n            $removeAction = 'Removed'\n\n            try {\n                Remove-VMSnapshot -VMSnapshot $old -ErrorAction Stop\n            } catch {\n                Write-Warning \"Removing checkpoint '$($old.Name)' from $($vm.Name) failed: $($_.Exception.Message)\"\n                $removeAction = 'Failed'\n            }\n\n            [PSCustomObject]@{\n                VM             = $vm.Name\n                Host           = $vm.ComputerName\n                Action         = $removeAction\n                Checkpoint     = $old.Name\n                CheckpointType = \"$($vm.CheckpointType)\"\n            }\n        }\n    }\n\n    $existing = Get-VMSnapshot -VM $vm -Name $checkpointName -ErrorAction SilentlyContinue\n\n    if ($existing) {\n        Write-Verbose \"Checkpoint '$checkpointName' already exists on $($vm.Name), skipping\"\n        continue\n    }\n\n    if ($PSCmdlet.ShouldProcess(\"$($vm.Name) on $($vm.ComputerName)\", \"Create checkpoint '$checkpointName'\")) {\n        Write-Verbose \"Creating checkpoint '$checkpointName' on $($vm.Name)\"\n        $action = 'Created'\n\n        try {\n            Checkpoint-VM -VM $vm -SnapshotName $checkpointName -ErrorAction Stop\n        } catch {\n            Write-Warning \"Checkpoint of $($vm.Name) failed: $($_.Exception.Message)\"\n            $action = 'Failed'\n        }\n\n        [PSCustomObject]@{\n            VM             = $vm.Name\n            Host           = $vm.ComputerName\n            Action         = $action\n            Checkpoint     = $checkpointName\n            CheckpointType = \"$($vm.CheckpointType)\"\n        }\n    }\n}\n",[15,440,441,447,454,459,466,471,476,481,486,491,501,507,517,523,533,539,549,555,565,571,581,587,595,601,609,615,621,627,633,640,665,674,695,708,713,730,753,758,775,787,792,809,829,846,851,868,885,890,900,906,911,924,932,944,950,955,961,989,1035,1040,1055,1060,1065,1076,1081,1090,1105,1110,1143,1171,1177,1183,1188,1193,1199,1213,1251,1262,1268,1273,1278,1284,1301,1316,1321,1326,1342,1347,1360,1382,1391,1414,1419,1424,1439,1453,1487,1492,1497,1502,1524,1540,1545,1558,1589,1609,1615,1620,1625,1651,1670,1675,1680,1686,1705,1742,1747,1761,1818,1848,1859,1864,1872,1888,1899,1943,1954,1960,1965,1982,1993,2004,2015,2026,2046,2051,2057,2062,2067,2091,2096,2104,2128,2133,2138,2143,2187,2209,2220,2225,2233,2252,2262,2293,2303,2308,2313,2326,2336,2346,2357,2368,2388,2393,2398],{"__ignoreMap":208},[97,442,443],{"class":213,"line":214},[97,444,446],{"class":445},"sAwPA","\u003C#\n",[97,448,449,451],{"class":213,"line":343},[97,450,42],{"class":220},[97,452,453],{"class":224},"SYNOPSIS\n",[97,455,456],{"class":213,"line":354},[97,457,458],{"class":445},"    Creates a dated pre-patch checkpoint on running Hyper-V VMs and prunes the ones earlier runs created.\n",[97,460,461,463],{"class":213,"line":365},[97,462,42],{"class":220},[97,464,465],{"class":224},"DESCRIPTION\n",[97,467,468],{"class":213,"line":376},[97,469,470],{"class":445},"    Finds the target VMs (every running VM on the local host, on a list of hosts, or on every Up node of a\n",[97,472,473],{"class":213,"line":387},[97,474,475],{"class":445},"    failover cluster, optionally filtered by name), removes this script's own checkpoints older than the\n",[97,477,478],{"class":213,"line":398},[97,479,480],{"class":445},"    retention window, then takes a checkpoint named \u003Cprefix>-\u003Cyyyy-MM-dd> using each VM's configured\n",[97,482,483],{"class":213,"line":409},[97,484,485],{"class":445},"    checkpoint type. Returns one object per action. A failure on one VM is reported and the run continues,\n",[97,487,488],{"class":213,"line":419},[97,489,490],{"class":445},"    so the script is safe to use as a Cluster-Aware Updating pre-update script.\n",[97,492,493,495,498],{"class":213,"line":425},[97,494,42],{"class":220},[97,496,497],{"class":224},"PARAMETER",[97,499,500],{"class":224}," VMName\n",[97,502,504],{"class":213,"line":503},11,[97,505,506],{"class":445},"    Names of VMs to checkpoint. Defaults to every running VM on the target hosts.\n",[97,508,510,512,514],{"class":213,"line":509},12,[97,511,42],{"class":220},[97,513,497],{"class":224},[97,515,516],{"class":224}," ComputerName\n",[97,518,520],{"class":213,"line":519},13,[97,521,522],{"class":445},"    Hyper-V hosts to target. Defaults to the local computer. Ignored when ClusterName is set.\n",[97,524,526,528,530],{"class":213,"line":525},14,[97,527,42],{"class":220},[97,529,497],{"class":224},[97,531,532],{"class":224}," ClusterName\n",[97,534,536],{"class":213,"line":535},15,[97,537,538],{"class":445},"    Failover cluster whose nodes (those that are Up) are all targeted.\n",[97,540,542,544,546],{"class":213,"line":541},16,[97,543,42],{"class":220},[97,545,497],{"class":224},[97,547,548],{"class":224}," RetentionDays\n",[97,550,552],{"class":213,"line":551},17,[97,553,554],{"class":445},"    Checkpoints created by this script and older than this many days are removed before new ones are taken.\n",[97,556,558,560,562],{"class":213,"line":557},18,[97,559,42],{"class":220},[97,561,497],{"class":224},[97,563,564],{"class":224}," CheckpointPrefix\n",[97,566,568],{"class":213,"line":567},19,[97,569,570],{"class":445},"    Prefix used to name and identify this script's checkpoints.\n",[97,572,574,576,578],{"class":213,"line":573},20,[97,575,42],{"class":220},[97,577,497],{"class":224},[97,579,580],{"class":224}," RequirePatchWeek\n",[97,582,584],{"class":213,"line":583},21,[97,585,586],{"class":445},"    Exit unless today falls in the seven days starting on this month's second Tuesday.\n",[97,588,590,592],{"class":213,"line":589},22,[97,591,42],{"class":220},[97,593,594],{"class":224},"EXAMPLE\n",[97,596,598],{"class":213,"line":597},23,[97,599,600],{"class":445},"    .\\New-PrePatchCheckpoint.ps1 -ClusterName 'hv-clu01' -VMName 'app-svr01', 'app-svr02' -RetentionDays 2\n",[97,602,604,606],{"class":213,"line":603},24,[97,605,42],{"class":220},[97,607,608],{"class":224},"NOTES\n",[97,610,612],{"class":213,"line":611},25,[97,613,614],{"class":445},"    Author  : Thomas Lasswell (https:\u002F\u002Fwww.techcolumnist.com)\n",[97,616,618],{"class":213,"line":617},26,[97,619,620],{"class":445},"    Version : 1.0 (2025-10-15)\n",[97,622,624],{"class":213,"line":623},27,[97,625,626],{"class":445},"    Requires: Hyper-V PowerShell module; FailoverClusters module for -ClusterName\n",[97,628,630],{"class":213,"line":629},28,[97,631,632],{"class":445},"#>\n",[97,634,636],{"class":213,"line":635},29,[97,637,639],{"emptyLinePlaceholder":638},true,"\n",[97,641,643,646,649,652,656,659,662],{"class":213,"line":642},30,[97,644,645],{"class":217},"[",[97,647,648],{"class":220},"CmdletBinding",[97,650,651],{"class":217},"(",[97,653,655],{"class":654},"s9osk","SupportsShouldProcess",[97,657,658],{"class":224}," =",[97,660,661],{"class":220}," $true",[97,663,664],{"class":217},")]\n",[97,666,668,671],{"class":213,"line":667},31,[97,669,670],{"class":224},"param",[97,672,673],{"class":217}," (\n",[97,675,677,680,683,685,688,690,693],{"class":213,"line":676},32,[97,678,679],{"class":217},"    [",[97,681,682],{"class":220},"Parameter",[97,684,651],{"class":217},[97,686,687],{"class":654},"Mandatory",[97,689,658],{"class":224},[97,691,692],{"class":220}," $false",[97,694,664],{"class":217},[97,696,698,700,702,705],{"class":213,"line":697},33,[97,699,679],{"class":217},[97,701,95],{"class":224},[97,703,704],{"class":217},"[]]$VMName",[97,706,707],{"class":224},",\n",[97,709,711],{"class":213,"line":710},34,[97,712,639],{"emptyLinePlaceholder":638},[97,714,716,718,720,722,724,726,728],{"class":213,"line":715},35,[97,717,679],{"class":217},[97,719,682],{"class":220},[97,721,651],{"class":217},[97,723,687],{"class":654},[97,725,658],{"class":224},[97,727,692],{"class":220},[97,729,664],{"class":217},[97,731,733,735,737,740,742,745,748,751],{"class":213,"line":732},36,[97,734,679],{"class":217},[97,736,95],{"class":224},[97,738,739],{"class":217},"[]]$ComputerName ",[97,741,334],{"class":224},[97,743,744],{"class":217}," $",[97,746,747],{"class":220},"env:",[97,749,750],{"class":217},"COMPUTERNAME",[97,752,707],{"class":224},[97,754,756],{"class":213,"line":755},37,[97,757,639],{"emptyLinePlaceholder":638},[97,759,761,763,765,767,769,771,773],{"class":213,"line":760},38,[97,762,679],{"class":217},[97,764,682],{"class":220},[97,766,651],{"class":217},[97,768,687],{"class":654},[97,770,658],{"class":224},[97,772,692],{"class":220},[97,774,664],{"class":217},[97,776,778,780,782,785],{"class":213,"line":777},39,[97,779,679],{"class":217},[97,781,95],{"class":224},[97,783,784],{"class":217},"]$ClusterName",[97,786,707],{"class":224},[97,788,790],{"class":213,"line":789},40,[97,791,639],{"emptyLinePlaceholder":638},[97,793,795,797,799,801,803,805,807],{"class":213,"line":794},41,[97,796,679],{"class":217},[97,798,682],{"class":220},[97,800,651],{"class":217},[97,802,687],{"class":654},[97,804,658],{"class":224},[97,806,692],{"class":220},[97,808,664],{"class":217},[97,810,812,814,817,819,822,824,827],{"class":213,"line":811},42,[97,813,679],{"class":217},[97,815,816],{"class":220},"ValidateRange",[97,818,651],{"class":217},[97,820,821],{"class":220},"0",[97,823,262],{"class":224},[97,825,826],{"class":220}," 365",[97,828,664],{"class":217},[97,830,832,834,836,839,841,844],{"class":213,"line":831},43,[97,833,679],{"class":217},[97,835,147],{"class":224},[97,837,838],{"class":217},"]$RetentionDays ",[97,840,334],{"class":224},[97,842,843],{"class":220}," 7",[97,845,707],{"class":224},[97,847,849],{"class":213,"line":848},44,[97,850,639],{"emptyLinePlaceholder":638},[97,852,854,856,858,860,862,864,866],{"class":213,"line":853},45,[97,855,679],{"class":217},[97,857,682],{"class":220},[97,859,651],{"class":217},[97,861,687],{"class":654},[97,863,658],{"class":224},[97,865,692],{"class":220},[97,867,664],{"class":217},[97,869,871,873,875,878,880,883],{"class":213,"line":870},46,[97,872,679],{"class":217},[97,874,95],{"class":224},[97,876,877],{"class":217},"]$CheckpointPrefix ",[97,879,334],{"class":224},[97,881,882],{"class":250}," 'PatchTuesday'",[97,884,707],{"class":224},[97,886,888],{"class":213,"line":887},47,[97,889,639],{"emptyLinePlaceholder":638},[97,891,893,895,897],{"class":213,"line":892},48,[97,894,679],{"class":217},[97,896,179],{"class":224},[97,898,899],{"class":217},"]$RequirePatchWeek\n",[97,901,903],{"class":213,"line":902},49,[97,904,905],{"class":217},")\n",[97,907,909],{"class":213,"line":908},50,[97,910,639],{"emptyLinePlaceholder":638},[97,912,914,917,921],{"class":213,"line":913},51,[97,915,916],{"class":224},"function",[97,918,920],{"class":919},"svObZ"," Get-PatchTuesday",[97,922,923],{"class":217}," {\n",[97,925,927,930],{"class":213,"line":926},52,[97,928,929],{"class":224},"    param",[97,931,673],{"class":217},[97,933,935,938,941],{"class":213,"line":934},53,[97,936,937],{"class":217},"        [",[97,939,940],{"class":224},"datetime",[97,942,943],{"class":217},"]$Date\n",[97,945,947],{"class":213,"line":946},54,[97,948,949],{"class":217},"    )\n",[97,951,953],{"class":213,"line":952},55,[97,954,639],{"emptyLinePlaceholder":638},[97,956,958],{"class":213,"line":957},56,[97,959,960],{"class":445},"    # Second Tuesday of the month: find the first Tuesday, then add a week.\n",[97,962,964,967,969,972,974,977,979,982,984,987],{"class":213,"line":963},57,[97,965,966],{"class":217},"    $firstOfMonth ",[97,968,334],{"class":224},[97,970,971],{"class":217}," [",[97,973,940],{"class":224},[97,975,976],{"class":217},"]::new($Date.Year",[97,978,262],{"class":224},[97,980,981],{"class":217}," $Date.Month",[97,983,262],{"class":224},[97,985,986],{"class":220}," 1",[97,988,905],{"class":217},[97,990,992,995,997,1000,1002,1005,1008,1011,1014,1016,1018,1021,1024,1026,1029,1032],{"class":213,"line":991},58,[97,993,994],{"class":217},"    $daysToTuesday ",[97,996,334],{"class":224},[97,998,999],{"class":217}," ([",[97,1001,147],{"class":224},[97,1003,1004],{"class":217},"][",[97,1006,1007],{"class":224},"System.DayOfWeek",[97,1009,1010],{"class":217},"]::Tuesday ",[97,1012,1013],{"class":224},"-",[97,1015,971],{"class":217},[97,1017,147],{"class":224},[97,1019,1020],{"class":217},"]$firstOfMonth.DayOfWeek ",[97,1022,1023],{"class":224},"+",[97,1025,843],{"class":220},[97,1027,1028],{"class":217},") ",[97,1030,1031],{"class":224},"%",[97,1033,1034],{"class":220}," 7\n",[97,1036,1038],{"class":213,"line":1037},59,[97,1039,639],{"emptyLinePlaceholder":638},[97,1041,1043,1046,1049,1051,1053],{"class":213,"line":1042},60,[97,1044,1045],{"class":224},"    return",[97,1047,1048],{"class":217}," $firstOfMonth.AddDays($daysToTuesday ",[97,1050,1023],{"class":224},[97,1052,843],{"class":220},[97,1054,905],{"class":217},[97,1056,1058],{"class":213,"line":1057},61,[97,1059,422],{"class":217},[97,1061,1063],{"class":213,"line":1062},62,[97,1064,639],{"emptyLinePlaceholder":638},[97,1066,1068,1071,1073],{"class":213,"line":1067},63,[97,1069,1070],{"class":217},"$now ",[97,1072,334],{"class":224},[97,1074,1075],{"class":220}," Get-Date\n",[97,1077,1079],{"class":213,"line":1078},64,[97,1080,639],{"emptyLinePlaceholder":638},[97,1082,1084,1087],{"class":213,"line":1083},65,[97,1085,1086],{"class":224},"if",[97,1088,1089],{"class":217}," ($RequirePatchWeek) {\n",[97,1091,1093,1096,1098,1100,1102],{"class":213,"line":1092},66,[97,1094,1095],{"class":217},"    $patchTuesday ",[97,1097,334],{"class":224},[97,1099,920],{"class":220},[97,1101,225],{"class":224},[97,1103,1104],{"class":217},"Date $now\n",[97,1106,1108],{"class":213,"line":1107},67,[97,1109,639],{"emptyLinePlaceholder":638},[97,1111,1113,1116,1119,1122,1125,1128,1131,1134,1137,1140],{"class":213,"line":1112},68,[97,1114,1115],{"class":224},"    if",[97,1117,1118],{"class":217}," ($now.Date ",[97,1120,1121],{"class":224},"-lt",[97,1123,1124],{"class":217}," $patchTuesday ",[97,1126,1127],{"class":224},"-or",[97,1129,1130],{"class":217}," $now.Date ",[97,1132,1133],{"class":224},"-ge",[97,1135,1136],{"class":217}," $patchTuesday.AddDays(",[97,1138,1139],{"class":220},"7",[97,1141,1142],{"class":217},")) {\n",[97,1144,1146,1149,1152,1155,1157,1160,1162,1165,1168],{"class":213,"line":1145},69,[97,1147,1148],{"class":220},"        Write-Verbose",[97,1150,1151],{"class":250}," \"Today is outside the patch week that starts ",[97,1153,1154],{"class":224},"$",[97,1156,651],{"class":250},[97,1158,1159],{"class":217},"$patchTuesday.ToString",[97,1161,651],{"class":250},[97,1163,1164],{"class":250},"'yyyy-MM-dd'",[97,1166,1167],{"class":250},"))",[97,1169,1170],{"class":250},"; nothing to do\"\n",[97,1172,1174],{"class":213,"line":1173},70,[97,1175,1176],{"class":224},"        return\n",[97,1178,1180],{"class":213,"line":1179},71,[97,1181,1182],{"class":217},"    }\n",[97,1184,1186],{"class":213,"line":1185},72,[97,1187,422],{"class":217},[97,1189,1191],{"class":213,"line":1190},73,[97,1192,639],{"emptyLinePlaceholder":638},[97,1194,1196],{"class":213,"line":1195},74,[97,1197,1198],{"class":445},"# Work out which hosts to query.\n",[97,1200,1202,1205,1207,1210],{"class":213,"line":1201},75,[97,1203,1204],{"class":217},"$targetHosts ",[97,1206,334],{"class":224},[97,1208,1209],{"class":224}," if",[97,1211,1212],{"class":217}," ($ClusterName) {\n",[97,1214,1216,1219,1222,1224,1227,1230,1233,1236,1239,1242,1245,1248],{"class":213,"line":1215},76,[97,1217,1218],{"class":217},"    (",[97,1220,1221],{"class":220},"Get-ClusterNode",[97,1223,225],{"class":224},[97,1225,1226],{"class":217},"Cluster $ClusterName ",[97,1228,1229],{"class":224},"|",[97,1231,1232],{"class":220}," Where-Object",[97,1234,1235],{"class":217}," { ",[97,1237,1238],{"class":220},"$_",[97,1240,1241],{"class":217},".State ",[97,1243,1244],{"class":224},"-eq",[97,1246,1247],{"class":250}," 'Up'",[97,1249,1250],{"class":217}," }).Name\n",[97,1252,1254,1257,1260],{"class":213,"line":1253},77,[97,1255,1256],{"class":217},"} ",[97,1258,1259],{"class":224},"else",[97,1261,923],{"class":217},[97,1263,1265],{"class":213,"line":1264},78,[97,1266,1267],{"class":217},"    $ComputerName\n",[97,1269,1271],{"class":213,"line":1270},79,[97,1272,422],{"class":217},[97,1274,1276],{"class":213,"line":1275},80,[97,1277,639],{"emptyLinePlaceholder":638},[97,1279,1281],{"class":213,"line":1280},81,[97,1282,1283],{"class":445},"# Get-VM with no host falls back to the local computer, so stop rather than checkpoint the wrong machine.\n",[97,1285,1287,1289,1292,1295,1298],{"class":213,"line":1286},82,[97,1288,1086],{"class":224},[97,1290,1291],{"class":217}," ($ClusterName ",[97,1293,1294],{"class":224},"-and",[97,1296,1297],{"class":224}," -not",[97,1299,1300],{"class":217}," $targetHosts) {\n",[97,1302,1304,1307,1310,1313],{"class":213,"line":1303},83,[97,1305,1306],{"class":224},"    throw",[97,1308,1309],{"class":250}," \"No nodes of cluster ",[97,1311,1312],{"class":217},"$ClusterName",[97,1314,1315],{"class":250}," are Up.\"\n",[97,1317,1319],{"class":213,"line":1318},84,[97,1320,422],{"class":217},[97,1322,1324],{"class":213,"line":1323},85,[97,1325,639],{"emptyLinePlaceholder":638},[97,1327,1329,1332,1334,1337,1339],{"class":213,"line":1328},86,[97,1330,1331],{"class":217},"$allVMs ",[97,1333,334],{"class":224},[97,1335,1336],{"class":220}," Get-VM",[97,1338,225],{"class":224},[97,1340,1341],{"class":217},"ComputerName $targetHosts\n",[97,1343,1345],{"class":213,"line":1344},87,[97,1346,639],{"emptyLinePlaceholder":638},[97,1348,1350,1353,1355,1357],{"class":213,"line":1349},88,[97,1351,1352],{"class":217},"$targetVMs ",[97,1354,334],{"class":224},[97,1356,1209],{"class":224},[97,1358,1359],{"class":217}," ($VMName) {\n",[97,1361,1363,1366,1368,1370,1373,1376,1379],{"class":213,"line":1362},89,[97,1364,1365],{"class":217},"    $allVMs ",[97,1367,1229],{"class":224},[97,1369,1232],{"class":220},[97,1371,1372],{"class":217}," { $VMName ",[97,1374,1375],{"class":224},"-contains",[97,1377,1378],{"class":220}," $_",[97,1380,1381],{"class":217},".Name }\n",[97,1383,1385,1387,1389],{"class":213,"line":1384},90,[97,1386,1256],{"class":217},[97,1388,1259],{"class":224},[97,1390,923],{"class":217},[97,1392,1394,1396,1398,1400,1402,1404,1406,1408,1411],{"class":213,"line":1393},91,[97,1395,1365],{"class":217},[97,1397,1229],{"class":224},[97,1399,1232],{"class":220},[97,1401,1235],{"class":217},[97,1403,1238],{"class":220},[97,1405,1241],{"class":217},[97,1407,1244],{"class":224},[97,1409,1410],{"class":250}," 'Running'",[97,1412,1413],{"class":217}," }\n",[97,1415,1417],{"class":213,"line":1416},92,[97,1418,422],{"class":217},[97,1420,1422],{"class":213,"line":1421},93,[97,1423,639],{"emptyLinePlaceholder":638},[97,1425,1427,1430,1433,1436],{"class":213,"line":1426},94,[97,1428,1429],{"class":224},"foreach",[97,1431,1432],{"class":217}," ($name ",[97,1434,1435],{"class":224},"in",[97,1437,1438],{"class":217}," $VMName) {\n",[97,1440,1442,1444,1447,1450],{"class":213,"line":1441},95,[97,1443,1115],{"class":224},[97,1445,1446],{"class":217}," ($targetVMs.Name ",[97,1448,1449],{"class":224},"-notcontains",[97,1451,1452],{"class":217}," $name) {\n",[97,1454,1456,1459,1462,1465,1468,1470,1472,1475,1478,1481,1484],{"class":213,"line":1455},96,[97,1457,1458],{"class":220},"        Write-Warning",[97,1460,1461],{"class":250}," \"VM '",[97,1463,1464],{"class":217},"$name",[97,1466,1467],{"class":250},"' was not found on ",[97,1469,1154],{"class":224},[97,1471,651],{"class":250},[97,1473,1474],{"class":217},"$targetHosts",[97,1476,1477],{"class":224}," -join",[97,1479,1480],{"class":250}," ', '",[97,1482,1483],{"class":250},")",[97,1485,1486],{"class":250},"\"\n",[97,1488,1490],{"class":213,"line":1489},97,[97,1491,1182],{"class":217},[97,1493,1495],{"class":213,"line":1494},98,[97,1496,422],{"class":217},[97,1498,1500],{"class":213,"line":1499},99,[97,1501,639],{"emptyLinePlaceholder":638},[97,1503,1505,1508,1510,1513,1516,1519,1521],{"class":213,"line":1504},100,[97,1506,1507],{"class":217},"$checkpointName ",[97,1509,334],{"class":224},[97,1511,1512],{"class":250}," '{0}-{1:yyyy-MM-dd}'",[97,1514,1515],{"class":224}," -f",[97,1517,1518],{"class":217}," $CheckpointPrefix",[97,1520,262],{"class":224},[97,1522,1523],{"class":217}," $now\n",[97,1525,1527,1530,1532,1535,1537],{"class":213,"line":1526},101,[97,1528,1529],{"class":217},"$cutoffDate ",[97,1531,334],{"class":224},[97,1533,1534],{"class":217}," $now.AddDays(",[97,1536,1013],{"class":224},[97,1538,1539],{"class":217},"$RetentionDays)\n",[97,1541,1543],{"class":213,"line":1542},102,[97,1544,639],{"emptyLinePlaceholder":638},[97,1546,1548,1550,1553,1555],{"class":213,"line":1547},103,[97,1549,1429],{"class":224},[97,1551,1552],{"class":217}," ($vm ",[97,1554,1435],{"class":224},[97,1556,1557],{"class":217}," $targetVMs) {\n",[97,1559,1561,1563,1566,1569,1571,1573,1576,1578,1580,1583,1586],{"class":213,"line":1560},104,[97,1562,1115],{"class":224},[97,1564,1565],{"class":217}," (",[97,1567,1568],{"class":250},"\"",[97,1570,1154],{"class":224},[97,1572,651],{"class":250},[97,1574,1575],{"class":217},"$vm.CheckpointType",[97,1577,1483],{"class":250},[97,1579,1568],{"class":250},[97,1581,1582],{"class":224}," -eq",[97,1584,1585],{"class":250}," 'Disabled'",[97,1587,1588],{"class":217},") {\n",[97,1590,1592,1594,1597,1599,1601,1604,1606],{"class":213,"line":1591},105,[97,1593,1458],{"class":220},[97,1595,1596],{"class":250}," \"Checkpoints are disabled on ",[97,1598,1154],{"class":224},[97,1600,651],{"class":250},[97,1602,1603],{"class":217},"$vm.Name",[97,1605,1483],{"class":250},[97,1607,1608],{"class":250},", skipping\"\n",[97,1610,1612],{"class":213,"line":1611},106,[97,1613,1614],{"class":224},"        continue\n",[97,1616,1618],{"class":213,"line":1617},107,[97,1619,1182],{"class":217},[97,1621,1623],{"class":213,"line":1622},108,[97,1624,639],{"emptyLinePlaceholder":638},[97,1626,1628,1630,1632,1634,1636,1638,1640,1642,1644,1646,1649],{"class":213,"line":1627},109,[97,1629,1115],{"class":224},[97,1631,1565],{"class":217},[97,1633,1568],{"class":250},[97,1635,1154],{"class":224},[97,1637,651],{"class":250},[97,1639,1575],{"class":217},[97,1641,1483],{"class":250},[97,1643,1568],{"class":250},[97,1645,1582],{"class":224},[97,1647,1648],{"class":250}," 'Standard'",[97,1650,1588],{"class":217},[97,1652,1654,1656,1659,1661,1663,1665,1667],{"class":213,"line":1653},110,[97,1655,1458],{"class":220},[97,1657,1658],{"class":250}," \"",[97,1660,1154],{"class":224},[97,1662,651],{"class":250},[97,1664,1603],{"class":217},[97,1666,1483],{"class":250},[97,1668,1669],{"class":250}," uses standard checkpoints, which capture memory state and are not application consistent\"\n",[97,1671,1673],{"class":213,"line":1672},111,[97,1674,1182],{"class":217},[97,1676,1678],{"class":213,"line":1677},112,[97,1679,639],{"emptyLinePlaceholder":638},[97,1681,1683],{"class":213,"line":1682},113,[97,1684,1685],{"class":445},"    # Remove this script's own expired checkpoints before creating a new one.\n",[97,1687,1689,1692,1694,1697,1699,1702],{"class":213,"line":1688},114,[97,1690,1691],{"class":217},"    $oldCheckpoints ",[97,1693,334],{"class":224},[97,1695,1696],{"class":220}," Get-VMSnapshot",[97,1698,225],{"class":224},[97,1700,1701],{"class":217},"VM $vm ",[97,1703,1704],{"class":224},"|\n",[97,1706,1708,1711,1713,1715,1718,1721,1723,1726,1729,1732,1734,1737,1739],{"class":213,"line":1707},115,[97,1709,1710],{"class":220},"        Where-Object",[97,1712,1235],{"class":217},[97,1714,1238],{"class":220},[97,1716,1717],{"class":217},".Name ",[97,1719,1720],{"class":224},"-like",[97,1722,1658],{"class":250},[97,1724,1725],{"class":217},"$CheckpointPrefix",[97,1727,1728],{"class":250},"-*\"",[97,1730,1731],{"class":224}," -and",[97,1733,1378],{"class":220},[97,1735,1736],{"class":217},".CreationTime ",[97,1738,1121],{"class":224},[97,1740,1741],{"class":217}," $cutoffDate }\n",[97,1743,1745],{"class":213,"line":1744},116,[97,1746,639],{"emptyLinePlaceholder":638},[97,1748,1750,1753,1756,1758],{"class":213,"line":1749},117,[97,1751,1752],{"class":224},"    foreach",[97,1754,1755],{"class":217}," ($old ",[97,1757,1435],{"class":224},[97,1759,1760],{"class":217}," $oldCheckpoints) {\n",[97,1762,1764,1767,1769,1772,1775,1777,1779,1781,1783,1785,1788,1790,1792,1795,1797,1799,1801,1804,1806,1808,1811,1813,1816],{"class":213,"line":1763},118,[97,1765,1766],{"class":224},"        if",[97,1768,1565],{"class":217},[97,1770,1771],{"class":220},"$PSCmdlet",[97,1773,1774],{"class":217},".ShouldProcess(",[97,1776,1568],{"class":250},[97,1778,1154],{"class":224},[97,1780,651],{"class":250},[97,1782,1603],{"class":217},[97,1784,1483],{"class":250},[97,1786,1787],{"class":250}," on ",[97,1789,1154],{"class":224},[97,1791,651],{"class":250},[97,1793,1794],{"class":217},"$vm.ComputerName",[97,1796,1483],{"class":250},[97,1798,1568],{"class":250},[97,1800,262],{"class":224},[97,1802,1803],{"class":250}," \"Remove checkpoint '",[97,1805,1154],{"class":224},[97,1807,651],{"class":250},[97,1809,1810],{"class":217},"$old.Name",[97,1812,1483],{"class":250},[97,1814,1815],{"class":250},"'\"",[97,1817,1142],{"class":217},[97,1819,1821,1824,1827,1829,1831,1833,1835,1838,1840,1842,1844,1846],{"class":213,"line":1820},119,[97,1822,1823],{"class":220},"            Write-Verbose",[97,1825,1826],{"class":250}," \"Removing expired checkpoint '",[97,1828,1154],{"class":224},[97,1830,651],{"class":250},[97,1832,1810],{"class":217},[97,1834,1483],{"class":250},[97,1836,1837],{"class":250},"' on ",[97,1839,1154],{"class":224},[97,1841,651],{"class":250},[97,1843,1603],{"class":217},[97,1845,1483],{"class":250},[97,1847,1486],{"class":250},[97,1849,1851,1854,1856],{"class":213,"line":1850},120,[97,1852,1853],{"class":217},"            $removeAction ",[97,1855,334],{"class":224},[97,1857,1858],{"class":250}," 'Removed'\n",[97,1860,1862],{"class":213,"line":1861},121,[97,1863,639],{"emptyLinePlaceholder":638},[97,1865,1867,1870],{"class":213,"line":1866},122,[97,1868,1869],{"class":224},"            try",[97,1871,923],{"class":217},[97,1873,1875,1878,1880,1883,1885],{"class":213,"line":1874},123,[97,1876,1877],{"class":220},"                Remove-VMSnapshot",[97,1879,225],{"class":224},[97,1881,1882],{"class":217},"VMSnapshot $old ",[97,1884,1013],{"class":224},[97,1886,1887],{"class":217},"ErrorAction Stop\n",[97,1889,1891,1894,1897],{"class":213,"line":1890},124,[97,1892,1893],{"class":217},"            } ",[97,1895,1896],{"class":224},"catch",[97,1898,923],{"class":217},[97,1900,1902,1905,1908,1910,1912,1914,1916,1919,1921,1923,1925,1927,1930,1932,1934,1936,1939,1941],{"class":213,"line":1901},125,[97,1903,1904],{"class":220},"                Write-Warning",[97,1906,1907],{"class":250}," \"Removing checkpoint '",[97,1909,1154],{"class":224},[97,1911,651],{"class":250},[97,1913,1810],{"class":217},[97,1915,1483],{"class":250},[97,1917,1918],{"class":250},"' from ",[97,1920,1154],{"class":224},[97,1922,651],{"class":250},[97,1924,1603],{"class":217},[97,1926,1483],{"class":250},[97,1928,1929],{"class":250}," failed: ",[97,1931,1154],{"class":224},[97,1933,651],{"class":250},[97,1935,1238],{"class":220},[97,1937,1938],{"class":217},".Exception.Message",[97,1940,1483],{"class":250},[97,1942,1486],{"class":250},[97,1944,1946,1949,1951],{"class":213,"line":1945},126,[97,1947,1948],{"class":217},"                $removeAction ",[97,1950,334],{"class":224},[97,1952,1953],{"class":250}," 'Failed'\n",[97,1955,1957],{"class":213,"line":1956},127,[97,1958,1959],{"class":217},"            }\n",[97,1961,1963],{"class":213,"line":1962},128,[97,1964,639],{"emptyLinePlaceholder":638},[97,1966,1968,1971,1974,1977,1980],{"class":213,"line":1967},129,[97,1969,1970],{"class":217},"            [",[97,1972,1973],{"class":224},"PSCustomObject",[97,1975,1976],{"class":217},"]",[97,1978,1979],{"class":224},"@",[97,1981,340],{"class":217},[97,1983,1985,1988,1990],{"class":213,"line":1984},130,[97,1986,1987],{"class":217},"                VM             ",[97,1989,334],{"class":224},[97,1991,1992],{"class":217}," $vm.Name\n",[97,1994,1996,1999,2001],{"class":213,"line":1995},131,[97,1997,1998],{"class":217},"                Host           ",[97,2000,334],{"class":224},[97,2002,2003],{"class":217}," $vm.ComputerName\n",[97,2005,2007,2010,2012],{"class":213,"line":2006},132,[97,2008,2009],{"class":217},"                Action         ",[97,2011,334],{"class":224},[97,2013,2014],{"class":217}," $removeAction\n",[97,2016,2018,2021,2023],{"class":213,"line":2017},133,[97,2019,2020],{"class":217},"                Checkpoint     ",[97,2022,334],{"class":224},[97,2024,2025],{"class":217}," $old.Name\n",[97,2027,2029,2032,2034,2036,2038,2040,2042,2044],{"class":213,"line":2028},134,[97,2030,2031],{"class":217},"                CheckpointType ",[97,2033,334],{"class":224},[97,2035,1658],{"class":250},[97,2037,1154],{"class":224},[97,2039,651],{"class":250},[97,2041,1575],{"class":217},[97,2043,1483],{"class":250},[97,2045,1486],{"class":250},[97,2047,2049],{"class":213,"line":2048},135,[97,2050,1959],{"class":217},[97,2052,2054],{"class":213,"line":2053},136,[97,2055,2056],{"class":217},"        }\n",[97,2058,2060],{"class":213,"line":2059},137,[97,2061,1182],{"class":217},[97,2063,2065],{"class":213,"line":2064},138,[97,2066,639],{"emptyLinePlaceholder":638},[97,2068,2070,2073,2075,2077,2079,2081,2083,2086,2088],{"class":213,"line":2069},139,[97,2071,2072],{"class":217},"    $existing ",[97,2074,334],{"class":224},[97,2076,1696],{"class":220},[97,2078,225],{"class":224},[97,2080,1701],{"class":217},[97,2082,1013],{"class":224},[97,2084,2085],{"class":217},"Name $checkpointName ",[97,2087,1013],{"class":224},[97,2089,2090],{"class":217},"ErrorAction SilentlyContinue\n",[97,2092,2094],{"class":213,"line":2093},140,[97,2095,639],{"emptyLinePlaceholder":638},[97,2097,2099,2101],{"class":213,"line":2098},141,[97,2100,1115],{"class":224},[97,2102,2103],{"class":217}," ($existing) {\n",[97,2105,2107,2109,2112,2115,2118,2120,2122,2124,2126],{"class":213,"line":2106},142,[97,2108,1148],{"class":220},[97,2110,2111],{"class":250}," \"Checkpoint '",[97,2113,2114],{"class":217},"$checkpointName",[97,2116,2117],{"class":250},"' already exists on ",[97,2119,1154],{"class":224},[97,2121,651],{"class":250},[97,2123,1603],{"class":217},[97,2125,1483],{"class":250},[97,2127,1608],{"class":250},[97,2129,2131],{"class":213,"line":2130},143,[97,2132,1614],{"class":224},[97,2134,2136],{"class":213,"line":2135},144,[97,2137,1182],{"class":217},[97,2139,2141],{"class":213,"line":2140},145,[97,2142,639],{"emptyLinePlaceholder":638},[97,2144,2146,2148,2150,2152,2154,2156,2158,2160,2162,2164,2166,2168,2170,2172,2174,2176,2178,2181,2183,2185],{"class":213,"line":2145},146,[97,2147,1115],{"class":224},[97,2149,1565],{"class":217},[97,2151,1771],{"class":220},[97,2153,1774],{"class":217},[97,2155,1568],{"class":250},[97,2157,1154],{"class":224},[97,2159,651],{"class":250},[97,2161,1603],{"class":217},[97,2163,1483],{"class":250},[97,2165,1787],{"class":250},[97,2167,1154],{"class":224},[97,2169,651],{"class":250},[97,2171,1794],{"class":217},[97,2173,1483],{"class":250},[97,2175,1568],{"class":250},[97,2177,262],{"class":224},[97,2179,2180],{"class":250}," \"Create checkpoint '",[97,2182,2114],{"class":217},[97,2184,1815],{"class":250},[97,2186,1142],{"class":217},[97,2188,2190,2192,2195,2197,2199,2201,2203,2205,2207],{"class":213,"line":2189},147,[97,2191,1148],{"class":220},[97,2193,2194],{"class":250}," \"Creating checkpoint '",[97,2196,2114],{"class":217},[97,2198,1837],{"class":250},[97,2200,1154],{"class":224},[97,2202,651],{"class":250},[97,2204,1603],{"class":217},[97,2206,1483],{"class":250},[97,2208,1486],{"class":250},[97,2210,2212,2215,2217],{"class":213,"line":2211},148,[97,2213,2214],{"class":217},"        $action ",[97,2216,334],{"class":224},[97,2218,2219],{"class":250}," 'Created'\n",[97,2221,2223],{"class":213,"line":2222},149,[97,2224,639],{"emptyLinePlaceholder":638},[97,2226,2228,2231],{"class":213,"line":2227},150,[97,2229,2230],{"class":224},"        try",[97,2232,923],{"class":217},[97,2234,2236,2239,2241,2243,2245,2248,2250],{"class":213,"line":2235},151,[97,2237,2238],{"class":220},"            Checkpoint-VM",[97,2240,225],{"class":224},[97,2242,1701],{"class":217},[97,2244,1013],{"class":224},[97,2246,2247],{"class":217},"SnapshotName $checkpointName ",[97,2249,1013],{"class":224},[97,2251,1887],{"class":217},[97,2253,2255,2258,2260],{"class":213,"line":2254},152,[97,2256,2257],{"class":217},"        } ",[97,2259,1896],{"class":224},[97,2261,923],{"class":217},[97,2263,2265,2268,2271,2273,2275,2277,2279,2281,2283,2285,2287,2289,2291],{"class":213,"line":2264},153,[97,2266,2267],{"class":220},"            Write-Warning",[97,2269,2270],{"class":250}," \"Checkpoint of ",[97,2272,1154],{"class":224},[97,2274,651],{"class":250},[97,2276,1603],{"class":217},[97,2278,1483],{"class":250},[97,2280,1929],{"class":250},[97,2282,1154],{"class":224},[97,2284,651],{"class":250},[97,2286,1238],{"class":220},[97,2288,1938],{"class":217},[97,2290,1483],{"class":250},[97,2292,1486],{"class":250},[97,2294,2296,2299,2301],{"class":213,"line":2295},154,[97,2297,2298],{"class":217},"            $action ",[97,2300,334],{"class":224},[97,2302,1953],{"class":250},[97,2304,2306],{"class":213,"line":2305},155,[97,2307,2056],{"class":217},[97,2309,2311],{"class":213,"line":2310},156,[97,2312,639],{"emptyLinePlaceholder":638},[97,2314,2316,2318,2320,2322,2324],{"class":213,"line":2315},157,[97,2317,937],{"class":217},[97,2319,1973],{"class":224},[97,2321,1976],{"class":217},[97,2323,1979],{"class":224},[97,2325,340],{"class":217},[97,2327,2329,2332,2334],{"class":213,"line":2328},158,[97,2330,2331],{"class":217},"            VM             ",[97,2333,334],{"class":224},[97,2335,1992],{"class":217},[97,2337,2339,2342,2344],{"class":213,"line":2338},159,[97,2340,2341],{"class":217},"            Host           ",[97,2343,334],{"class":224},[97,2345,2003],{"class":217},[97,2347,2349,2352,2354],{"class":213,"line":2348},160,[97,2350,2351],{"class":217},"            Action         ",[97,2353,334],{"class":224},[97,2355,2356],{"class":217}," $action\n",[97,2358,2360,2363,2365],{"class":213,"line":2359},161,[97,2361,2362],{"class":217},"            Checkpoint     ",[97,2364,334],{"class":224},[97,2366,2367],{"class":217}," $checkpointName\n",[97,2369,2371,2374,2376,2378,2380,2382,2384,2386],{"class":213,"line":2370},162,[97,2372,2373],{"class":217},"            CheckpointType ",[97,2375,334],{"class":224},[97,2377,1658],{"class":250},[97,2379,1154],{"class":224},[97,2381,651],{"class":250},[97,2383,1575],{"class":217},[97,2385,1483],{"class":250},[97,2387,1486],{"class":250},[97,2389,2391],{"class":213,"line":2390},163,[97,2392,2056],{"class":217},[97,2394,2396],{"class":213,"line":2395},164,[97,2397,1182],{"class":217},[97,2399,2401],{"class":213,"line":2400},165,[97,2402,422],{"class":217},[20,2404,2406],{"id":2405},"notes","Notes",[25,2408,2409,2412,2427,2443,2453,2464],{},[28,2410,2411],{},"Checkpoints are not backups. Microsoft's own FAQ answers \"Should checkpoints be used as a substitute for backups?\" with a flat no: a checkpoint is not the same as a VSS writer backup and is not recommended as a permanent data or system recovery solution. It lives on the same storage as the VM, so it protects you against a bad patch for the day or two it takes to confirm the update went well, and does nothing for storage failure or ransomware. Keep your real backup schedule regardless.",[28,2413,2414,2415,2418,2419,2422,2423,2426],{},"The checkpoint type comes from the VM, not the script. Production (the default for new VMs) uses VSS in Windows guests or file system freeze in Linux guests and falls back to a standard checkpoint if that fails; ProductionOnly fails instead of falling back, which is why ",[15,2416,2417],{},"sql-svr01"," shows ",[15,2420,2421],{},"Failed"," in the sample above. Change it with ",[15,2424,2425],{},"Set-VM -Name \u003Cvmname> -CheckpointType ProductionOnly"," if you would rather have a failure than a memory-state checkpoint. Microsoft warns that standard checkpoints can cause consistency problems for anything that replicates between nodes, Active Directory being the example it gives.",[28,2428,2429,2430,2432,2433,2436,2437,2439,2440,2442],{},"Keep the retention short. Microsoft notes that the presence of a checkpoint reduces the VM's disk performance, and a differencing disk on a write-heavy SQL Server or Exchange VM grows for as long as it exists. I run ",[15,2431,144],{}," at 1 or 2 on those hosts so ",[15,2434,2435],{},"Remove-VMSnapshot"," merges the ",[15,2438,54],{}," back before the next cycle. A merge needs free space; if it fails with 0x80070070, free space or export the VM to a larger volume. Never delete ",[15,2441,54],{}," files by hand.",[28,2444,2445,2446,2449,2450,42],{},"Rolling back a production checkpoint leaves the VM off (there is no memory state to resume), so plan for a guest boot: ",[15,2447,2448],{},"Restore-VMSnapshot -VMName \u003Cvmname> -Name \u003Ccheckpoint> -Confirm:$false",", then ",[15,2451,2452],{},"Start-VM -Name \u003Cvmname>",[28,2454,2455,2456,2459,2460,2463],{},"Off VMs are skipped by default because nothing changes inside them until they start, so there is nothing for a patch to break. Name them in ",[15,2457,2458],{},"-VMName"," if you want a checkpoint anyway; ",[15,2461,2462],{},"Checkpoint-VM"," works on an off VM.",[28,2465,2466,2467,2470,2471,2473,2474,2476,2477,2480,2481,191,2483,2485,2486,2489],{},"As a CAU pre-update script, a script that fails stops that node from being updated. That is why the checkpoint and cleanup calls are wrapped in ",[15,2468,2469],{},"try","\u002F",[15,2472,1896],{},": one VM whose VSS writer misbehaves, or whose old checkpoint won't merge, produces a warning and a ",[15,2475,2421],{}," row instead of blocking the whole Updating Run. ",[15,2478,2479],{},"Get-VMSnapshot",", ",[15,2482,2462],{},[15,2484,2435],{}," are the real cmdlet names; ",[15,2487,2488],{},"Get-VMCheckpoint"," and friends are aliases the Hyper-V module adds, so they are avoided here.",[20,2491,2493],{"id":2492},"source","Source",[25,2495,2496,2506,2514,2529,2537,2545],{},[28,2497,2498,2505],{},[2499,2500,2504],"a",{"href":2501,"rel":2502},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fwindows-server\u002Fvirtualization\u002Fhyper-v\u002Fcheckpoints",[2503],"nofollow","Using checkpoints"," (standard versus production, checkpoint types, merging)",[28,2507,2508,2513],{},[2499,2509,2512],{"href":2510,"rel":2511},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fprevious-versions\u002Fwindows\u002Fit-pro\u002Fwindows-server-2012-r2-and-2012\u002Fdn818483(v=ws.11)",[2503],"Checkpoints and Snapshots Overview"," (the \"not a substitute for backups\" FAQ, performance and merge space)",[28,2515,2516,2480,2520,191,2524,2528],{},[2499,2517,2462],{"href":2518,"rel":2519},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fpowershell\u002Fmodule\u002Fhyper-v\u002Fcheckpoint-vm",[2503],[2499,2521,2479],{"href":2522,"rel":2523},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fpowershell\u002Fmodule\u002Fhyper-v\u002Fget-vmsnapshot",[2503],[2499,2525,2435],{"href":2526,"rel":2527},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fpowershell\u002Fmodule\u002Fhyper-v\u002Fremove-vmsnapshot",[2503]," cmdlet references",[28,2530,2531,2536],{},[2499,2532,2535],{"href":2533,"rel":2534},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fwindows-server\u002Fvirtualization\u002Fhyper-v\u002Fdeploy\u002Fupgrade-virtual-machine-version-in-hyper-v-on-windows-or-windows-server",[2503],"Upgrade virtual machine version in Hyper-V"," (production checkpoints need configuration version 6.2)",[28,2538,2539,2544],{},[2499,2540,2543],{"href":2541,"rel":2542},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fwindows\u002Fdeployment\u002Fupdate\u002Frelease-cycle",[2503],"Update release cycle for Windows clients"," (monthly security release timing)",[28,2546,2547,191,2551],{},[2499,2548,428],{"href":2549,"rel":2550},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fpowershell\u002Fmodule\u002Fclusterawareupdating\u002Finvoke-caurun",[2503],[2499,2552,2555],{"href":2553,"rel":2554},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fwindows-server\u002Ffailover-clustering\u002Fcluster-aware-updating",[2503],"Cluster-Aware Updating overview",[2557,2558,2559],"style",{},"html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}",{"title":208,"searchDepth":343,"depth":343,"links":2561},[2562,2563,2564,2565,2566,2567],{"id":22,"depth":343,"text":23},{"id":58,"depth":343,"text":59},{"id":197,"depth":343,"text":198},{"id":434,"depth":343,"text":435},{"id":2405,"depth":343,"text":2406},{"id":2492,"depth":343,"text":2493},"techcolumnist",[2570,2571],"ps","scripts","2025-10-15T14:00:00Z","A script that takes dated production checkpoints of running Hyper-V VMs on hosts or a whole cluster before patching, prunes its own old ones and plugs into CAU.","md",false,null,{},"\u002Fblog\u002F2025\u002F10\u002F15\u002Fpowershell-hyper-v-automate-vm-checkpoints-before-patch-tuesday",{"title":6,"description":2573},[2568],"blog\u002F2025\u002F10\u002F15\u002Fpowershell-hyper-v-automate-vm-checkpoints-before-patch-tuesday",[207,2583,2584],"hyper-v","cluster","\u002F2025\u002F10\u002F15\u002Fpowershell-hyper-v-automate-vm-checkpoints-before-patch-tuesday\u002F","0Vu0dDh82kXCh6Ab_GY3K3IbvX6176-yWBBQrjUi1KQ",{"title":2588,"description":2589,"date":2590,"url":2591,"categories":2592,"tags":2593,"image":2576,"readingTime":354,"canonical":2568,"sites":2595,"series":2576,"seriesOrder":2576},"PowerShell: Intune – Force Compliance Re-Evaluation Fleet-Wide","A Microsoft Graph PowerShell script that sends the syncDevice action to every matching Intune-managed device, throttled, so compliance is re-evaluated at once.","2025-10-22T14:00:00Z","\u002F2025\u002F10\u002F22\u002Fpowershell-intune-force-a-compliance-policy-re-evaluation-fleet-wide\u002F",[2570,2571],[207,2594],"intune",[2568],{"title":2597,"description":2598,"date":2599,"url":2600,"categories":2601,"tags":2602,"image":2576,"readingTime":376,"canonical":2568,"sites":2606,"series":2576,"seriesOrder":2576},"PowerShell: Windows – Discover Local Admins Across Every Workstation","A script that reads the local Administrators group on every workstation by SID, survives orphaned-SID errors, and flags members outside an approved allowlist.","2025-10-08T14:00:00Z","\u002F2025\u002F10\u002F08\u002Fpowershell-windows-discover-local-admins-across-every-workstation\u002F",[2570,2571],[207,2603,2604,2605],"windows","discovery","active-directory",[2568],[2608,2616,2625],{"title":2609,"description":2610,"date":2611,"url":2612,"categories":2613,"tags":2614,"image":2576,"readingTime":376,"canonical":2568,"sites":2615,"series":2576,"seriesOrder":2576},"PowerShell: Hyper-V – Script a Failover Cluster Deployment End to End","A re-runnable script that installs Hyper-V and clustering, validates the nodes, builds the cluster, sets a quorum witness, adds CSV or S2D storage and pins Live Migration.","2025-07-09T14:00:00Z","\u002F2025\u002F07\u002F09\u002Fpowershell-hyper-v-script-a-failover-cluster-deployment-end-to-end\u002F",[2570,2571],[207,2583,2584],[2568],{"title":2617,"description":2618,"date":2619,"url":2620,"categories":2621,"tags":2622,"image":2576,"readingTime":376,"canonical":2568,"sites":2624,"series":2576,"seriesOrder":2576},"PowerShell: Active Directory – Report Group Membership Sprawl","Rank AD security groups by nesting depth, transitive member count, ownership and staleness for an access review, plus a per-user Kerberos token size estimate.","2025-12-03T14:00:00Z","\u002F2025\u002F12\u002F03\u002Fpowershell-active-directory-report-group-membership-sprawl\u002F",[2570,2571],[207,2605,2623],"reporting",[2568],{"title":2626,"description":2627,"date":2628,"url":2629,"categories":2630,"tags":2631,"image":2576,"readingTime":365,"canonical":2568,"sites":2632,"series":2576,"seriesOrder":2576},"PowerShell: Windows Server – Disable SMBv1 Fleet-Wide and Verify","A script that audits SMBv1 access (event 3000), disables the SMBv1 server and optional feature across Windows servers, and reports which ones still need a restart.","2025-11-26T14:00:00Z","\u002F2025\u002F11\u002F26\u002Fpowershell-windows-server-disable-smbv1-fleet-wide-and-verify-it-stuck\u002F",[2570,2571],[207,2603],[2568],{"doc":2576,"posts":2634},[],1790052513205]