Programmatically restoring files from a Volume Shadow Copy

Background:


A specific file has been corrupted on many home directories.
Within a Volume Shadow Copy backup is a good copy of the file.


The corruption is easy to detect, but how do you code something
to automatically go through previous versions on multiple servers.


Here are my findings with some snippets of C# to help.


Command Line:


When you open a previous version, explorer shows the date in brackets:
\\server\folder (‎01 February ‎2013, ‏‎12:34)


But try that same path in the command line or code and it will fail.
Shift Right Click on a folder, 'Open command window here' and you get:
Z:\@GMT-2013.02.01-12.34.56\folder\


Using a VSS time in a file path:


That @GMT path can go anywhere you would expect a directory, for example:
\\server\@GMT-2013.02.01-12.34.56\folder\file.txt
\\server\folder\@GMT-2013.02.01-12.34.56\file.txt
Both shares go to the same place, providing a copy the previous version.


Finding a valid VSS date and time:


The GMT/UTC path has to be the exact moment the 'Shadow Copy' was started.


Tests showed the starting seconds varied daily, even the starting hour changed
as the VSS schedule was local time and 'daylight savings' had taken effect.
In short, using the schedule and guessing paths was not going to be practical.


As a starting point I found the command line: VSSAdmin List Shadows
But this has no remote parameter, gave local time, and would require parsing.


Remote WMI query to rescue:


Using "SELECT * FROM Win32_ShadowCopy" and the "InstallDate" property you can
get a list of shadow start times, but they need converting from local time:


var dmtf = wmiProperty["InstallDate"].ToString();
var vssTime = ManagementDateTimeConverter.ToDateTime(dmtf).ToUniversalTime();


WMI results can be returned in any order and we want the newest shadow first, so we put the query results into a list and date sort descending:


vssTimeList.Sort((a, b) => b.CompareTo(a));


The dates can then be converted into a usable directory path format:


var vssPath = "@GMT-" + vssTime.ToString("yyyy.MM.dd-H.mm.ss");


Using the VSS paths:


The shadow times returned are for ALL drives on the server, so when looping
through the times and combining them into a share path, some may be invalid
when the time is for a shadow on another drive.

Leave a Reply

Your email address will not be published. Required fields are marked *

FOOTER TO GO HERE!