improve.dk
Just another mindless drone looking for the perfect stack
posts - 227, comments - 489

Copying a SQL Server database file that’s in use using Volume Shadow Copy

Written on June 21, 2011 by Mark S. Rasmussen in Development: .NET, SQL Server: Tricks

When working on OrcaMDF I usually setup a test database, force a checkpoint and then perform my tests on the MDF file. Problem is, you can’t open the MDF file for reading, nor copy it, as long as the database is online in SQL Server. I could shut down SQL Server temporarily while copying the file, but that quickly becomes quite a hassle.

Leveraging Volume Shadow Copy (VSS) through AlphaVSS

AlphaVSS is an excellent library for invoking VSS through .NET. While it can do much more, I’m using it to create a snapshot of a single active file, copy it and then dispose of the snapshot afterwards.

The following class presents a single static method that’ll copy any file (locked or not) and copy it to the desired destination. It would be easy to adapt upon this sample to copy multiple files, directories, etc. Note that while a copy file progress clalback is supported, I don’t really care about the progress and am there sending a null reference when calling CopyFileEx.

class VssHelper
{
	[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
	private static extern bool CopyFileEx(string lpExistingFileName, string lpNewFileName, CopyProgressRoutine lpProgressRoutine, int lpData, ref int pbCancel, uint dwCopyFlags);
	private delegate uint CopyProgressRoutine(long TotalFileSize, long TotalBytesTransferred, long StreamSize, long StreamBytesTransferred, uint dwStreamNumber, uint dwCallbackReason, IntPtr hSourceFile, IntPtr hDestinationFile, IntPtr lpData);

	public static void CopyFile(string source, string destination)
	{
		var oVSSImpl = VssUtils.LoadImplementation();

		using (var vss = oVSSImpl.CreateVssBackupComponents())
		{
			vss.InitializeForBackup(null);

			vss.SetBackupState(false, true, VssBackupType.Full, false);

			using (var async = vss.GatherWriterMetadata())
				async.Wait();

			vss.StartSnapshotSet();
			string volume = new FileInfo(source).Directory.Root.Name;
			var snapshot = vss.AddToSnapshotSet(volume, Guid.Empty);

			using (var async = vss.PrepareForBackup())
				async.Wait();

			using (var async = vss.DoSnapshotSet())
				async.Wait();

			var props = vss.GetSnapshotProperties(snapshot);
			string vssFile = source.Replace(volume, props.SnapshotDeviceObject + @"\");

			int cancel = 0;
			CopyFileEx(vssFile, destination, null, 0, ref cancel, 0);
		}
	}
}

Feedback

No comments posted yet.

Post Comment

Name  
Email
Url
Comment
Please add 6 and 3 and type the answer here: