我正在尝试使用网站alphavss上提供的示例代码。我正在尝试包含 VssBackup.cs 类,然后在我的程序中使用它。很可能我错过了一个 dll 引用,但我在使用组件时没有收到任何错误。任何人都知道问题可能是什么?
我收到 3 个错误:
找不到类型或命名空间名称“快照”(您是否缺少 using 指令或程序集引用?)
Snapshot _snap;
找不到类型或命名空间名称“IVssAsync”(您是否缺少 using 指令或程序集引用?
using (IVssAsync async = _backup.GatherWriterMetadata())
{.......
找不到类型或命名空间名称“快照”(您是否缺少 using 指令或程序集引用?)
_snap = new Snapshot(_backup);
类 ** VssBackup.cs站点提供的 C# 示例代码**
/* Copyright (c) 2008-2012 Peter Palotas
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#region Copyright Notice
/*
* AlphaVSS Sample Code
* Written by Jay Miller
*
* This code is hereby released into the public domain, This applies
* worldwide.
*/
#endregion
using System;
using System.Diagnostics;
using System.Collections.Generic;
using Alphaleonis.Win32.Vss;
using Alphaleonis.Win32.Filesystem;
namespace VssSample
{
/// <summary>
/// This class encapsulates some simple VSS logic. Its goal is to allow
/// a user to backup a single file from a shadow copy (presumably because
/// that file is otherwise unavailable on its home volume).
/// </summary>
/// <example>
/// This code creates a shadow copy and copies a single file from
/// the new snapshot to a location on the D drive. Here we're
/// using the AlphaFS library to make a full-file copy of the file.
/// <code>
/// string source_file = @"C:\Windows\system32\config\sam";
/// string backup_root = @"D:\Backups";
/// string backup_path = Path.Combine(backup_root,
/// Path.GetFilename(source_file));
///
/// // Initialize the shadow copy subsystem.
/// using (VssBackup vss = new VssBackup())
/// {
/// vss.Setup(Path.GetPathRoot(source_file));
/// string snap_path = vss.GetSnapshotPath(source_file);
///
/// // Here we use the AlphaFS library to make the copy.
/// Alphaleonis.Win32.Filesystem.File.Copy(snap_path, backup_path);
/// }
/// </code>
/// This code creates a shadow copy and opens a stream over a file
/// on the new snapshot volume.
/// <code>
/// string source_file = @"C:\Windows\system32\config\sam";
///
/// // Initialize the shadow copy subsystem.
/// using (VssBackup vss = new VssBackup())
/// {
/// vss.Setup(Path.GetPathRoot(filename));
///
/// // We can now access the shadow copy by either retrieving a stream:
/// using (Stream s = vss.GetStream(filename))
/// {
/// Debug.Assert(s.CanRead == true);
/// Debug.Assert(s.CanWrite == false);
/// }
/// }
/// </code>
/// </example>
public class VssBackup : IDisposable
{
/// <summary>
/// Setting this flag to true will enable 'component mode', which
/// does not, in this example, do much of any substance.
/// </summary>
/// <remarks>
/// VSS has the ability to selectively disable VSS-compatible
/// components according to the specifics of the current backup. One
/// might, for example, only quiesce Outlook if only the Outlook PST
/// file is intended to be backed up. The ExamineComponents() method
/// provides a framework for this sort of mode if you're interested.
/// Otherwise, this example code quiesces all VSS-compatible components
/// before making its shadow copy.
/// </remarks>
bool ComponentMode = false;
/// <summary>A reference to the VSS context.</summary>
IVssBackupComponents _backup;
/// <summary>Some persistent context for the current snapshot.</summary>
Snapshot _snap;
/// <summary>
/// Constructs a VssBackup object and initializes some of the necessary
/// VSS structures.
/// </summary>
public VssBackup()
{
InitializeBackup();
}
/// <summary>
/// Sets up a shadow copy against the specified volume.
/// </summary>
/// <remarks>
/// This methods is separated out from the constructor because if it
/// throws, we still want the Dispose() method to be called.
/// </remarks>
/// <param name="volumeName">Name of the volume to copy.</param>
public void Setup(string volumeName)
{
Discovery(volumeName);
PreBackup();
}
/// <summary>
/// The disposal of this object involves sending completion notices
/// to the writers, removing the shadow copies from the system and
/// finally releasing the BackupComponents object. This method must
/// be called when this class is no longer used.
/// </summary>
public void Dispose()
{
try { Complete(true); } catch { }
if (_snap != null)
{
_snap.Dispose();
_snap = null;
}
if (_backup != null)
{
_backup.Dispose();
_backup = null;
}
}
/// <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();
}
}
/// <summary>
/// This stage involes the requester (us, again) processing the
/// information it received from writers on the system to find out
/// which volumes - if any - must be shadow copied to perform a full
/// backup.
/// </summary>
void Discovery(string fullPath)
{
if (ComponentMode)
// In component mode, we would need to enumerate through each
// component and decide whether it should be added to our
// backup document.
ExamineComponents(fullPath);
else
// Once we are finished with the writer metadata, we can dispose
// of it. If we were in component mode, we would want to keep it
// around so that we could notify the writers of our success or
// failure when we finish the backup.
_backup.FreeWriterMetadata();
// Now we use our helper class to add the appropriate volume to the
// shadow copy set.
_snap = new Snapshot(_backup);
_snap.AddVolume(Path.GetPathRoot(fullPath));
}
/// <summary>
/// This method is optional in this implementation, and in fact does
/// nothing of substance. It does demonstrate how one might parse
/// through the various writers on the system and add them to the
/// backup document if necessary.
/// </summary>
/// <param name="fullPath">The full path of the file to back up.</param>
void ExamineComponents(string fullPath)
{
// At this point it is the requester's duty to examine what the
// writers have prepared for us. The WriterMetadata property
// (in place of the C API's 'GetWriterMetadata' function) collects
// metadata from each writer behind a list interface.
IList<IVssExamineWriterMetadata> writer_mds = _backup.WriterMetadata;
// If you receive a "bad state" error when enumerating, you might
// have a registry inconsistency from a program that improperly
// uninstalled itself. If your event log is showing an error like,
// "ContentIndexingService called routine RegQueryValueExW which
// failed," you'll want to read Microsoft's KB article #907574.
foreach (IVssExamineWriterMetadata metadata in writer_mds)
{
// We can see the name of the writer, if we like.
Trace.WriteLine("Examining metadata for " + metadata.WriterName);
// The important bit of the writers' metadata is the list of
// components each writer is broken into. These components are
// responsible for some number of files, so going through this
// data allows us to construct an initial list of files for our
// shadow copies.
foreach (IVssWMComponent cmp in metadata.Components)
{
// Print out some info for each component.
Trace.WriteLine(" Component: " + cmp.ComponentName);
Trace.WriteLine(" Component info: " + cmp.Caption);
// If a component is available for backup, it's then up to us to
// decide whether it is relevant to the current backup. To do
// this, we may examine the files each component manages.
foreach (VssWMFileDescription file in cmp.Files)
{
// The idea here is to find out whether these files are
// relevant to whatever purpose your application holds. If
// they are, you should a) add this component to your backup
// set so VSS involves it in the shadow copy operation, and
// b) record the files' volume names so you know later which
// volumes need to be shadow copied.
// I'm not worried about that stuff for this example, though,
// so instead I'm printing out the stuff you might need to
// examine if you have requirements of that sort.
Trace.WriteLine(" Path: " + file.Path);
Trace.WriteLine(" Spec: " + file.FileSpecification);
// Here we might insert some logic to:
//
// 1. Check whether the AlternateLocation property is valid.
// 2. Expand environment vairables in either Path.or
// AlternateLocation, as appropriate.
// 3. Considering the FileSpecification and the IsRecursive
// properties, decide whether this component manages
// the file(s) you wish to backup (in this case, the
// fullPath argument).
//
// If this component is relevant, add it with AddComponent().
// (The FileToPathSpecification method below might help with
// some of these steps.)
}
}
}
}
/// <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();
}
/// <summary>
/// This simple method uses a bit of string manipulation to turn a
/// full, local path into its corresponding snapshot path. This
/// method may help users perform full file copies from the snapsnot.
/// </summary>
/// <remarks>
/// Note that the System.IO methods are not able to access files on
/// the snapshot. Instead, you will need to use the AlphaFS library
/// as shown in the example.
/// </remarks>
/// <example>
/// This code creates a shadow copy and copies a single file from
/// the new snapshot to a location on the D drive. Here we're
/// using the AlphaFS library to make a full-file copy of the file.
/// <code>
/// string source_file = @"C:\Windows\system32\config\sam";
/// string backup_root = @"D:\Backups";
/// string backup_path = Path.Combine(backup_root,
/// Path.GetFilename(source_file));
///
/// // Initialize the shadow copy subsystem.
/// using (VssBackup vss = new VssBackup())
/// {
/// vss.Setup(Path.GetPathRoot(source_file));
/// string snap_path = vss.GetSnapshotPath(source_file);
///
/// // Here we use the AlphaFS library to make the copy.
/// Alphaleonis.Win32.Filesystem.File.Copy(snap_path, backup_path);
/// }
/// </code>
/// </example>
/// <seealso cref="GetStream"/>
/// <param name="localPath">The full path of the original file.</param>
/// <returns>A full path to the same file on the snapshot.</returns>
public string GetSnapshotPath(string localPath)
{
Trace.WriteLine("New volume: " + _snap.Root);
// This bit replaces the file's normal root information with root
// info from our new shadow copy.
if (Path.IsPathRooted(localPath))
{
string root = Path.GetPathRoot(localPath);
localPath = localPath.Replace(root, String.Empty);
}
string slash = Path.DirectorySeparatorChar.ToString();
if (!_snap.Root.EndsWith(slash) && !localPath.StartsWith(slash))
localPath = localPath.Insert(0, slash);
localPath = localPath.Insert(0, _snap.Root);
Trace.WriteLine("Converted path: " + localPath);
return localPath;
}
/// <summary>
/// This method opens a stream over the shadow copy of the specified
/// file.
/// </summary>
/// <example>
/// This code creates a shadow copy and opens a stream over a file
/// on the new snapshot volume.
/// <code>
/// string source_file = @"C:\Windows\system32\config\sam";
///
/// // Initialize the shadow copy subsystem.
/// using (VssBackup vss = new VssBackup())
/// {
/// vss.Setup(Path.GetPathRoot(filename));
///
/// // We can now access the shadow copy by either retrieving a stream:
/// using (Stream s = vss.GetStream(filename))
/// {
/// Debug.Assert(s.CanRead == true);
/// Debug.Assert(s.CanWrite == false);
/// }
/// }
/// </code>
/// </example>
public System.IO.Stream GetStream(string localPath)
{
// GetSnapshotPath() returns a very funky-looking path. The
// System.IO methods can't handle these sorts of paths, so instead
// we're using AlphaFS, another excellent library by Alpha Leonis.
// Note that we have no 'using System.IO' at the top of the file.
// (The Stream it returns, however, is just a System.IO stream.)
return File.OpenRead(GetSnapshotPath(localPath));
}
/// <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 method takes the information in a file description and
/// converts it to a full path specification - with wildcards.
/// </summary>
/// <remarks>
/// Using the wildcard-to-regex library found at
/// http://www.codeproject.com/KB/string/wildcmp.aspx on the
/// output of this method might be very helpful.
/// </remarks>
/// <param name="file">Object describing a component's file.</param>
/// <returns>
/// Returns a full path, potentially including DOS wildcards. Eg.
/// 'c:\windows\config\*'.
/// </returns>
string FileToPathSpecification(VssWMFileDescription file)
{
// Environment variables (eg. "%windir%") are common.
string path = Environment.ExpandEnvironmentVariables(file.Path);
// Use the alternate location if it's present.
if (!String.IsNullOrEmpty(file.AlternateLocation))
path = Environment.ExpandEnvironmentVariables(
file.AlternateLocation);
// Normalize wildcard usage.
string spec = file.FileSpecification.Replace("*.*", "*");
// Combine the file specification and the directory name.
return Path.Combine(path, file.FileSpecification);
}
}
}