Thursday, September 6, 2007

Windows Shadow Copy (VSS) Woes

Motive:

For a while, I've been meaning to work on a better backup solution to work under Windows. I've not yet seen a tool that is reliable, extensible, and able to copy in-use files. NTBackup, which comes with Windows, has the advantage of using Microsoft's Shadow Copy, which allows for backing up from a "snapshot in time", and also allows for copies of in-use files, but otherwise falls short of the goal.

Be warned - if you're reading this post this looking for a solution, there really is none. At current, this post only outlines some of the problems. If you have a suggestion, please leave a note!

Looking for Shadow Copy:

One of the first interesting pages I found was Adi Oltean's "The VSS (Volume Shadow Copy) SDK is available for download". It contains a "sample application" called VSHADOW. Though I don't like relying on a non-supported "sample", it looked somewhat promising. Sure enough, running "vshadow -wait d:" results in a shadow copy accessible by a special Windows device name while the command remains active, e.g. "\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1". (It waits with a "Press <ENTER> to continue..." prompt.) There are features to access such a shadow copy by a drive letter or a mount point, but unfortunately, only under Windows Server 2003 (and presumably, Windows Vista). The vshadow readme.doc included with the SDK states that these special device names have "a special volume device syntax that is not compatible with certain shell commands ... Still, many Win32 applications or shell commands can operate on this device..." Using the copy command does work to copy files from the shadow copy, but even something as simple as getting a directory listing seems to require a bit of scripting.

In a moment of possible insanity, I thought it would be cool if I could access the shadow copy using the File class in Java. Since Java does rely on the underlying operating system APIs for OS-specific operations such as working with files, I wouldn't have been surprised if it had worked. Unfortunately, any attempts fail as if the files don't exist.

No help from Microsoft.Net:

Well, with no honest expectation for Java to interface with such advanced Windows features, I thought I'd try Microsoft's approach, Visual Studio 2005. Attempt:

DirectoryInfo di = new DirectoryInfo(
  @"\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1");

The result? A very discouraging exception:

System.ArgumentException was unhandled
  Message="Paths that begin with \\\\?\\GlobalRoot are internal
    to the kernel and should not be opened by managed applications."
  Source="mscorlib"
  StackTrace:
       at System.IO.Path.NormalizePathFast(String path, Boolean fullCheck)
       at System.IO.Path.GetFullPathInternal(String path)
       at System.IO.DirectoryInfo..ctor(String path)
       …

All I can say is, for as hard as Microsoft is pushing the .Net framework, such artificial limitations are very disappointing.

Someone else with the same goal:

One promising article I found was Craig Andera's "HoboCopy". I can't agree more with his two reasons for being unhappy with using ntbackup as a backup strategy, including its proprietary format. I also strongly agree with his following paragraphs which explain some of the advantages and strengths of the Volume Shadow Service (VSS) / shadow copy.

Unfortunately, it appears that Craig, too, discovered that working with VSS from managed code / .Net is severely broken / impossible. He continued with the challenge to write a tool using unmanaged C++. Unfortunately, not even HoboCopy meets my design requirement for a tool to interface with VSS.

Other approaches / notes:

Another promising approach I found was another blog entry by Adi Oltean, "A bit of black magic: How to assign drive letters to VSS shadow copies... on Windows XP !" Unfortunately, it relies upon an unsupported and nearly-impossible-to-find tool from various Microsoft resource kits, DOSDEV.EXE. (I did manage to find it in Microsoft Product Support's Reporting Tools. It is in the MPSRPT_SETUPPerf.EXE download.)

One last blog entry I found which was worth noting is Alex Thissen's "Volume Shadow Copy: your way to copying locked file".

Wish for the future:

My wish list doesn't seem that long for a tool or easy-to-use API:

  • Ability to copy files from a shadow copy, either through use of a file OR by stdout / application streaming.
  • Ability to retrieve directory listings and other basic file information such as size and last modified dates.
  • Ability to be used from managed code, e.g. C#.Net.

6 comments:

Saravanan said...

Hi,

If you are still looking for finding the list of files in a snapshot directory, the JDK 1.5 file API does work.

D:\>java finddir "\\\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\SnapDir"

File Exists true

AUTOEXEC.BAT
boot.ini
CONFIG.SYS
console.txt
Install.exe
InstMsi.exe
InstMsiW.exe
IO.SYS
MSDOS.SYS
msizap.exe
netfxsd1.cab
netfxsdk.msi
NTDETECT.COM
ntldr
TMPatch.log

Woong bin Kang said...

Hey,
I just wanted to tell you that you don't need dosdev to expose it as a device. Just use vshadow.exe in MS VSS SDK with -el switch. It is also possible to use -er switch to expose the shadow copy as a network share.

Thanks for your post!

Mark A. Ziesemer said...

Thank you both, Saravanan and Woong bin Kang, for your comments. When I have some time, I'll look further into both approaches!

Saravanan, I'm wondering if I just needed the 2 additional backslashes at the beginning (for a total of 8 for the Java escaping)? I'm not sure where I saw the original example I listed, but there it was only 2 backslashes (for a total of 4 before the escaping).

Justin said...

Any updates to this post?

Jon and Judy Glick said...

You may want to check out http://alphavss.codeplex.com/. It looks very promising! I've been playing around with it a bit, and have successfully created a volume shadow copy. Now just trying to find a better way than dosdev.exe to map a drive letter to it.

Jon and Judy Glick said...

I think I just found my answer, from the same author! :) http://alphafs.codeplex.com/