I am attempting to create and access a Volume Shadow Copy snapshot using the Windows Power Shell in Windows 7. I found that I can create snapshots using the following via a previous superuser question:
(Get-WmiObject -list win32_shadowcopy).create("C:\","ClientAccessible")
I am unable to find any documentation indicating that it is possible to set a shadow copy to "Exposed" so that it can be mapped to a drive letter using WMI
. An article linked in the same question shows a hack using a junction to access the snapshot.
When I try to access the symlink, I get the following:
PS C:\Windows\system32> ls C:\shadowcopy
Get-ChildItem : The parameter is incorrect.
At line:1 char:3
+ ls <<<< C:\shadowcopy
+ CategoryInfo : ReadError: (C:\shadowcopy:String) [Get-ChildItem], IOException
+ FullyQualifiedErrorId : DirIOError,Microsoft.PowerShell.Commands.GetChildItemCommand
Attempting to access the snapshot directly gives the following:
PS C:\Windows\system32> ls '\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy14'
Get-ChildItem : Paths that begin with \\?\GlobalRoot are internal to the kernel and should not be opened by managed applications.
At line:1 char:3
+ ls <<<< '\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy14'
+ CategoryInfo : NotSpecified: (:) [Get-ChildItem], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.GetChildItemCommand
How can I access a VSS snapshot from a powershell script?
vssadmin create shadow /for=c: Now go into the Windows File Explorer and right click the C: drive (or the drive you are working with). You should see an option called "Restore previous versions". Once you click on that you should see the available Shadow Copies (snapshots), click on the one you want to view.
Click Start, right-click My Computer, and then click Manage. Right-click Shared Folders, point to All Tasks, and then click Configure Shadow Copies.
How did you create the symlink? As outlined in that article, you have to specify the device path with a trailing backslash:
$s1 = (Get-WmiObject -List Win32_ShadowCopy).Create("C:\\", "ClientAccessible")
$s2 = Get-WmiObject Win32_ShadowCopy | Where-Object { $_.ID -eq $s1.ShadowID }
$d = $s2.DeviceObject + "\\"
Then $d
is your volume letter specifier:
cmd /c mklink /d C:\shadowcopy "$d"
After this, I was able to access the shadow copy mounted to C:\shadowcopy
just fine.
To unmount the shadow copy call $s2.Delete()
, as @KeyszerS pointed out in the comments.
So with the information provided here and the official microsoft documentation here https://docs.microsoft.com/en-us/previous-versions/windows/desktop/vsswmi/create-method-in-class-win32-shadowcopy I created a couple powershell functions/cmdlets that solve this problem. Random note, as of powershell 5 new-item has the itemType of symbolicLink but when I tried to make one with the target being the shadow snapshot it fails saying the path doesn't exist, so the mklink tool is still the way to go.
function New-ShadowLink {
[CmdletBinding()]
param (
$linkPath="$($ENV:SystemDrive)\ShadowCopy"
)
begin {
Write-Verbose "Creating a snapshot of $($ENV:SystemDrive)\"
$class=[WMICLASS]"root\cimv2:win32_shadowcopy";
$result = $class.create("$ENV:SystemDrive\", "ClientAccessible");
Write-Verbose "Getting the full target path for a symlink to the shadow snapshot"
$shadow = Get-CimInstance -ClassName Win32_ShadowCopy | Where-Object ID -eq $result.ShadowID
$target = "$($shadow.DeviceObject)\";
}
process {
Write-Verbose "Creating SymLink to shadowcopy at $linkPath"
Invoke-Expression -Command "cmd /c mklink /d '$linkPath' '$target'";
}
end {
Write-Verbose "Created link to shadowcopy snapshot of $($ENV:SystemDrive)\ at $linkPath";
Write-Verbose "Returning shadowcopy snapshot object"
return $shadow;
}
}
function Remove-ShadowLink {
[CmdletBinding()]
param (
$shadow,
$linkPath="$($ENV:SystemDrive)\ShadowCopy"
)
begin {
Write-verbose "Removing shadow copy link at $linkPath"
}
process {
Write-Verbose "Deleting the shadowcopy snapshot"
$shadow.Delete();
Write-Verbose "Deleting the now empty folder"
Try {
Remove-Item -Force -Recurse $linkPath -ErrorAction Stop;
}
catch {
Invoke-Expression -Command "cmd /c rmdir /S /Q '$linkPath'";
}
}
end {
Write-Verbose "Shadow link and snapshot have been removed";
return;
}
}
These could be utilized by copy pasting both functions then running them like this
$shadow = New-ShadowLink -Verbose;
ls C:\ShadowCopy # would show snapshot version of c drive
Remove-ShadowLink -shadow $shadow -Verbose;
ls C:\ShadowCopy # will give error as it doesn't exist
$s = New-ShadowLink -verbose
VERBOSE: Creating a snapshot of C:\
VERBOSE: Getting the full target path for a symlink to the shadow snapshot
VERBOSE: Creating SymLink to shadowcopy at C:\ShadowCopy
VERBOSE: Created link to shadowcopy snapshot of C:\ at C:\ShadowCopy
VERBOSE: Returning shadowcopy snapshot object
PS C:\> ls C:\ShadowCopy
Directory: C:\ShadowCopy
#ommitted my C drive listing, but it would be here
PS C:\> Remove-ShadowLink -shadow $s -Verbose
VERBOSE: Removing shadow copy link at C:\ShadowCopy
VERBOSE: Deleting the shadowcopy snapshot
VERBOSE: Deleting the now empty folder
VERBOSE: Shadow link and snapshot have been removed
PS C:\> ls C:\ShadowCopy
ls : Cannot find path 'C:\ShadowCopy' because it does not exist.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With