AlphaVSS is a Dot.NET class library providing a managed API for the Volume Shadow Copy Service (VSS). AlphaVSS is written in C# and C++/CLI and released under the MIT license. AlphaVSS duplicates the original VSS API (quite closely) and act as a wrapper to the VSS API for the use of Dot.Net developing.
In this blog I will show and explain the basic use of AlphaVSS, using several examples, ordered from the simple to the more complex ones. Please review the code thoroughly from the first code to last. Explanations and clarifications in the code and mast be reading from the first example.
use the search on-line option and look for alphavss. Install the package.
// Getting information on the files to copy (This is not part of the VSS action)
String _Source1 = @
"C:\_ISUG_VSS_DB\20140106_ISUG_VSS_DB.mdf"
;
String _Source2 = @
"C:\_ISUG_VSS_DB\20140106_ISUG_VSS_DB_log.ldf"
;
String _Destination = @
"V:\QQ"
;
FileInfo MyFileInfo =
new
FileInfo(_Source1);
String _Volume = MyFileInfo.Directory.Root.Name;
// VSS step 1: Initialize
IVssImplementation _vssImplementation = VssUtils.LoadImplementation();
IVssBackupComponents _backup = _vssImplementation.CreateVssBackupComponents();
_backup.InitializeForBackup(
null
);
// VSS step 2: Getting Metadata from all the VSS writers
_backup.GatherWriterMetadata();
// VSS step 3: VSS Configuration
_backup.SetContext(VssVolumeSnapshotAttributes.Persistent | VssVolumeSnapshotAttributes.NoAutoRelease);
_backup.SetBackupState(
false
,
true
, 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 (Here come the name "Volume Shadow-Copy")
// For each file that we nee to copy we have to make sure that the propere volume is in the "Snapshot Set"
Guid MyGuid01 = _backup.StartSnapshotSet();
Guid MyGuid02 = _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!
/***********************************/
// 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,
* Therefor, 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
/***********************************/
_backup.ExposeSnapshot(MyGuid02,
null
, VssVolumeSnapshotAttributes.ExposedLocally,
"L:"
);
// VSS step 8: Copy Files!
/***********************************
/* Now we start to copy the files/folders/disk!
/* Execution time can depend on what we are copying
/* We can copy one element or several element.
/* As long as we are working under the same snapshot,
/* the element should be in consist state from the same point-in-time
/***********************************/
String sVSSFile1 = _Source1.Replace(_Volume, @
"L:\"
);
String sVSSFile2 = _Source2.Replace(_Volume, @
"L:\"
);
if
(File.Exists(sVSSFile1))
System.IO.File.Copy(sVSSFile1, _Destination + @
"\"
+ System.IO.Path.GetFileName(_Source1),
true
);
if
(File.Exists(sVSSFile2))
System.IO.File.Copy(sVSSFile2, _Destination + @
"\"
+ System.IO.Path.GetFileName(_Source2),
true
);
// VSS step 9: Delete the snapshot (using the Exposed Snapshot name)
foreach
(VssSnapshotProperties prop
in
_backup.QuerySnapshots())
{
if
(prop.ExposedName == @
"L:\"
)
{
Console.WriteLine(
"prop.ExposedNam Found!"
);
_backup.DeleteSnapshot(prop.SnapshotId,
true
);
}
}
_backup =
null
;
Console.WriteLine(
"END OK. Click any Key to close the application"
);
Console.ReadLine();
At this time as I know, there is no built-in NuGet package for Dot.Net framework lower then version 4. that is not a problem :-) At the project web site we can download the code and compile it for any version we want, or we can download a DLL libraries prepared for different versions of Dot.Net.
* On the new windows chose "Browse..." button.
This code use several small upgrades. let's start with the code first and I will add some example latter on....
Module
mMain
Private
Declare
Auto
Function
CopyFileEx
Lib
"kernel32.dll"
(
ByVal
lpExistingFileName
As
String
,
ByVal
lpNewFileName
As
String
,
ByVal
lpProgressRoutine
As
CopyProgressRoutine_Delegate,
ByVal
lpData
As
Int32,
ByVal
lpBool
As
Int32,
ByVal
dwCopyFlags
As
Int32)
As
Integer
Private
Delegate
Function
CopyProgressRoutine_Delegate(
ByVal
totalFileSize
As
Long
,
ByVal
totalBytesTransferred
As
Long
,
ByVal
streamSize
As
Long
,
ByVal
streamBytesTransferred
As
Long
,
ByVal
dwStreamNumber
As
Int32,
ByVal
dwCallbackReason
As
Int32,
ByVal
hSourceFile
As
Int32,
ByVal
hDestinationFile
As
Int32,
ByVal
lpData
As
Int32
)
As
Long
Private
m_oCPR
As
CopyProgressRoutine_Delegate
Sub
Main()
'
' Display Setting
Console.BackgroundColor = ConsoleColor.White
Console.Clear()
Console.SetWindowSize(90, 30)
Console.SetWindowPosition(0, 0)
Console.ForegroundColor = ConsoleColor.DarkGreen
' Prevent example from ending if CTL+C is pressed.
Console.TreatControlCAsInput =
True
StartPoint:
Console.Clear()
Console.WriteLine(
"*******************************************************************"
)
Console.WriteLine(
"** **"
)
Console.WriteLine(
"** Greetings, **"
)
Console.WriteLine(
"** **"
)
Console.WriteLine(
"** This small app is only for primary basic Testing **"
)
Console.WriteLine(
"** of VSS using Dot.Net Technology **"
)
Console.WriteLine(
"** The app is base on the AlphaVSS open project: **"
)
Console.Write(
"** "
)
Console.ForegroundColor = ConsoleColor.Blue
Console.ForegroundColor = ConsoleColor.DarkGreen
Console.WriteLine(
" **"
)
Console.WriteLine(
"** **"
)
Console.WriteLine(
"** The application is designed only for internal purposes!! **"
)
Console.WriteLine(
"** In no way use on production servers. **"
)
Console.Write(
"** "
)
Console.ForegroundColor = ConsoleColor.DarkRed
Console.Write(
"Any use is at your own risk!!!"
)
Console.ForegroundColor = ConsoleColor.DarkGreen
Console.WriteLine(
" **"
)
Console.WriteLine(
"** **"
)
Console.WriteLine(
"** Have Fun, **"
)
Console.WriteLine(
"** Ariely Ronen **"
)
Console.WriteLine(
"** ____________________________________________________________ **"
)
Console.WriteLine(
"** **"
)
Console.WriteLine(
"** Do you want to start the TEST **"
)
Console.WriteLine(
"** by selecting the file you want to copy? (y/n) **"
)
Console.WriteLine(
"** **"
)
Console.WriteLine(
"*******************************************************************"
)
Dim
MyConsoleKeyInfo
As
ConsoleKeyInfo
MyConsoleKeyInfo = Console.ReadKey()
If
Not
(MyConsoleKeyInfo.Key.ToString() =
"Y"
)
Then
Return
SelectFileToCopy:
Console.Clear()
Console.Write(
"Starting Test Ver 0.01"
)
Dim
sDestFolder
As
New
FolderBrowserDialog
Dim
sDestFolderPath
As
String
sDestFolder.Description =
"Select a destination folder (where the file will be copy to)."
' Do not show the button for new folder
sDestFolder.ShowNewFolderButton =
False
Dim
dlgResult
As
DialogResult = sDestFolder.ShowDialog()
If
dlgResult = Windows.Forms.DialogResult.OK
Then
sDestFolderPath = sDestFolder.SelectedPath
Else
sDestFolderPath = My.Computer.FileSystem.SpecialDirectories.MyDocuments.ToString()
End
If
Dim
oOFD
As
New
OpenFileDialog
Dim
sFileName
As
String
' copy progress handler
' we add the function "CopyProgressRoutine" to the Delegate "CopyProgressRoutine_Delegate"
' so every time the event come the function run
m_oCPR =
New
CopyProgressRoutine_Delegate(
AddressOf
CopyProgressRoutine)
oOFD.ValidateNames =
False
oOFD.Title =
"Select an in-use file you would like to copy."
oOFD.Filter =
"All files (*.*)|*.*"
If
oOFD.ShowDialog = DialogResult.OK
Then
sFileName = oOFD.FileName
Console.Clear()
Console.WriteLine(
"File to Copy: "
)
Console.WriteLine(sFileName)
Console.WriteLine()
Console.WriteLine(
"The file will be copy to:"
)
Console.WriteLine(sDestFolderPath)
Console.WriteLine()
Console.WriteLine(
"Press any key to continue."
)
Console.ReadKey()
Console.Clear()
' Lets Start to copy
PerformVSSCopy(sFileName, sDestFolderPath)
End
If
Console.WriteLine()
Console.WriteLine(
"Press 1 to go to Start Point,2 to go to Select new File To Copy, any other key to exit."
)
MyConsoleKeyInfo = Console.ReadKey()
Select
Case
MyConsoleKeyInfo.Key.ToString()
Case
"D1"
GoTo
StartPoint
Case
"D2"
GoTo
SelectFileToCopy
Case
Else
End
Select
End
Sub
Private
Function
CopyProgressRoutine(
ByVal
totalFileSize
As
Long
,
ByVal
totalBytesTransferred
As
Long
,
ByVal
streamSize
As
Long
,
ByVal
streamBytesTransferred
As
Long
,
ByVal
dwStreamNumber
As
Int32,
ByVal
dwCallbackReason
As
Int32,
ByVal
hSourceFile
As
Int32,
ByVal
hDestinationFile
As
Int32,
ByVal
lpData
As
Int32
)
As
Int32
Dim
dPerc
As
Double
= 100
If
totalFileSize <> 0
Then
dPerc = (totalBytesTransferred / totalFileSize) * 100
Console.CursorLeft = 0
Console.Write(
"Copied "
& totalBytesTransferred &
" of "
& totalFileSize &
" ["
& Format(dPerc,
"0.0"
) &
"%]"
)
End
Function
Private
Sub
PerformVSSCopy(
ByVal
sFilename
As
String
,
ByVal
sDestFolder
As
String
)
' Based on the documention from
' and the help of those on
' The parts I have marked and INFO ONLY are not required for the
' VSS Copy to work, they just give insight into the process
Dim
oVSSImpl
As
Alphaleonis.Win32.Vss.IVssImplementation
Dim
oVSS
As
Alphaleonis.Win32.Vss.IVssBackupComponents
Dim
sVolume
As
String
Dim
oFI
As
New
IO.FileInfo(sFilename)
Dim
gSnapshot
As
Guid
Dim
gSnapshotSet
As
Guid
Dim
sVSSFile
As
String
Dim
sDestFile
As
String
Dim
oProps
As
Alphaleonis.Win32.Vss.VssSnapshotProperties
Try
' Load the Implementation specifi for this machine i.e Windowx XP , Vista, 32 or 64 Bit
oVSSImpl = Alphaleonis.Win32.Vss.VssUtils.LoadImplementation()
' This is the main man for VSS Backups.
Console.WriteLine(
"Initializing VssBackupComponents Object"
)
oVSS = oVSSImpl.CreateVssBackupComponents
oVSS.InitializeForBackup(
Nothing
)
' Tell VSS that we are requesting a backup with particular options
Console.WriteLine(
"Setting Backup State"
)
oVSS.SetBackupState(
False
,
True
, Alphaleonis.Win32.Vss.VssBackupType.Full,
False
)
' Tell all VSS Writers that we want their MetaData. We wait until all Writers have responded.
Console.WriteLine(
"Gat Writers Metadata"
)
Using async
As
Alphaleonis.Win32.Vss.IVssAsync = oVSS.GatherWriterMetadata()
async.Wait()
End
Using
' INFO ONLY : Enumerate who responded to our GatherWriterMetadata request
' Create the Snapshot Set that we will place all our Snapshotted volumes into. (even tho here will only snapshot one volume)
Console.WriteLine(
"Starting Snapshot Set"
)
gSnapshotSet = oVSS.StartSnapshotSet()
' Add a Snapshot for the required Volume
sVolume = oFI.Directory.Root.Name
Console.WriteLine(
"Add To Snapshot Set the Volume: "
& sVolume)
gSnapshot = oVSS.AddToSnapshotSet(sVolume, Guid.Empty)
' Notify all VSS Writers that the backup is about to start, we wait untuil they have indicated they are ready.
Console.WriteLine(
"VSS Writers Prepare For Backup ."
)
Using async
As
Alphaleonis.Win32.Vss.IVssAsync = oVSS.PrepareForBackup()
async.Wait()
End
Using
'Request that the Snapshot are created and wait until they are ready.
Console.WriteLine(
"Do Snapshot Set [this can take some time]"
)
Using async
As
Alphaleonis.Win32.Vss.IVssAsync = oVSS.DoSnapshotSet
async.Wait()
End
Using
' --------------------------------------------------------------
' --------------------------------------------------------------
' Now we can start copying the file.
' --------------------------------------------------------------
' We need the properties to tell us how to access our files in the snapshot
oProps = oVSS.GetSnapshotProperties(gSnapshot)
sVSSFile = sFilename.Replace(sVolume, oProps.SnapshotDeviceObject &
"\"
)
sDestFile = IO.Path.Combine(sDestFolder, IO.Path.GetFileName(sFilename))
' INFO ONLY Lets check the Properties of the snapshot set
' Copy, but the normal .NET routines will not work here. Back to the API !!!
Console.WriteLine(
"Copying file using API Routines."
)
Console.WriteLine()
CopyFileEx(sVSSFile, sDestFile, m_oCPR, 0, 0, 0)
Console.WriteLine()
Console.WriteLine(
"Done !"
)
' --------------------------------------------------------------
' --------------------------------------------------------------
' Release the snapshot set, we could also just call Dispose on the VssBackupComponents object
' For clarity, I'll do both here.
Console.WriteLine(
"Deleting Snapshot Set."
)
oVSS.DeleteSnapshotSet(gSnapshotSet,
True
)
Catch
ex
As
Exception
Console.WriteLine()
Console.WriteLine(ex.Message)
Console.WriteLine(ex.StackTrace)
Console.WriteLine()
Finally
oVSS.Dispose()
End
Try
End
Sub
'''
''' Determines if we can use the usual file operations to copy this file. I.E It is not a locked or inaccessbile file.
'''
'''
'''
Private
Function
CanOpenFileNormaly(
ByVal
sFileName
As
String
)
As
Boolean
Dim
bRet
As
Boolean
Dim
oStr
As
IO.FileStream
Try
oStr =
New
IO.FileStream(sFileName, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read)
oStr.Close()
bRet =
True
Catch
ex
As
Exception
bRet =
False
End
Try
Return
bRet
End
Function
End
Module
I do not remember where i got them. It is highly recommended to adjust this code for the new Version of AlphaVSS.
.
.