private void CreateVssSnapshotOfSystemVolume(IVssBackupComponents backupComponents) { try { logger.LogInformation($"Creating VSS snapshot for drive {migrationData.OperatingSystemDriveLetter}:\\"); backupComponents.InitializeForBackup(null); backupComponents.GatherWriterMetadata(); backupComponents.SetContext(VssVolumeSnapshotAttributes.Persistent | VssVolumeSnapshotAttributes.NoAutoRelease); this.vssSnapshotSetId = backupComponents.StartSnapshotSet(); this.vssSnapshotId = backupComponents.AddToSnapshotSet($"{migrationData.OperatingSystemDriveLetter}:\\"); backupComponents.SetBackupState(false, true, VssBackupType.Differential, false); backupComponents.PrepareForBackup(); backupComponents.DoSnapshotSet(); VssSnapshotProperties snapshotInfo = backupComponents.GetSnapshotProperties(this.vssSnapshotId); logger.LogDebug($"VSS snapshot created. Root Path: {snapshotInfo.SnapshotDeviceObject}"); } catch (Exception ex) { logger.LogError(ex, "An error occured during VSS snapshot creation"); if (this.vssSnapshotId != Guid.Empty) { backupComponents.DeleteSnapshot(this.vssSnapshotId, true); this.vssSnapshotId = Guid.Empty; this.vssSnapshotSetId = Guid.Empty; } throw; } }
public void MapVolumesToSnapShots() { _volumeMap = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); foreach (var kvp in _volumes) { _volumeMap.Add(kvp.Key, _vssBackupComponents.GetSnapshotProperties(kvp.Value).SnapshotDeviceObject); } _volumeReverseMap = _volumeMap.ToDictionary(x => x.Value, x => x.Key); }
private void Initialize(string Volume, bool IncludeBootableSystemState) { //string filename = @"C:\Windows\system32\config\sam"; //FileInfo fiSource = new FileInfo(filename); //String Volume = fiSource.Directory.Root.Name; // VSS step 1: Initialize IVssImplementation vss = VssUtils.LoadImplementation(); IVssBackupComponents backup = vss.CreateVssBackupComponents(); backup.InitializeForBackup(null); // VSS step 2: Getting Metadata from all the VSS writers backup.GatherWriterMetadata(); // VSS step 3: VSS Configuration backup.SetContext((VssVolumeSnapshotAttributes)0); backup.SetBackupState(false, IncludeBootableSystemState, Alphaleonis.Win32.Vss.VssBackupType.Full, false); // VSS step 4: Declaring the Volumes that we need to use in this beckup. // The Snapshot is a volume element (hence the name "Volume Shadow-Copy"). // For each file that we nee to copy we have to make sure that the proper volume is included in the "Snapshot Set". Guid SetGuid = backup.StartSnapshotSet(); Guid VolumeGuid = backup.AddToSnapshotSet(Volume, Guid.Empty); // VSS step 5: Preparation (Writers & Provaiders need to start preparation) backup.PrepareForBackup(); // VSS step 6: Create a Snapshot For each volume in the "Snapshot Set" backup.DoSnapshotSet(); /*********************************** * /* At this point we have a snapshot! * /* This action should not take more then 60 second, regardless of file or disk size. * /* The snapshot is not a backup or any copy! * /* please more information at http://technet.microsoft.com/en-us/library/ee923636.aspx * /***********************************/ // VSS step 7: Expose Snapshot /*********************************** * /* Snapshot path look like: * \\?\Volume{011682bf-23d7-11e2-93e7-806e6f6e6963}\ * The build in method System.IO.File.Copy do not work with path like this, * Therefore, we are going to Expose the Snapshot to our application, * by mapping the Snapshot to new virtual volume * - Make sure that you are using a volume that is not already exist * - This is only for learning purposes. usually we will use the snapshot directly as i show in the next example in the blog * /***********************************/ VssSnapshotProperties SnapshotProperties = backup.GetSnapshotProperties(VolumeGuid); DirectoryInfo diShadowRoot = new DirectoryInfo(SnapshotProperties.SnapshotDeviceObject); DirectoryInfo[] Folders = diShadowRoot.GetDirectories(); }
public string GetSnapshotRoot(string volumeName) { try { var snapProperties = backup.GetSnapshotProperties(snapShotsGuids[volumeName]); return(snapProperties.SnapshotDeviceObject); } catch { return(null); } }
private static VssSnapshotProperties GetSnapshotProperties(IVssBackupComponents backupComponents, Guid snapshotId) { VssSnapshotProperties props = new VssSnapshotProperties(); IntPtr buffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(VssSnapshotProperties))); backupComponents.GetSnapshotProperties(snapshotId, buffer); Marshal.PtrToStructure(buffer, props); NativeMethods.VssFreeSnapshotProperties(buffer); return(props); }
private void RemoveVssSnapshotOfSystemVolume(IVssBackupComponents backupComponents) { if (this.vssSnapshotId != Guid.Empty) { try { backupComponents.BackupComplete(); } catch (VssBadStateException) { } VssSnapshotProperties snapshotInfo = backupComponents.GetSnapshotProperties(this.vssSnapshotId); logger.LogDebug($"Removing snapshot {snapshotInfo.SnapshotDeviceObject}"); backupComponents.DeleteSnapshot(this.vssSnapshotId, true); } }
public override void PerformStep() { logger.LogInformation("Cloning operating system."); using (IVssBackupComponents backupComponents = vss.CreateVssBackupComponents()) { this.CreateVssSnapshotOfSystemVolume(backupComponents); try { logger.LogInformation("Copying system partition data..."); using (PrivilegeEnabler privEnabler = new PrivilegeEnabler(Privilege.Backup, Privilege.Restore)) { VssSnapshotProperties snapshotInfo = backupComponents.GetSnapshotProperties(this.vssSnapshotId); using (Stream rawVolStream = this.fileSystemHelper.OpenRawDiskStream(snapshotInfo.SnapshotDeviceObject)) { string vhdFullName = $"{migrationData.VhdFileTemporaryFolder}\\{migrationData.VhdFileName}"; using (VirtualDiskDecorator disk = this.fileSystemHelper.OpenVhdx(vhdFullName)) { var partitionTable = disk.Partitions; if (partitionTable != null) { int partIndex = partitionTable.CreatePrimaryBySector(1, (rawVolStream.Length / disk.Geometry.BytesPerSector), BiosPartitionTypes.Ntfs, false); PartitionInfoDecorator partition = disk.Partitions[partIndex]; using (var vhdPartitionStream = partition.Open()) { this.fileSystemHelper.CloneNtfsFileSystem(rawVolStream, vhdPartitionStream, logger); } } else { logger.LogError("VHD disk does not contain BIOS partition table. Other partitions tables are not supported."); } } } } } finally { this.RemoveVssSnapshotOfSystemVolume(backupComponents); //always remove the VSS snapshot, either after success or failure } logger.LogInformation("Cloning operating system completed."); } return; }
static void BackupFile(string srcPath, string destPath) { srcPath = Path.GetFullPath(srcPath); IVssImplementation vssImpl = VssUtils.LoadImplementation(); using (IVssBackupComponents vss = vssImpl.CreateVssBackupComponents()) { vss.InitializeForBackup(null); vss.SetBackupState(true, true, VssBackupType.Full, false); vss.SetContext(VssSnapshotContext.FileShareBackup); using (IVssAsync async = vss.GatherWriterMetadata()) async.Wait(); Guid vssSet = vss.StartSnapshotSet(); var rootPath = Path.GetPathRoot(srcPath); var snapshotId = vss.AddToSnapshotSet(rootPath, Guid.Empty); using (IVssAsync async = vss.DoSnapshotSet()) async.Wait(); try { var snapshotPath = vss.GetSnapshotProperties(snapshotId).SnapshotDeviceObject; var pathNoRoot = srcPath.Substring(rootPath.Length); var path = Path.Combine(snapshotPath, pathNoRoot); if (File.Exists(destPath)) { File.Delete(destPath); } Alphaleonis.Win32.Filesystem.File.Copy(path, destPath); } finally { vss.DeleteSnapshotSet(vssSet, true); } } }
/// <summary> /// Constructs a new backup snapshot, using all the required disks /// </summary> /// <param name="sourcepaths">The folders that are about to be backed up</param> /// <param name="options">A set of commandline options</param> public WindowsSnapshot(string[] sourcepaths, Dictionary <string, string> options) { try { //Substitute for calling VssUtils.LoadImplementation(), as we have the dlls outside the GAC string alphadir = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "alphavss"); string alphadll = System.IO.Path.Combine(alphadir, VssUtils.GetPlatformSpecificAssemblyShortName() + ".dll"); IVssImplementation vss = (IVssImplementation)System.Reflection.Assembly.LoadFile(alphadll).CreateInstance("Alphaleonis.Win32.Vss.VssImplementation"); var excludedWriters = new Guid[0]; if (options.ContainsKey("vss-exclude-writers")) { excludedWriters = options["vss-exclude-writers"].Split(';').Where(x => !string.IsNullOrWhiteSpace(x) && x.Trim().Length > 0).Select(x => new Guid(x)).ToArray(); } //Check if we should map any drives bool useSubst = Utility.Utility.ParseBoolOption(options, "vss-use-mapping"); //Prepare the backup m_backup = vss.CreateVssBackupComponents(); m_backup.InitializeForBackup(null); m_backup.SetContext(VssSnapshotContext.Backup); m_backup.SetBackupState(false, true, VssBackupType.Full, false); if (excludedWriters.Length > 0) { m_backup.DisableWriterClasses(excludedWriters.ToArray()); } m_sourcepaths = sourcepaths.Select(x => Directory.Exists(x) ? Utility.Utility.AppendDirSeparator(x) : x).ToList(); List <string> hypervPaths; try { m_backup.GatherWriterMetadata(); hypervPaths = PrepareHyperVBackup(options, m_backup.WriterMetadata.FirstOrDefault(o => o.WriterId.Equals(HyperVWriterGuid))); } finally { m_backup.FreeWriterMetadata(); } if (hypervPaths != null) { m_sourcepaths.AddRange(hypervPaths); } //Sanity check for duplicate files/folders var pathDuplicates = m_sourcepaths.GroupBy(x => x, Utility.Utility.ClientFilenameStringComparer) .Where(g => g.Count() > 1).Select(y => y.Key).ToList(); foreach (var pathDuplicate in pathDuplicates) { Logging.Log.WriteMessage(string.Format("Removing duplicate source: {0}", pathDuplicate), Logging.LogMessageType.Information); } if (pathDuplicates.Count > 0) { m_sourcepaths = m_sourcepaths.Distinct(Utility.Utility.ClientFilenameStringComparer).OrderBy(a => a).ToList(); } //Sanity check for multiple inclusions of the same files/folders var pathIncludedPaths = m_sourcepaths.Where(x => m_sourcepaths.Where(y => y != x).Any(z => x.StartsWith(z, Utility.Utility.ClientFilenameStringComparision))).ToList(); foreach (var pathIncluded in pathIncludedPaths) { Logging.Log.WriteMessage(string.Format("Removing already included source: {0}", pathIncluded), Logging.LogMessageType.Information); } if (pathIncludedPaths.Count > 0) { m_sourcepaths = m_sourcepaths.Except(pathIncludedPaths, Utility.Utility.ClientFilenameStringComparer).ToList(); } m_backup.StartSnapshotSet(); //Figure out which volumes are in the set m_volumes = new Dictionary <string, Guid>(StringComparer.InvariantCultureIgnoreCase); foreach (string s in m_sourcepaths) { string drive = Alphaleonis.Win32.Filesystem.Path.GetPathRoot(s); if (!m_volumes.ContainsKey(drive)) { if (!m_backup.IsVolumeSupported(drive)) { throw new VssVolumeNotSupportedException(drive); } m_volumes.Add(drive, m_backup.AddToSnapshotSet(drive)); } } //Make all writers aware that we are going to do the backup m_backup.PrepareForBackup(); //Create the shadow volumes m_backup.DoSnapshotSet(); //Make a little lookup table for faster translation m_volumeMap = new Dictionary <string, string>(StringComparer.InvariantCultureIgnoreCase); foreach (KeyValuePair <string, Guid> kvp in m_volumes) { m_volumeMap.Add(kvp.Key, m_backup.GetSnapshotProperties(kvp.Value).SnapshotDeviceObject); } //If we should map the drives, we do that now and update the volumeMap if (useSubst) { m_mappedDrives = new List <DefineDosDevice>(); foreach (string k in new List <string>(m_volumeMap.Keys)) { try { DefineDosDevice d; m_mappedDrives.Add(d = new DefineDosDevice(m_volumeMap[k])); m_volumeMap[k] = Utility.Utility.AppendDirSeparator(d.Drive); } catch { } } } } catch { //In case we fail in the constructor, we do not want a snapshot to be active try { Dispose(); } catch { } throw; } }
/// <summary> /// Constructs a new backup snapshot, using all the required disks /// </summary> /// <param name="sources">Sources to determine which volumes to include in snapshot</param> /// <param name="options">A set of commandline options</param> public WindowsSnapshot(IEnumerable <string> sources, IDictionary <string, string> options) { try { // Substitute for calling VssUtils.LoadImplementation(), as we have the dlls outside the GAC var assemblyLocation = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); if (assemblyLocation == null) { throw new InvalidOperationException(); } var alphadir = Path.Combine(assemblyLocation, "alphavss"); var alphadll = Path.Combine(alphadir, VssUtils.GetPlatformSpecificAssemblyShortName() + ".dll"); var vss = (IVssImplementation)System.Reflection.Assembly.LoadFile(alphadll).CreateInstance("Alphaleonis.Win32.Vss.VssImplementation"); if (vss == null) { throw new InvalidOperationException(); } var excludedWriters = new Guid[0]; if (options.ContainsKey("vss-exclude-writers")) { excludedWriters = options["vss-exclude-writers"].Split(';').Where(x => !string.IsNullOrWhiteSpace(x) && x.Trim().Length > 0).Select(x => new Guid(x)).ToArray(); } //Check if we should map any drives var useSubst = Utility.Utility.ParseBoolOption(options, "vss-use-mapping"); //Prepare the backup m_backup = vss.CreateVssBackupComponents(); m_backup.InitializeForBackup(null); m_backup.SetContext(VssSnapshotContext.Backup); m_backup.SetBackupState(false, true, VssBackupType.Full, false); if (excludedWriters.Length > 0) { m_backup.DisableWriterClasses(excludedWriters.ToArray()); } try { m_backup.GatherWriterMetadata(); } finally { m_backup.FreeWriterMetadata(); } m_backup.StartSnapshotSet(); //Figure out which volumes are in the set m_volumes = new Dictionary <string, Guid>(StringComparer.OrdinalIgnoreCase); foreach (var s in sources) { var drive = AlphaFS.Path.GetPathRoot(s); if (!m_volumes.ContainsKey(drive)) { //TODO: that seems a bit harsh... we could fall-back to not using VSS for that volume only if (!m_backup.IsVolumeSupported(drive)) { throw new VssVolumeNotSupportedException(drive); } m_volumes.Add(drive, m_backup.AddToSnapshotSet(drive)); } } //Make all writers aware that we are going to do the backup m_backup.PrepareForBackup(); //Create the shadow volumes m_backup.DoSnapshotSet(); //Make a little lookup table for faster translation m_volumeMap = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); foreach (var kvp in m_volumes) { m_volumeMap.Add(kvp.Key, m_backup.GetSnapshotProperties(kvp.Value).SnapshotDeviceObject); } m_volumeReverseMap = m_volumeMap.ToDictionary(x => x.Value, x => x.Key); //If we should map the drives, we do that now and update the volumeMap if (useSubst) { m_mappedDrives = new List <DefineDosDevice>(); foreach (var k in new List <string>(m_volumeMap.Keys)) { try { DefineDosDevice d; m_mappedDrives.Add(d = new DefineDosDevice(m_volumeMap[k])); m_volumeMap[k] = Utility.Utility.AppendDirSeparator(d.Drive); } catch (Exception ex) { Logging.Log.WriteVerboseMessage(LOGTAG, "SubstMappingfailed", ex, "Failed to map VSS path {0} to drive", k); } } } } catch { //In case we fail in the constructor, we do not want a snapshot to be active try { Dispose(); } catch (Exception ex) { Logging.Log.WriteVerboseMessage(LOGTAG, "VSSCleanupOnError", ex, "Failed during VSS error cleanup"); } throw; } }
/// <summary> /// Constructs a new backup snapshot, using all the required disks /// </summary> /// <param name="sourcepaths">The folders that are about to be backed up</param> /// <param name="options">A set of commandline options</param> public WindowsSnapshot(string[] sourcepaths, Dictionary<string, string> options) { try { //Substitute for calling VssUtils.LoadImplementation(), as we have the dlls outside the GAC string alphadir = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "alphavss"); string alphadll = System.IO.Path.Combine(alphadir, VssUtils.GetPlatformSpecificAssemblyName().Name + ".dll"); IVssImplementation vss = (IVssImplementation)System.Reflection.Assembly.LoadFile(alphadll).CreateInstance("Alphaleonis.Win32.Vss.VssImplementation"); List<Guid> excludedWriters = new List<Guid>(); if (options.ContainsKey("vss-exclude-writers")) { foreach (string s in options["vss-exclude-writers"].Split(';')) if (!string.IsNullOrEmpty(s) && s.Trim().Length > 0) excludedWriters.Add(new Guid(s)); } //Check if we should map any drives bool useSubst = Utility.Utility.ParseBoolOption(options, "vss-use-mapping"); //Prepare the backup m_backup = vss.CreateVssBackupComponents(); m_backup.InitializeForBackup(null); if (excludedWriters.Count > 0) m_backup.DisableWriterClasses(excludedWriters.ToArray()); m_snapshotId = m_backup.StartSnapshotSet(); m_sourcepaths = new string[sourcepaths.Length]; for(int i = 0; i < m_sourcepaths.Length; i++) m_sourcepaths[i] = Utility.Utility.AppendDirSeparator(sourcepaths[i]); try { //Gather information on all Vss writers using (IVssAsync async = m_backup.GatherWriterMetadata()) async.Wait(); m_backup.FreeWriterMetadata(); } catch { try { m_backup.FreeWriterMetadata(); } catch { } throw; } //Figure out which volumes are in the set m_volumes = new Dictionary<string, Guid>(StringComparer.InvariantCultureIgnoreCase); foreach (string s in m_sourcepaths) { string drive = Alphaleonis.Win32.Filesystem.Path.GetPathRoot(s); if (!m_volumes.ContainsKey(drive)) { if (!m_backup.IsVolumeSupported(drive)) throw new VssVolumeNotSupportedException(drive); m_volumes.Add(drive, m_backup.AddToSnapshotSet(drive)); } } //Signal that we want to do a backup m_backup.SetBackupState(false, true, VssBackupType.Full, false); //Make all writers aware that we are going to do the backup using (IVssAsync async = m_backup.PrepareForBackup()) async.Wait(); //Create the shadow volumes using (IVssAsync async = m_backup.DoSnapshotSet()) async.Wait(); //Make a little lookup table for faster translation m_volumeMap = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase); foreach(KeyValuePair<string, Guid> kvp in m_volumes) m_volumeMap.Add(kvp.Key, m_backup.GetSnapshotProperties(kvp.Value).SnapshotDeviceObject); //If we should map the drives, we do that now and update the volumeMap if (useSubst) { m_mappedDrives = new List<DefineDosDevice>(); foreach (string k in new List<string>(m_volumeMap.Keys)) { try { DefineDosDevice d; m_mappedDrives.Add(d = new DefineDosDevice(m_volumeMap[k])); m_volumeMap[k] = Utility.Utility.AppendDirSeparator(d.Drive); } catch { } } } } catch { //In case we fail in the constructor, we do not want a snapshot to be active try { Dispose(); } catch { } throw; } }
private static VssSnapshotProperties GetSnapshotProperties(IVssBackupComponents backupComponents, Guid snapshotId) { VssSnapshotProperties props = new VssSnapshotProperties(); IntPtr buffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(VssSnapshotProperties))); backupComponents.GetSnapshotProperties(snapshotId, buffer); Marshal.PtrToStructure(buffer, props); NativeMethods.VssFreeSnapshotProperties(buffer); return props; }
/// <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); }
private void BackupSubset(IDictionary <string, string> vmNamesMapSubset, Options options) { IVssImplementation vssImpl = VssUtils.LoadImplementation(); using (IVssBackupComponents vss = vssImpl.CreateVssBackupComponents()) { RaiseEvent(EventAction.InitializingVSS, null, null); vss.InitializeForBackup(null); vss.SetBackupState(true, true, VssBackupType.Full, false); vss.SetContext(VssSnapshotContext.Backup); // Add Hyper-V writer Guid hyperVwriterGuid = new Guid("66841cd4-6ded-4f4b-8f17-fd23f8ddc3de"); vss.EnableWriterClasses(new Guid[] { hyperVwriterGuid }); vss.GatherWriterMetadata(); IList <IVssWMComponent> components = new List <IVssWMComponent>(); // key: volumePath, value: volumeName. These values are equivalent on a standard volume, but differ in the CSV case IDictionary <string, string> volumeMap = new Dictionary <string, string>(); var wm = vss.WriterMetadata.Where((o) => o.WriterId.Equals(hyperVwriterGuid)).FirstOrDefault(); foreach (var component in wm.Components) { if (vmNamesMapSubset.ContainsKey(component.ComponentName)) { components.Add(component); vss.AddComponent(wm.InstanceId, wm.WriterId, component.Type, component.LogicalPath, component.ComponentName); foreach (var file in component.Files) { string volumeName = null; string volumePath = null; volumePath = Path.GetPathRoot(file.Path).ToUpper(); volumeName = volumePath; if (!volumeMap.ContainsKey(volumePath)) { volumeMap.Add(volumePath, volumeName); } } } } if (components.Count > 0) { Guid vssSet = vss.StartSnapshotSet(); // Key: volumeName, value: snapshotGuid IDictionary <string, Guid> snapshots = new Dictionary <string, Guid>(); foreach (var volumeName in volumeMap.Values) { snapshots.Add(volumeName, vss.AddToSnapshotSet(volumeName, Guid.Empty)); } vss.PrepareForBackup(); RaiseEvent(EventAction.StartingSnaphotSet, components, volumeMap); vss.DoSnapshotSet(); RaiseEvent(EventAction.SnapshotSetDone, components, volumeMap); // key: volumeName, value: snapshotVolumePath IDictionary <string, string> snapshotVolumeMap = new Dictionary <string, string>(); foreach (var kv in snapshots) { snapshotVolumeMap.Add(kv.Key, vss.GetSnapshotProperties(kv.Value).SnapshotDeviceObject); } BackupFiles(components, volumeMap, snapshotVolumeMap, vmNamesMapSubset, options); foreach (var component in components) { vss.SetBackupSucceeded(wm.InstanceId, wm.WriterId, component.Type, component.LogicalPath, component.ComponentName, true); } vss.BackupComplete(); RaiseEvent(EventAction.DeletingSnapshotSet, components, volumeMap); vss.DeleteSnapshotSet(vssSet, true); } } }
public ISnapshot[] CreateVolumeSnapShot(List <FileSystem> volumes, string[] spoPaths, SnapshotSupportedLevel level) { using (new Alphaleonis.Win32.Security.PrivilegeEnabler(Privilege.Backup, Privilege.Restore)){ //PrivilegesManager pm = new PrivilegesManager(); //pm.Grant(); VssBackupType vssLevel = VssBackupType.Full; if (level == SnapshotSupportedLevel.Full) { vssLevel = VssBackupType.Full; } else if (level == SnapshotSupportedLevel.Incremental) { vssLevel = VssBackupType.Incremental; } else if (level == SnapshotSupportedLevel.Differential) { vssLevel = VssBackupType.Differential; } else if (level == SnapshotSupportedLevel.TransactionLog) { vssLevel = VssBackupType.Log; } ArrayList snapshots = new ArrayList(); Metadata = new SPOMetadata(); bool snapshotSuccedeed = false; try{ IVssImplementation vss = VssUtils.LoadImplementation(); backup = vss.CreateVssBackupComponents(); Logger.Append(Severity.DEBUG, "0/6 Initializing Snapshot (" + ((spoPaths == null)? "NON-component mode" : "component mode") + ", level " + level + ")"); backup.InitializeForBackup(null); if (spoPaths == null) // component-less snapshot set { backup.SetBackupState(false, true, VssBackupType.Full, false); } else { backup.SetBackupState(true, true, vssLevel, (vssLevel == VssBackupType.Full)?false:true); } if (OperatingSystemInfo.IsAtLeast(OSVersionName.WindowsServer2003)) { // The only context supported on Windows XP is VssSnapshotContext.Backup backup.SetContext(VssSnapshotContext.AppRollback /*|VssSnapshotContext.All*/); } Logger.Append(Severity.DEBUG, "1/6 Gathering writers metadata and status"); using (IVssAsync async = backup.GatherWriterMetadata()){ async.Wait(); async.Dispose(); } // gather writers status before adding backup set components using (IVssAsync async = backup.GatherWriterStatus()){ async.Wait(); async.Dispose(); } Logger.Append(Severity.DEBUG, "2/6 Adding writers and components"); // Now we add the components (vss writers, writer paths/params) of this snapshot set if (spoPaths != null) { foreach (IVssExamineWriterMetadata writer in backup.WriterMetadata) { foreach (string spo in spoPaths) { //Logger.Append (Severity.TRIVIA, "Searching writer and/or component matching "+spo); int index = spo.IndexOf(writer.WriterName); if (index < 0 && spo != "*") { continue; } bool found = false; Logger.Append(Severity.TRIVIA, "Found matching writer " + writer.WriterName + ", instance name=" + writer.InstanceName); // First we check that the writer's status is OK, else we don't add it to avoid failure of complete snapshot if it's not bool writerOk = false; foreach (VssWriterStatusInfo status in backup.WriterStatus) { if (status.Name == writer.WriterName) { Logger.Append(Severity.TRIVIA, "Checking required writer " + status.Name + ", status=" + status.State.ToString() + ", error state=" + status.Failure.ToString()); if (status.State == VssWriterState.Stable && status.Failure == VssError.Success) // if we get there it means that we are ready to add the wanted component to VSS set { writerOk = true; } else { Logger.Append(Severity.ERROR, "Cannot add writer " + status.Name + " to snapshot set," + " status=" + status.State.ToString() + ". Backup data managed by this writer may not be consistent"); if (LogEvent != null) { LogEvent(this, new LogEventArgs(820, Severity.WARNING, status.Name + ", Status=" + status.State.ToString() + ", Failure=" + status.Failure.ToString())); } } } } if (!writerOk) { if (OperatingSystemInfo.IsAtLeast(OSVersionName.WindowsServer2003)) { backup.DisableWriterClasses(new Guid[] { writer.WriterId }); } continue; } bool addAllComponents = false; if (spo.Length == index + writer.WriterName.Length || spo == "*" || spo == "" + writer.WriterName + @"\*") { addAllComponents = true; } foreach (IVssWMComponent component in writer.Components) { found = false; //Console.WriteLine("createvolsnapshot : current component is :"+component.LogicalPath+@"\"+component.ComponentName); if ((!addAllComponents) && spo.IndexOf(component.LogicalPath + @"\" + component.ComponentName) < 0) { continue; } //Logger.Append (Severity.TRIVIA, "Asked to recursively select all '"+writer.WriterName+"' writer's components"); if (OperatingSystemInfo.IsAtLeast(OSVersionName.WindowsServer2003)) { foreach (VssWMDependency dep in component.Dependencies) { Logger.Append(Severity.TRIVIA, "Component " + component.ComponentName + " depends on component " + dep.ComponentName); } } if (component.Selectable) { backup.AddComponent(writer.InstanceId, writer.WriterId, component.Type, component.LogicalPath, component.ComponentName); } Logger.Append(Severity.INFO, "Added writer '" + writer.WriterName + "' component " + component.ComponentName); found = true; // Second we need to find every drive containing files necessary for writer's backup // and add them to drives list, in case they weren't explicitely selected as part of backuppaths List <VssWMFileDescription> componentFiles = new List <VssWMFileDescription>(); componentFiles.AddRange(component.Files); componentFiles.AddRange(component.DatabaseFiles); componentFiles.AddRange(component.DatabaseLogFiles); foreach (VssWMFileDescription file in componentFiles) { if (string.IsNullOrEmpty(file.Path)) { continue; } //Console.WriteLine ("component file path="+file.Path+", alt backuplocation="+file.AlternateLocation // +", backuptypemask="+file.BackupTypeMask.ToString()+", spec="+file.FileSpecification+", recursive="+file.IsRecursive); // TODO : Reuse GetInvolvedDrives (put it into VolumeManager class) string drive = file.Path.Substring(0, 3).ToUpper(); if (drive.Contains(":") && drive.Contains("\\")) { var searchedVol = from FileSystem vol in volumes where vol.MountPoint.Contains(drive) select vol; //if(!volumes.Contains(drive)){ if (searchedVol == null) { Logger.Append(Severity.INFO, "Select VSS component " + component.LogicalPath + @"\" + component.ComponentName + " requires snapshotting of drive " + drive + ", adding it to the list."); volumes.Add(searchedVol.First()); } break; } } //Logger.Append(Severity.TRIVIA, "Added writer/component "+spo); //break; } //metadata.Metadata.Add(writer.SaveAsXml()); Metadata.Metadata.Add(writer.WriterName, writer.SaveAsXml()); if (found == false) { Logger.Append(Severity.WARNING, "Could not find VSS component " + spo + " which was part of backup paths"); } } } } Logger.Append(Severity.DEBUG, "3/6 Preparing Snapshot "); //backup.SetBackupState(false, true, VssBackupType.Full, false); Guid snapID = backup.StartSnapshotSet(); //Guid volID = new Guid(); foreach (FileSystem volume in volumes) { VSSSnapshot snapshot = new VSSSnapshot(); snapshot.Type = this.Name; Logger.Append(Severity.DEBUG, "Preparing Snapshot of " + volume.MountPoint); if (volume.MountPoint != null && backup.IsVolumeSupported(volume.MountPoint)) { snapshot.Id = backup.AddToSnapshotSet(volume.MountPoint); snapshot.Path = volume.MountPoint; } else // return the fake provider to get at least a degraded backup, better than nothing { Logger.Append(Severity.WARNING, "Volume '" + volume.MountPoint + "' is not snapshottable (or null). Backup will be done without snapshot, risks of data inconsistancy."); ISnapshotProvider fakeSnapProvider = SnapshotProvider.GetProvider("NONE"); List <FileSystem> fakeList = new List <FileSystem>(); fakeList.Add(volume); snapshot = (VSSSnapshot)fakeSnapProvider.CreateVolumeSnapShot(fakeList, null, SnapshotSupportedLevel.Full)[0]; } if (snapshot.Id == System.Guid.Empty) { Logger.Append(Severity.ERROR, "Unable to add drive " + volume.MountPoint + " to snapshot set (null guid)"); } else { Logger.Append(Severity.TRIVIA, "Drive " + volume.MountPoint + " will be snapshotted to " + snapshot.Id); } snapshots.Add(snapshot); } Logger.Append(Severity.DEBUG, "4/6 Calling Prepare..."); using (IVssAsync async = backup.PrepareForBackup()){ async.Wait(); async.Dispose(); } Logger.Append(Severity.DEBUG, "5/6 Snapshotting volumes"); using (IVssAsync async = backup.DoSnapshotSet()){ async.Wait(); async.Dispose(); } //if(OperatingSystemInfo.IsAtLeast(OSVersionName.WindowsServer2003)) foreach (IVssExamineWriterMetadata w in backup.WriterMetadata) { foreach (IVssWMComponent comp in w.Components) { try{ backup.SetBackupSucceeded(w.InstanceId, w.WriterId, comp.Type, comp.LogicalPath, comp.ComponentName, true); Logger.Append(Severity.TRIVIA, "Component " + comp.ComponentName + " has been notified about backup success."); } catch (Exception) { //Logger.Append (Severity.WARNING, "Could not notify component "+comp.ComponentName+" about backup completion : "+se.Message); } } } //Node.Misc.VSSObjectHandle.StoreObject(backup); try{ //on XP backupcomplete consider that we have done with the snapshot and releases it. //if(OperatingSystemInfo.IsAtLeast(OSVersionName.WindowsServer2003)){ backup.BackupComplete(); Metadata.Metadata.Add("_bcd_", backup.SaveAsXml()); //} }catch (Exception bce) { Logger.Append(Severity.WARNING, "Error calling VSS BackupComplete() : " + bce.Message); } using (IVssAsync async = backup.GatherWriterStatus()){ async.Wait(); async.Dispose(); } Logger.Append(Severity.DEBUG, "6/6 Successfully shapshotted volume(s) "); foreach (ISnapshot sn in snapshots) { if (sn.Id == Guid.Empty) { continue; } sn.MountPoint = backup.GetSnapshotProperties(sn.Id).SnapshotDeviceObject; sn.TimeStamp = Utilities.Utils.GetUtcUnixTime(backup.GetSnapshotProperties(sn.Id).CreationTimestamp.ToUniversalTime()); /* * DirectoryInfo snapMountPoint = Directory.CreateDirectory( Path.Combine(Utilities.ConfigManager.GetValue("Backups.TempFolder"), "snapshot_"+sn.Id)); * Logger.Append(Severity.DEBUG, "Mounting shapshotted volume '"+sn.Name+"' to '"+snapMountPoint.FullName+"'"); * backup.ExposeSnapshot(sn.Id, null, VssVolumeSnapshotAttributes.ExposedLocally, snapMountPoint.FullName); * //sn.Path = snapMountPoint.FullName+Path.DirectorySeparatorChar; * //sn.Path = @"\\?\Volume{"+sn.Id+"}"+Path.DirectorySeparatorChar;*/ } } catch (Exception e) { try{ //backup.BackupComplete(); backup.AbortBackup(); } catch (Exception ae) { Logger.Append(Severity.ERROR, "Error trying to cancel VSS snapshot set : " + ae.Message); } // TODO !! report snapshoty failure to hub task Logger.Append(Severity.ERROR, "Error creating snapshot :'" + e.Message + " ---- " + e.StackTrace + "'. Backup will continue without snapshot. Backup of VSS components will fail. !TODO! report that to hub"); backup.Dispose(); throw new Exception(e.Message); } finally{ // TODO !!! reactivate dispose //backup.Dispose(); //pm.Revoke(); } return((ISnapshot[])snapshots.ToArray(typeof(ISnapshot))); } }
/// <summary> /// Constructs a new backup snapshot, using all the required disks /// </summary> /// <param name="sourcepaths">The folders that are about to be backed up</param> /// <param name="options">A set of commandline options</param> public WindowsSnapshot(string[] sourcepaths, Dictionary <string, string> options) { try { //Substitute for calling VssUtils.LoadImplementation(), as we have the dlls outside the GAC string alphadir = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "alphavss"); string alphadll = System.IO.Path.Combine(alphadir, VssUtils.GetPlatformSpecificAssemblyShortName() + ".dll"); IVssImplementation vss = (IVssImplementation)System.Reflection.Assembly.LoadFile(alphadll).CreateInstance("Alphaleonis.Win32.Vss.VssImplementation"); List <Guid> excludedWriters = new List <Guid>(); if (options.ContainsKey("vss-exclude-writers")) { foreach (string s in options["vss-exclude-writers"].Split(';')) { if (!string.IsNullOrEmpty(s) && s.Trim().Length > 0) { excludedWriters.Add(new Guid(s)); } } } //Check if we should map any drives bool useSubst = Utility.Utility.ParseBoolOption(options, "vss-use-mapping"); //Prepare the backup m_backup = vss.CreateVssBackupComponents(); m_backup.InitializeForBackup(null); if (excludedWriters.Count > 0) { m_backup.DisableWriterClasses(excludedWriters.ToArray()); } m_backup.StartSnapshotSet(); m_sourcepaths = new string[sourcepaths.Length]; for (int i = 0; i < m_sourcepaths.Length; i++) { m_sourcepaths[i] = System.IO.Directory.Exists(sourcepaths[i]) ? Utility.Utility.AppendDirSeparator(sourcepaths[i]) : sourcepaths[i]; } try { //Gather information on all Vss writers m_backup.GatherWriterMetadata(); m_backup.FreeWriterMetadata(); } catch { try { m_backup.FreeWriterMetadata(); } catch { } throw; } //Figure out which volumes are in the set m_volumes = new Dictionary <string, Guid>(StringComparer.InvariantCultureIgnoreCase); foreach (string s in m_sourcepaths) { string drive = Alphaleonis.Win32.Filesystem.Path.GetPathRoot(s); if (!m_volumes.ContainsKey(drive)) { if (!m_backup.IsVolumeSupported(drive)) { throw new VssVolumeNotSupportedException(drive); } m_volumes.Add(drive, m_backup.AddToSnapshotSet(drive)); } } //Signal that we want to do a backup m_backup.SetBackupState(false, true, VssBackupType.Full, false); //Make all writers aware that we are going to do the backup m_backup.PrepareForBackup(); //Create the shadow volumes m_backup.DoSnapshotSet(); //Make a little lookup table for faster translation m_volumeMap = new Dictionary <string, string>(StringComparer.InvariantCultureIgnoreCase); foreach (KeyValuePair <string, Guid> kvp in m_volumes) { m_volumeMap.Add(kvp.Key, m_backup.GetSnapshotProperties(kvp.Value).SnapshotDeviceObject); } //If we should map the drives, we do that now and update the volumeMap if (useSubst) { m_mappedDrives = new List <DefineDosDevice>(); foreach (string k in new List <string>(m_volumeMap.Keys)) { try { DefineDosDevice d; m_mappedDrives.Add(d = new DefineDosDevice(m_volumeMap[k])); m_volumeMap[k] = Utility.Utility.AppendDirSeparator(d.Drive); } catch { } } } } catch { //In case we fail in the constructor, we do not want a snapshot to be active try { Dispose(); } catch { } throw; } }
public bool Create(List<String> Volumes) { try { if (OperatingSystemInfo.ProcessorArchitecture == ProcessorArchitecture.X64 || OperatingSystemInfo.ProcessorArchitecture == ProcessorArchitecture.IA64) { if (!System.IO.File.Exists(System.Windows.Forms.Application.StartupPath + "\\AlphaVSS.60.x64.dll")) { HelperFunctions.ShowError(Translations.Get("WrongVersion64")); Settings.ShadowCopy = false; return false; } } else { if (!System.IO.File.Exists(System.Windows.Forms.Application.StartupPath + "\\AlphaVSS.60.x86.dll")) { HelperFunctions.ShowError(Translations.Get("WrongVersion32")); Settings.ShadowCopy = false; return false; } } if (GlobalData.SettingsInAppData) { _OldSnapshotSetIdsPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\RoboGapp\\SnapshotIds.dat"; } else { _OldSnapshotSetIdsPath = System.Windows.Forms.Application.StartupPath + "\\SnapshotIds.dat"; } Abort(); HelperFunctions.WriteLog(Translations.Get("LoadingVSSImplementation")); IVssImplementation VssImplementation = null; try { VssImplementation = VssUtils.LoadImplementation(); } catch (Exception ex) { HelperFunctions.ShowError(Translations.Get("ShadowCopyError") + "\n\n" + Translations.Get("Error") + "\n" + ex.Message); if (OperatingSystemInfo.ProcessorArchitecture == ProcessorArchitecture.X64) { HelperFunctions.ShowError(Translations.Get("VCRedist64")); } else if (OperatingSystemInfo.ProcessorArchitecture == ProcessorArchitecture.IA64) { HelperFunctions.ShowError(Translations.Get("VCRedistIA64")); } else { HelperFunctions.ShowError(Translations.Get("VCRedist32")); } return false; } HelperFunctions.WriteLog(Translations.Get("CreatingBackupComponents")); _BackupComponents = VssImplementation.CreateVssBackupComponents(); HelperFunctions.WriteLog(Translations.Get("InitializingVSSBackup")); _BackupComponents.InitializeForBackup(null); if (OperatingSystemInfo.OSVersionName > OSVersionName.WindowsServer2003) { HelperFunctions.WriteLog(Translations.Get("SettingVSSContext")); _BackupComponents.SetContext(VssVolumeSnapshotAttributes.Persistent | VssVolumeSnapshotAttributes.NoAutoRelease); } HelperFunctions.WriteLog(Translations.Get("SettingVSSBackupState")); _BackupComponents.SetBackupState(false, true, VssBackupType.Full, false); HelperFunctions.WriteLog(Translations.Get("GatheringWriterMetadata")); _BackupComponents.GatherWriterMetadata(); HelperFunctions.WriteLog(Translations.Get("CreatingSnapshotSet")); _SnapshotSetId = _BackupComponents.StartSnapshotSet(); _SnapshotIds.Clear(); for (int i = 0; i < Volumes.Count; i++) { HelperFunctions.WriteLog(Translations.Get("AddingToSnapshotSet1") + Volumes[i] + Translations.Get("AddingToSnapshotSet2")); Guid SnapshotId = _BackupComponents.AddToSnapshotSet(Volumes[i], Guid.Empty); _SnapshotIds.Add(SnapshotId); } HelperFunctions.WriteLog(Translations.Get("SavingSnapshotSetID")); SaveSnapshotSetId(); HelperFunctions.WriteLog(Translations.Get("PreparingVSSBackup")); _BackupComponents.PrepareForBackup(); HelperFunctions.WriteLog(Translations.Get("CreatingVSSSnapshots")); _BackupComponents.DoSnapshotSet(); HelperFunctions.WriteLog(Translations.Get("ExposingSnapshots")); GlobalData.ShadowCopyMounts.Clear(); List<String> FreeDriveLetters = IO.GetFreeDriveLetters(); String Path = System.Windows.Forms.Application.StartupPath; if (OperatingSystemInfo.OSVersionName > OSVersionName.WindowsServer2003) { try { if (System.IO.File.Exists(Path + "\\write.test")) File.Delete(Path + "\\write.test"); using (System.IO.File.Create(Path + "\\write.test")) { } File.Delete(Path + "\\write.test"); } catch { Path = IO.GetCommonApplicationDataPath(); if (Path == "") { HelperFunctions.ShowError(Translations.Get("ExposingSnapshotsDirError")); return false; } } } for (int i = 0; i < Volumes.Count; i++) { if (OperatingSystemInfo.OSVersionName <= OSVersionName.WindowsServer2003) { GlobalData.ShadowCopyMounts.Add(Volumes[i], FreeDriveLetters[i]); DefineDosDevice(0, FreeDriveLetters[i].Substring(0, 2), _BackupComponents.GetSnapshotProperties(_SnapshotIds[i]).SnapshotDeviceObject); } else { DriveInfo DriveInfo = null; if (Path == System.Windows.Forms.Application.StartupPath) { DriveInfo = DriveInfo.GetDrives().FirstOrDefault((DriveInfo DI) => DI.RootDirectory.ToString() == System.Windows.Forms.Application.StartupPath.Substring(0, 3)); if (DriveInfo == null || DriveInfo.DriveType == DriveType.Network) { Path = IO.GetCommonApplicationDataPath(); if (Path == "") { HelperFunctions.ShowError(Translations.Get("ExposingSnapshotsDirError")); return false; } } } GlobalData.ShadowCopyMounts.Add(Volumes[i], Path + "\\mnt" + i.ToString() + "\\"); if (System.IO.Directory.Exists(GlobalData.ShadowCopyMounts[Volumes[i]])) { try { Directory.Delete(GlobalData.ShadowCopyMounts[Volumes[i]], false); } catch (Exception ex) { HelperFunctions.ShowError(ex); return false; } } Directory.Create(GlobalData.ShadowCopyMounts[Volumes[i]]); _BackupComponents.ExposeSnapshot(_SnapshotIds[i], null, VssVolumeSnapshotAttributes.ExposedLocally, GlobalData.ShadowCopyMounts[Volumes[i]]); } } HelperFunctions.WriteLog(Translations.Get("SnapshotSuccessful")); return true; } catch (Exception ex) { HelperFunctions.ShowError(ex); return false; } }