Powershell 7.0 VSS

I saw there’s already discussion on implementing VSS but hasn’t been built as of yet.

I wanted to write something for myself that creates/destroys shadow copies before/after restic runs.

I came across this comment on the issue which lead me in the right direction but then I discovered that these Get-WmiObject commands don’t work in Powershell 7.

If you try, you get:

Get-WmiObject: The term ‘Get-WmiObject’ is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

So, I tried using CimInstance instead which worked after lots of hair pulling and internet searches.

Here’s what I came up with. I don’t claim to be the best scripter ever but it might help someone who wants to do VSS with Powershell 7 with no extra software installs:

# Absolute path for directories to backup. This version is only enabling VSS for the C:\
# Paths need to include \shadowcopy\. That is where the VSS for the drive is linked for the duration of the backup
$backupLocations = @(
    "C:\shadowcopy\Users\Doni",
    "C:\shadowcopy\Program Files (x86)\Steam"   
)

# Restic options
$repo = "rclone:gcd_clear://restic"
$pFile = "C:\users\Doni\Documents\restic.txt"
$computername = $env:COMPUTERNAME.tolower()


# Check for currently running restic instance
$isRunning = Get-Process -Name "restic" -ErrorAction SilentlyContinue

if ($isRunning.ProcessName -eq "rclone") {
    Write-Host "restic instance currently running. Exiting..."
    Exit
}

# This section ends by removing ALL shadow copies indiscriminately
else {

    foreach ($location in $backupLocations)
        {
            if ($null = Get-CimInstance -ClassName Win32_ShadowCopy) {
            
            }

            # Determine drive letter from path given in $backupLocations array
            $driveLetter = ($location.ToCharArray() | Select-Object -First 3) -join ''

            # Build shadowcopy and link
            $deviceID = Get-CimInstance -ClassName win32_volume | Where-Object {$_.Name -eq "$driveLetter"} | Select-Object -ExpandProperty DeviceID
            Invoke-CimMethod -ClassName Win32_ShadowCopy -Arguments @{ Volume = $deviceID; Context = "ClientAccessible"} -MethodName Create

            $shadowObject = Get-CimInstance -ClassName Win32_ShadowCopy | Select-Object -ExpandProperty DeviceObject
            $shadowPath = $shadowObject + "\"
            
            cmd /c mklink /d C:\shadowcopy "$shadowPath"

            restic -r $repo -p $pFile backup $location --host $computername

            Get-CimInstance -ClassName Win32_ShadowCopy | Remove-CimInstance

            Remove-Item C:\shadowcopy -Confirm:$false -Force
        }
}
1 Like

Nice!

Here’s what I do: Windows VSS support

Yours seems more elegant. I’m going to have to look into this. Thanks!

1 Like

Please see HELP WANTED: Testing Windows VSS support .