Accessing a shadow copy from another process

Aug 7, 2014 at 4:28 AM
Edited Aug 7, 2014 at 2:41 PM
I'm having trouble reading a shadow copy volume from a process other than the one that created it. Everything seems to work if I create a symlink to the volume and read it from there, but I'd prefer to read the shadow copy volume directly so I don't have to clean up symlinks and mount points, and so "mysterious" volumes don't show up on our users' computers while a backup is running.

Here's what I'm doing. I've developed a backup tool for UNIX-style systems, and I recently ported the tool to Windows. In order to support shadow copies, the backup tool invokes a small C# program I wrote based on AlphaVSS. The C# program can correctly create and destroy snapshots, and if I make a symlink to the shadow copy volume I can read its contents. Here's the output from vssadmin for one of my snapshot sets:
Contents of shadow copy set ID: {33ab622d-8ccc-4872-a8a7-1009ee3c8160}
   Contained 1 shadow copies at creation time: 8/6/2014 11:16:04 PM
      Shadow Copy ID: {e35d15b9-0642-4fd1-af57-01b671ecd0d0}
         Original Volume: (C:)\\?\Volume{1e83ad11-fe89-11e3-9ebf-806e6f6e6963}\
         Shadow Copy Volume: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy63
         Originating Machine: sarwdows
         Service Machine: sarwdows
         Provider: 'Microsoft Software Shadow Copy provider 1.0'
         Type: Backup
         Attributes: Differential, Auto recovered
The following symlink commands work from a terminal:
mklink /d c:\vsstest \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy63\
dir \vsstest
<the contents of C: appear>
However, if I try to call GetFileAttributesEx() on the shadow copy volume from within my backup program, I get an error:
GetFileAttributesEx \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy61: The parameter is incorrect.
My questions are:
  1. Should I be able to access this path from the parent process of the process that created the snapshot?
  2. Does GetFileAttributesEx() simply not work for shadow copy volumes? If not, is there any way I can easily tell which methods should work?
Thanks!


UPDATE: I think the "other process" part is not my problem. I tried calling File.Exists() on various paths built from the SnapshotDeviceObject path, and they all return false. It looks to me like I'm not creating the shadow copy correctly after all, even though a symlink to it works.

Here are the steps I'm taking:
IVssImplementation vssImp = VssUtils.LoadImplementation();
using (IVssBackupComponents vss = vssImp.CreateVssBackupComponents())
{
    String newRoot;

    // Create the snapshot set
    vss.InitializeForBackup(null);
    vss.SetContext(VssSnapshotContext.Backup);
    vss.SetBackupState(false, true, VssBackupType.Full, false);
    vss.GatherWriterMetadata();
    Guid set_id = vss.StartSnapshotSet();
    bool created = false, success = false;
    try
    {
        string volume = Path.GetPathRoot("C:\\");
        Guid snap_id;
        if (vss.IsVolumeSupported(volume))
        {
            snap_id = vss.AddToSnapshotSet(volume);
        }
        else
        {
            throw new VssVolumeNotSupportedException(volume);
        }

        // Create the snapshot
        vss.PrepareForBackup();
        vss.GatherWriterStatus();
        vss.DoSnapshotSet();
        created = true;
        vss.GatherWriterStatus();

        // Get the path to the snapshot
        VssSnapshotProperties props = vss.GetSnapshotProperties(snap_id);
        newRoot = props.SnapshotDeviceObject;
        success = true;
    }
    finally
    {
        if (success)
        {
            vss.BackupComplete();
        }
        else
        {
            if (created)
            {
                vss.GatherWriterStatus();
                vss.DeleteSnapshotSet(set_id, true);
            }
            vss.AbortBackup();
        }
    }

    bool exists = File.Exists(newRoot); // Returns false
    exists = File.Exists(newRoot + "\\"); // Returns false
    exists = File.Exists(newRoot + "\\Windows"); // Returns false
}