/// <summary>
        /// Makes a recursive snapshot of the directory as it is.
        /// </summary>
        /// <param name="baseDirectory">The directory to start in.</param>
        /// <returns>A file system snapshot</returns>
        public static SnapshotFilesystem MakeFsSnapshot(System.IO.DirectoryInfo baseDirectory)
        {
            DirectoryInfo baseDir = new DirectoryInfo(baseDirectory.FullName);

            if (!baseDir.Exists)
            {
                throw new ArgumentException("Base directory doesn't exist");
            }

            SnapshotFilesystem res = new SnapshotFilesystem();

            if (!baseDir.FullName.EndsWith(Path.DirectorySeparatorChar) && !baseDir.FullName.EndsWith(Path.AltDirectorySeparatorChar))
            {
                // Add ending slash to get a uniform output
                baseDir = new DirectoryInfo(baseDir.FullName + Path.DirectorySeparatorChar);
            }

            res.BasePath = baseDir.FullName;
            res.Items    = new LinkedList <SnapshotFilesystemItem>();

            // Make VSS
            // Sequence of calls: http://us.generation-nt.com/answer/volume-shadow-copy-backupcomplete-vss-e-bad-state-help-29094302.html
            IVssImplementation   vssImplementation = VssUtils.LoadImplementation();
            IVssBackupComponents backupComponents  = vssImplementation.CreateVssBackupComponents();

            backupComponents.InitializeForBackup(null);
            backupComponents.SetContext(VssSnapshotContext.Backup);

            backupComponents.SetBackupState(false, false, VssBackupType.Copy, false);
            backupComponents.GatherWriterMetadata();

            try
            {
                Guid snapshotSetGuid  = backupComponents.StartSnapshotSet();
                Guid backupVolumeGuid = backupComponents.AddToSnapshotSet(baseDir.Root.FullName);

                backupComponents.PrepareForBackup();
                backupComponents.DoSnapshotSet();

                VssSnapshotProperties properties = backupComponents.GetSnapshotProperties(backupVolumeGuid);

                DirectoryInfo shadowCopyBase = new DirectoryInfo(Path.Combine(properties.SnapshotDeviceObject, Path.GetDirectoryNameWithoutRoot(baseDir.FullName)));

                if (!shadowCopyBase.FullName.EndsWith(Path.DirectorySeparatorChar) && !shadowCopyBase.FullName.EndsWith(Path.AltDirectorySeparatorChar))
                {
                    // Add ending slash to get a uniform output
                    shadowCopyBase = new DirectoryInfo(shadowCopyBase.FullName + Path.DirectorySeparatorChar);
                }

                // Do stuff
                DoFsSnapshot(shadowCopyBase, shadowCopyBase, res.Items);

                // Delete snapshot
                backupComponents.BackupComplete();
                backupComponents.DeleteSnapshotSet(snapshotSetGuid, false);
            }
            catch (Exception)
            {
                backupComponents.AbortBackup();
            }

            //DoFsSnapshot(baseDirectory, baseDirectory, res.Items);

            return(res);
        }
        /// <summary>
        /// Makes a recursive snapshot of the directory as it is.
        /// </summary>
        /// <param name="baseDirectory">The directory to start in.</param>
        /// <returns>A file system snapshot</returns>
        public static SnapshotFilesystem MakeFsSnapshot(System.IO.DirectoryInfo baseDirectory)
        {
            DirectoryInfo baseDir = new DirectoryInfo(baseDirectory.FullName);

            if (!baseDir.Exists)
                throw new ArgumentException("Base directory doesn't exist");

            SnapshotFilesystem res = new SnapshotFilesystem();

            if (!baseDir.FullName.EndsWith(Path.DirectorySeparatorChar) && !baseDir.FullName.EndsWith(Path.AltDirectorySeparatorChar))
            {
                // Add ending slash to get a uniform output
                baseDir = new DirectoryInfo(baseDir.FullName + Path.DirectorySeparatorChar);
            }

            res.BasePath = baseDir.FullName;
            res.Items = new LinkedList<SnapshotFilesystemItem>();

            // Make VSS
            // Sequence of calls: http://us.generation-nt.com/answer/volume-shadow-copy-backupcomplete-vss-e-bad-state-help-29094302.html
            IVssImplementation vssImplementation = VssUtils.LoadImplementation();
            IVssBackupComponents backupComponents = vssImplementation.CreateVssBackupComponents();

            backupComponents.InitializeForBackup(null);
            backupComponents.SetContext(VssSnapshotContext.Backup);

            backupComponents.SetBackupState(false, false, VssBackupType.Copy, false);
            backupComponents.GatherWriterMetadata();

            try
            {
                Guid snapshotSetGuid = backupComponents.StartSnapshotSet();
                Guid backupVolumeGuid = backupComponents.AddToSnapshotSet(baseDir.Root.FullName);

                backupComponents.PrepareForBackup();
                backupComponents.DoSnapshotSet();

                VssSnapshotProperties properties = backupComponents.GetSnapshotProperties(backupVolumeGuid);

                DirectoryInfo shadowCopyBase = new DirectoryInfo(Path.Combine(properties.SnapshotDeviceObject, Path.GetDirectoryNameWithoutRoot(baseDir.FullName)));

                if (!shadowCopyBase.FullName.EndsWith(Path.DirectorySeparatorChar) && !shadowCopyBase.FullName.EndsWith(Path.AltDirectorySeparatorChar))
                {
                    // Add ending slash to get a uniform output
                    shadowCopyBase = new DirectoryInfo(shadowCopyBase.FullName + Path.DirectorySeparatorChar);
                }

                // Do stuff
                DoFsSnapshot(shadowCopyBase, shadowCopyBase, res.Items);

                // Delete snapshot
                backupComponents.BackupComplete();
                backupComponents.DeleteSnapshotSet(snapshotSetGuid, false);
            }
            catch (Exception)
            {
                backupComponents.AbortBackup();
            }

            //DoFsSnapshot(baseDirectory, baseDirectory, res.Items);

            return res;
        }