PowerShell: Create and Delete VSS Snapshots

Update 7/30/20: use this newer version

# There are 2 functions in this snippet
# 1. Create a VSS Snapshot Shadow on a specific volume
# 2. Delete a VSS Snapshot using Snapshot ID
# Limitations:
# 1. Microsoft VSS must be available on the target system.
# 2. Environmental checks are assumed to have been performed to ensure that there is adequate disk space for storing snapshots.

function createVssSnapshot{
# Sanitation
if (!($targetVolume -like "*\")){$targetVolume+="\"}
if(Test-Path $vssAccessLink){(Get-Item $vssAccessLink).Delete()}

write-host "Initiating VSS snapshot..."
$thisSnapshot = $shadowCopyClass.Create($targetVolume, "ClientAccessible")
$thisShadow = Get-WmiObject Win32_ShadowCopy | Where-Object { $_.ID -eq $thisSnapshot.ShadowID }
$thisShadowPath = $thisShadow.DeviceObject + "\"

# Creating symlink
$null=cd C:
$null=cmd /c mklink /d $vssAccessLink $thisShadowPath
write-host "Vss Snapshot of $targetVolume has been made and it's accessible at this local file system (LFS): $vssAccessLink."

# Validation
if(Test-Path $vssAccessLink){
write-host "Snapshot $snapshotId has been created.";
return $snapshotId;
write-host "Failed to create client accessible VSS Snapshot.";
return $false;

createVssSnapshot $targetVolume $vssAccessLink
function deleteVssSnapshot{

# Deterministic method of obtaining newest snapshot ID if it is not specified
$lastSnapshotIdString=vssadmin list shadows /for=$targetVolume|`
%{if($_ -like "*Shadow Copy ID:*"){$_}}|`
select-object -last 1|`
%{[void]($_ -match "{(.*)}$"); $matches[1]}

# Remove a single snapshot
write-host "Removing snapshot Id $snapShotId..."
#$removeSnapshotCommand="cmd.exe /c vssadmin delete shadows /Shadow=$snapShotId /quiet"
#$voidOutput=cmd.exe /c vssadmin delete shadows /Shadow=$lastSnapshotId /quiet
invoke-expression 'cmd /c start powershell -Command {
$command="cmd.exe /c vssadmin delete shadows /Shadow=$snapShotId /quiet";
write-host $command;
invoke-expression $command;
pause; } -Args $snapShotId'
# This is the workaround to the annoyance of antivirus software terminating sessions upon invoking the snapshot removal procedure
Invoke-Command -Session $newSession -ScriptBlock{param($snapShotId);vssadmin delete shadows /Shadow=$snapShotId /quiet} -args $snapShotId

# Remove symlink
write-host "Removing symlink $vssAccessLink..."
(Get-Item $vssAccessLink).Delete()

# Remove all Snapshots
#Get-WmiObject Win32_ShadowCopy | % {$_.delete()}
#vssadmin delete shadows /For=$targetVolume /Quiet

# Validation
#vssadmin list shadows /for=$targetVolume
$validateLastSnapshot=vssadmin list shadows /for=$targetVolume|`
%{if($_ -like "*Shadow Copy ID:*"){$_}}|`
select-object -last 1|`
%{[void]($_ -match "{(.*)}$"); $matches[1]}
if(!($validateLastSnapshotId -eq $snapShotId)){
write-host "Last snapshot Id is now $validateLastSnapshotId"
return $true
write-host "$snapShotId still exists. There was an error in its removal";
return $false
$lastSnapshotId=createVssSnapshot $targetVolume $vssAccessLink
deleteVssSnapshot $targetVolume $lastSnapshotId $vssAccessLink

Leave a Reply

Your email address will not be published. Required fields are marked *