/// <summary> /// The final phase of the backup involves some cleanup steps. /// If we're in component mode, we're supposed to notify each of the /// writers of the outcome of the backup. Once that's done, or if /// we're not in component mode, we send the BackupComplete event to /// all of the writers. /// </summary> /// <param name="succeeded">Success value for all of the writers.</param> void Complete(bool succeeded) { if (ComponentMode) { // As before, we iterate through all of the writers on the system. // A more efficient method might only iterate through those writers // that were actually involved in this backup. IList <IVssExamineWriterMetadata> writers = _backup.WriterMetadata; foreach (IVssExamineWriterMetadata metadata in writers) { foreach (IVssWMComponent component in metadata.Components) { // The BackupSucceeded call should mirror the AddComponent // call that was called during the discovery phase. _backup.SetBackupSucceeded( metadata.InstanceId, metadata.WriterId, component.Type, component.LogicalPath, component.ComponentName, succeeded); } } // Finally, we can dispose of the writer metadata. _backup.FreeWriterMetadata(); } try { // The BackupComplete event must be sent to all of the writers. using (IVssAsync async = _backup.BackupComplete()) async.Wait(); } // Not sure why, but this throws a VSS_BAD_STATE on XP and W2K3. // Per some forum posts about this, I'm just ignoring it. catch (VssBadStateException) { } }
/// <summary> /// This phase of the backup is focused around creating the shadow copy. /// We will notify writers of the impending snapshot, after which they /// have a short period of time to get their on-disk data in order and /// then quiesce writing. /// </summary> void PreBackup() { Debug.Assert(_snap != null); // This next bit is a way to tell writers just what sort of backup // they should be preparing for. The important parts for us now // are the first and third arguments: we want to do a full, // backup and, depending on whether we are in component mode, either // a full-volume backup or a backup that only requires specific // components. _backup.SetBackupState(ComponentMode, true, VssBackupType.Full, false); // From here we just need to send messages to each writer that our // snapshot is imminent, using (IVssAsync async = _backup.PrepareForBackup()) { // As before, the 'using' statement automatically disposes of // our comm link. Also as before, we simply block while the // writers to complete their background preparations. async.Wait(); } // It's now time to create the snapshot. Each writer will have to // freeze its I/O to the selected volumes for up to 10 seconds // while this process takes place. _snap.Copy(); }
public void Complete(bool succeeded) { try { // The BackupComplete event must be sent to all of the writers. using (IVssAsync async = _backup.BackupComplete()) async.Wait(); } catch (VssBadStateException) { } }
void InitializeBackup() { IVssImplementation vss = VssUtils.LoadImplementation(); _backup = vss.CreateVssBackupComponents(); _backup.InitializeForBackup(null); using (IVssAsync async = _backup.GatherWriterMetadata()) { async.Wait(); } }
public bool IsVolumeSnapshottable(string volumeName) { IVssImplementation vssImplementation = VssUtils.LoadImplementation(); using (IVssBackupComponents backup = vssImplementation.CreateVssBackupComponents()){ backup.InitializeForBackup(null); using (IVssAsync async = backup.GatherWriterMetadata()){ async.Wait(); async.Dispose(); } return(backup.IsVolumeSupported(volumeName)); } }
public void PreBackup() { Debug.Assert(_set_id != null); _backup.SetBackupState(false, true, VssBackupType.Full, false); using (IVssAsync async = _backup.PrepareForBackup()) { async.Wait(); } Copy(); }
public VSS(BackupLevel level) { this.RestorePosition = RestoreOrder.AfterStorage; this.ExplodedComponents = new List <string>(); Metadata = new SPOMetadata(); BasePaths = new List <BasePath>(); IVssImplementation vss = VssUtils.LoadImplementation(); backup = vss.CreateVssBackupComponents(); //Logger.Append(Severity.DEBUG, "0/6 Initializing Snapshot ("+ ((BasePaths == null)? "NON-component mode" : "component mode")+")"); backup.InitializeForBackup(null); VssBackupType vssLevel = VssBackupType.Full; if (level == BackupLevel.Full) { vssLevel = VssBackupType.Full; } else if (level == BackupLevel.Refresh) { vssLevel = VssBackupType.Incremental; } /* else if (level == BackupLevel.Differential) * vssLevel = VssBackupType.Differential;*/ else if (level == BackupLevel.TransactionLog) { vssLevel = VssBackupType.Log; } //if(spoPaths == null) // component-less snapshot set // backup.SetBackupState(false, true, VssBackupType.Full, false); //else backup.SetBackupState(true, true, vssLevel, false); if (OperatingSystemInfo.IsAtLeast(OSVersionName.WindowsServer2003)) { // The only context supported on Windows XP is VssSnapshotContext.Backup backup.SetContext(VssSnapshotContext.AppRollback); } //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(); } }
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> /// This stage initializes both the requester (this program) and /// any writers on the system in preparation for a backup and sets /// up a communcation channel between the two. /// </summary> void InitializeBackup() { // Here we are retrieving an OS-dependent object that encapsulates // all of the VSS functionality. The OS indepdence that this single // factory method provides is one of AlphaVSS's major strengths! IVssImplementation vss = VssUtils.LoadImplementation(); // Now we create a BackupComponents object to manage the backup. // This object will have a one-to-one relationship with its backup // and must be cleaned up when the backup finishes (ie. it cannot // be reused). // // Note that this object is a member of our class, as it needs to // stick around for the full backup. _backup = vss.CreateVssBackupComponents(); // Now we must initialize the components. We can either start a // fresh backup by passing null here, or we could resume a previous // backup operation through an earlier use of the SaveXML method. _backup.InitializeForBackup(null); // At this point, we're supposed to establish communication with // the writers on the system. It is possible before this step to // enable or disable specific writers via the BackupComponents' // Enable* and Disable* methods. // // Note the 'using' construct here to dispose of the asynchronous // comm link once we no longer need it. using (IVssAsync async = _backup.GatherWriterMetadata()) { // Because allowing writers to prepare their metadata can take // a while, we are given a VssAsync object that gives us some // status on the background operation. In this case, we just // wait for it to finish. async.Wait(); } }
public List <ISnapshot> ListSpecialObjects() { List <ISnapshot> alreadyExisting = new List <ISnapshot>(); IVssImplementation vssImplementation = VssUtils.LoadImplementation(); using (IVssBackupComponents backup = vssImplementation.CreateVssBackupComponents()){ backup.InitializeForBackup(null); using (IVssAsync async = backup.GatherWriterMetadata()){ async.Wait(); async.Dispose(); } if (OperatingSystemInfo.IsAtLeast(OSVersionName.WindowsServer2003)) { // The only context supported on Windows XP is VssSnapshotContext.All //backup.SetContext(VssSnapshotContext.Backup); backup.SetContext(VssSnapshotContext.AppRollback | VssSnapshotContext.All); } //backup.SetBackupState(false, true, VssBackupType.Full, false); //Guid snapID = backup.StartSnapshotSet(); //backup.AddToSnapshotSet(@"C:\"); foreach (IVssExamineWriterMetadata writer in backup.WriterMetadata) { VSSSnapshot s = new VSSSnapshot(); s.Path = writer.WriterName; s.Type = (writer.Source == VssSourceType.TransactedDB || writer.Source == VssSourceType.NonTransactedDB)? "VSSDB" : "VSSWriter"; s.Version = writer.Version.Major + "." + writer.Version.Minor + "." + writer.Version.MajorRevision + "." + writer.Version.MinorRevision + writer.Version.Revision; s.MountPoint = writer.WriterName; foreach (IVssWMComponent cmp in writer.Components) { VSSSnapshot childS = new VSSSnapshot(); childS.Path = cmp.ComponentName; childS.Icon = cmp.GetIcon(); childS.Type = (cmp.Type == VssComponentType.Database)? "VSSDB" : "VSSFileGroup"; if (!cmp.Selectable) { childS.Type = "spoDisabled"; } childS.MountPoint = cmp.LogicalPath; childS.Disabled = true; if (OperatingSystemInfo.IsAtLeast(OSVersionName.WindowsServer2003)) { foreach (VssWMDependency dep in cmp.Dependencies) { Logger.Append(Severity.INFO, "TODO: vss component " + cmp.ComponentName + " has dependancy on " + dep.ComponentName); } } if (cmp.Selectable) { childS.Disabled = false; } s.AddChildComponent(childS); } alreadyExisting.Add(s); } //backup.QueryProviders foreach (IVssWriterComponents wc in backup.WriterComponents) { foreach (IVssComponent c in wc.Components) { VSSSnapshot s = new VSSSnapshot(); s.Path = c.ComponentName; s.Type = c.ComponentType.ToString(); alreadyExisting.Add(s); } } } return(alreadyExisting); }
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> /// Create the actual snapshot. This process can take around 10s. /// </summary> public void Copy() { using (IVssAsync async = _backup.DoSnapshotSet()) async.Wait(); }