Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing Volume Shadow Copy (VSS) Snapshots from powershell

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?

like image 759
jordanm Avatar asked Jan 08 '13 03:01

jordanm


People also ask

How do I view VSS snapshots?

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.

How do I find shadow copy settings?

Click Start, right-click My Computer, and then click Manage. Right-click Shared Folders, point to All Tasks, and then click Configure Shadow Copies.


2 Answers

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.

like image 112
Ansgar Wiechers Avatar answered Sep 23 '22 00:09

Ansgar Wiechers


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.
like image 34
JJ Fullmer Avatar answered Sep 25 '22 00:09

JJ Fullmer