Friday, March 23, 2012

Work with a "shadow copy" of your file system

Sometimes it is useful to be able to take a snapshot of the file system as it currently stands while still having programs use / access it. The reason I wrote this PowerShell script is that I want to be able to copy virtual machines around while still accessing them. Unfortunately, copying virtual machines takes a long time due to their size, so it is useful to be able to copy them while they are in use. This script allows me to shut down the virtual machine, start the copy operation, and then restart the virtual machine while the copy is still in progress.

Notes / caveats:

  • This script requires administrative privileges.
  • The script is naive and does not work if the folder you want to work with is inside a mount point or directory junction (this situation is usually rare).
  • The script leaves a symbolic link in the temp folder, so these may accumulate over time.

function CreateShadowCopy([string]$LocationToOpen) {
    if(-not $LocationToOpen -or -not (test-path $LocationToOpen)) {
        $LocationToOpen = get-location
    }
    if(-not (get-item $LocationToOpen).PSIsContainer) {
        $LocationToOpen = split-path -Parent $LocationToOpen
    }
 
    $fullPath = (resolve-path $LocationToOpen).Path
    $fileRoot = [system.io.path]::GetPathRoot($fullPath)
    $shadow = (Get-WmiObject -list win32_shadowcopy).Create($fileRoot, "ClientAccessible") 
    $shadowRoot = join-path $env:temp $shadow.ShadowID
    $shadowPath = gwmi win32_shadowcopy | ? { $_.Id -eq $shadow.ShadowID } | select -ExpandProperty DeviceObject
    cmd /c mklink /d $shadowRoot $shadowPath\ | out-null
    $rootlessCurrentPath = $fullPath.substring($fileRoot.length)
    join-path $shadowRoot $rootlessCurrentPath
}

$shadowPath = CreateShadowCopy D:\
try {
    pushd $shadowPath

    ls .
    echo "Do stuff..."
}
finally {
    popd
    cmd /c rd $shadowPath
}

0 comments:

Post a Comment