Announcing HoboCopy

CraigBlog

Syndication

For a while now, I've been unhappy with the state of my backup strategy. I have a simple script that runs ntbackup every night on a rotating, 14-day schedule: one full backup followed by six incremental backups, then repeat with a different target. In this way, I can always recover to any day in (at least) the last week.
 
So why am I unhappy? Two reasons:
 
  1. ntbackup isn't exactly robust - I've seen all sorts of failures, and restoring files is sort of flaky.
  2. ntbackup locks its information up in a proprietary format. I just want my files, dammit, not some .bks file.
 
Being a cheap bastard with decent programming skills, I started looking at what it would take to wire up my own solution. I thought about using robocopy, the king of copy tools. But it has one major drawback: it can't copy any files that are locked by another program. Some of my friends solve this problem by shutting down all their programs every night, but I knew that there was no way I (or my wife) was going to remember to do that, and of course the one time I'd forget was the day my hard drive would tank. Plus, what about programs like SQL Server that I don't want to ever shut down?
 
Obviously, it's possible to copy files that are in use. After all, ntbackup does it. So I started poking around, and came across VSS. The good VSS (Volume Shadow Service), not the unbelievably crappy one (Visual Source Safe). The Volume Shadow Service is a very cool piece of Windows XP/2003 that lets you "snapshot" a hard drive, creating what's essentially a point-in-time image of what's on the disk. You can then copy files from that image at your leisure. Better, it's done in an efficient manner, so that it doesn't actually copy anything unless someone does a write, and even then it only copies at a block level. Which is good, because otherwise you'd need 50GB free to snapshot 50GB of data.
 
But it's even better than that. VSS includes an API that programs like SQL Server 2005 can use to find out when a snapshot is about to occur. When so notified, VSS-aware programs can flush their state to disk, so you get a consistent backup. Of course, not every program is aware of VSS. For those, you get what the docs call a "crash consistent" snapshot. Translation: whatever the hell was on the disk. In my book, that's still better than not backing up at all. After all, my computer seems to do just fine after a BSOD, which is no different.
 
Armed with the Platform SDK docs, I set out to achieve my goal of a VSS-based backup utility. I would have liked to have used robocopy to do the copy, but I couldn't get it to copy using source paths like \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\data\backup\SmtpSend\Properties\Resources.resx,
which how you get to the files in the snapshot.
 
Next, I tried to write a managed tool that would do the copy. That wouldn't have been too bad - recursive file copy is pretty simple to implement. Unfortunately, the VSS API is completely broken for CLR interop - the main object you need to access implements one COM interface,  IVssBackupComponents. But if you try to query that object for that interface, it returns E_NOINTERFACE. Which is wrong, wrong, wrong. And also means that there's no way to use the object from straight managed code.
 
So I decided to write the tool in unmanaged C++. Maybe I could have done it in managed C++, or a combination of C++ and C#, but in the end I decided to make this a project that would help me get a little rust off my C++ skills. Plus, the documentation suggests that paths starting with \\?\GLOBALROOT aren't safe to use from managed code, although it worked fine when I tested it. The end result is HoboCopy. You pass it a source directory and a destination directory, and it makes a recursive copy using VSS. I've run it against my entire hard drive, and it's able to copy everything except files I didn't have permission to copy (e.g. some stuff under Documents and Settings), and for those situations I've got the /skipdenied switch. Some day I'll add a switch that enables the SE_BACKUP privilege to make that behavior even better. Unless one of you wants to submit a patch. :)
 
Speaking of patches. As of now, the project is hosted at SourceForge under the MIT license, so have at it! (Make sure you download the right one - there are separate binaries for XP and W2K3.) Just go easy on me if you look at the source - it's been years since I wrote much C++. :)

Posted Sep 20 2006, 06:54 AM by craig-andera

Comments

DuncanS wrote re: Announcing HoboCopy
on 09-20-2006 7:51 AM
Hmmnn, I got the interop to work, you use the VSSCoordinatorClass class:


VSS.VSSCoordinator vss = new VSS.VSSCoordinatorClass();

vss.StartSnapshotSet(out snapshotSetID);
vss.AddToSnapshotSet(this.VolumeName, Guid.Empty, out _snapshotID);

VSS.IVssAsync vssAync;
object callback = null;
vss.DoSnapshotSet(callback, out vssAync);
vss.DoSnapshotSet(callback, out vssAync);

while(true)
{
int hr, x=0;
vssAync.QueryStatus(out hr, ref x);
Console.Write(".");
if((AsyncStatus)hr == AsyncStatus.Finished)
break;
Thread.Sleep(1000);
}

VSS._VSS_SNAPSHOT_PROP snapshotProps;
vss.GetSnapshotProperties(_snapshotID, out snapshotProps);
_snapshotDeviceName = snapshotProps.m_pwszSnapshotDeviceObject;

...
Haacked wrote re: Announcing HoboCopy
on 09-20-2006 8:16 AM
Dang you're cheap. You couldn't just by Achronos?

Cool stuff though!
Haacked wrote re: Announcing HoboCopy
on 09-20-2006 8:25 AM
http://www.genie-soft.com/ does zip backup.
Craig wrote re: Announcing HoboCopy
on 09-20-2006 8:59 AM
Ah! Didn't know about the coordinator class...where were you two months ago!? :) Thanks for the heads-up, though. Maybe I'll switch it to work managed some day.

And yes, I am cheap. :)
Craig wrote re: Announcing HoboCopy
on 09-20-2006 9:05 AM
Wait - where did you find VSSCoordinator? I only see one pretty worthless hit on it on Google...
Craig wrote re: Announcing HoboCopy
on 09-20-2006 12:03 PM
OK, found it. It's right there in the registry. :)

I'm still not 100% sure this would work - as I said I found some sort of warning about using interop to copy files out of the \\?\GLOBALROOT namespace. But if it does work, it sure as hell would be easier than what I'm doing now.
Jason Haley wrote Interesting Finds: September 20, 2006
on 09-20-2006 7:31 PM
Eric Bowen wrote re: Announcing HoboCopy
on 09-21-2006 5:47 AM
You can mount a VSS Shadow Copy as a drive letter, and then you CAN use RoboCopy (I'll try to cook up a demo on my blog).
Craig wrote re: Announcing HoboCopy
on 09-21-2006 6:28 AM
Except you can't create persistent shadow copies on XP. Otherwise that would be a great solution.
Steve Floyd wrote re: Announcing HoboCopy
on 09-22-2006 7:56 AM
FileKeeper (http://www.filekeeper.com) has nailed the continuous backup problem to the wall. Really slick instantaneous backup with right-click recovery for all versions.

I hit ^S (Save) in Word and it grabs the difference and backs it up that instant. Really cool.

Volume Shadow Service is limited to so many copies.
John McPherson wrote re: Announcing HoboCopy
on 09-25-2006 5:02 AM
Cool stuff man, I also LIKE very much the fact that you code the starting { and ending } on seperate lines, this is the same tech. that I use and it makes C, C++, C# C whatever code so much more readable...

Thanks,
Craig wrote re: Announcing HoboCopy
on 09-25-2006 5:45 PM
Steve: FileKeeper sounds cool, but at "not free" it doesn't meet my cheapness requirements. :) As for VSS being limited, the only limitation I know of is for persistent copies, which HoboCopy doesn't use.

John: glad you liked the style - writing C++ after years and years of C# was a major challenge. As it is, I find the HoboCopy code to be a real mishmash of traditional C++ and C# styles. But given that there's a COM component that gives access to the VSS API, I'll probably rewrite HoboCopy as managed code the next time I need to make significant changes - it's just soooo much easier to get work done in C#.
Jmtyra wrote re: Announcing HoboCopy
on 11-30-2006 9:08 AM
LOVE Hobocopy, this is ~exactly~ what I've been looking for. I have been using some other solutions, but never been able to backup locked/in-use files.

Awesome job Craig, you da man!! =D
Craig wrote re: Announcing HoboCopy
on 11-30-2006 9:42 AM
Glad you like it. Be warned, I've found one major bug that I've got a pending fix for. Basically, the part where it tells SQL Server (or whatever other writers) that a snapshot is about to occur is wrong in the publicly released version. Straight file copying still works, but you're going to get a "crash consistent" view of files, not a "backup consistent" one. I'll be releasing a new version sometime in the next few weeks to correct this.
Ken wrote re: Announcing HoboCopy
on 11-30-2006 10:57 AM
TYVM... tis almost a perfect fix for my desire for a background backup of my notebook.

I've been getting an error message when I've tried to specify a remote unc (\\server\share) as the destination. Am I doing something wrong or is this a restriction in the current version?

Thanks again!
Craig wrote re: Announcing HoboCopy
on 11-30-2006 11:47 AM
No, that's a scenario I've explicitly supported. In fact, I had to do a little extra work to make sure it works.

What error are you getting? Can you run with /loglevel=4 and send me the log?
Ken wrote re: Announcing HoboCopy
on 12-01-2006 11:34 AM
The problem was a lack of patience on my part. I had aborted a local backup copy process, and then tried to start a new one to the UNC. I've a feeling (could be wrong!) that the VSS was still processing the first request, and so hobocopy gave me an error. After playing with it some more I managed to get it working.

On another 2 notebooks however, the story is different. When I try to run the program for them I get the following error:

"The system cannot execute the specified program."

It's running from the same network share for both machines, and I get the same error when I copy the hobofiles local to the c drive. Any ideas?

<bow> thanks!

Ken
kenlowe65
at gmail dot com.
Craig wrote re: Announcing HoboCopy
on 12-01-2006 12:09 PM
ah, yes, Hobocopy is not particularly good yet at recovering from aborted errors. I believe if you wait a while, VSS will clean up after itself. A reboot will probably also do it, as will obtaining a copy of vshadow.exe and running it with -da (delete all shadow copies).

As for the "system cannot execute the specified program" error, that's a bit weird. It sounds like something important is missing. Can you point a copy of depends.exe at the EXE and see if it shows any missing dependencies? Perhaps the C runtime?

The other thing I can think of is that it might be an OS/platform thing. Are you trying to run it on a 64 bit box, or using the XP version on W2K3/Vista or vice-versa?
Ken wrote re: Announcing HoboCopy
on 12-01-2006 6:41 PM
It has worked fine on two WinXP sp2 notebooks (HP Tablet and Dell D820). It has also failed on two WinXP sp2 notebooks (a Fujitsu tablet and Toshiba portege). Very strange.

I will try the "depends.exe" and see if there is any difference between the machines on Monday.
Ken wrote re: Announcing HoboCopy
on 12-04-2006 6:08 AM
Dependency failures:
MSVCR80.dll
MSJAVA.dll
Craig wrote re: Announcing HoboCopy
on 12-05-2006 3:50 AM
MSJAVA? WTF? I'm definitely not using Java. I think you can ignore that one.

MSVCR80.dll, however, is the C Runtime. I don't know what you installed on one machine versus the other that you got the CRT one place but not the other, but that's likely it.

A little googling shows that MSVCR80.dll can be downloaded. Give it a try and see if that helps. You should just be able to drop it in the same dir as Hobocopy.exe.
Chris Wilson wrote re: Announcing HoboCopy
on 12-06-2006 2:24 PM
Hi Craig,

Thanks for writing this and making it available under the MIT license! I'm working on a backup program (Box Backup) that I want to add VSS support to, and this should help if I need sample code that's compatible with the license (unlike the VSS SDK).

I'm trying to access the methods of IVssBackupComponents by IDispatch, rather than vtable, to help users who don't have the header files and want to compile the code. However, I think that maybe VSS doesn't support IDispatch properly.

I can get an IDispatch interface from IVssBackupComponents, but when I try to get the DISPID of the AbortBackup method using GetIDsOfNames, I get the error (HRESULT) 0x8002801D, which seems to be TYPE_E_LIBNOTREGISTERED.

This is not a documented return code from GetIDsOfNames. Any ideas what I can do, if anything?

Cheers, Chris.
Chris Wilson wrote re: Announcing HoboCopy
on 12-06-2006 2:48 PM
Hi Craig,

Also, if I try to get an IDispatch interface from VSS.VSSCoordinator, CoCreateInstance returns E_NOINTERFACE. Do you know how a scripting language such as C# manages to call methods on this interface? Is there a header provided, or some other way to call methods such as StartSnapshotSet, as DuncanS seems to have managed to do from C#? (I have never programmed in C#, I'm using C++ to try to get this interface).

Cheers, Chris.
Craig wrote re: Announcing HoboCopy
on 12-07-2006 3:31 AM
First, I looked into using VssCoordinator, but it doesn't support anything like the full VSS API, so I can't use it for Hobocopy. You may or may not encounter the same limitations.

Second, there's no reason at all that VSSCoordinator has to implement IDispatch - it's completely optional. In fact, it comes with a set of restrictions that may well have been too severe for them.

Third, C# isn't a scripting language - it doesn't have to use IDispatch at all (and in fact doesn't) when calling VSSCoordinator methods.

HTH.
Chris Wilson wrote re: Announcing HoboCopy
on 12-08-2006 12:20 AM
Hi Craig,

Thanks for your answers. If C# doesn't use IDispatch, do you know how it does call methods of e.g. VSSCoordinator? Presumably it doesn't understand C++ headers? Does it use the type library and LoadRegTypeLib, ITypeInfo and Invoke? Some other mechanism?

Cheers, Chris.
Craig wrote re: Announcing HoboCopy
on 12-08-2006 3:09 AM
It simply builds vtables, which after all are pretty simple structures. It can do this by importing type library information, but that's not necessary - as long as it knows the type and order of methods and parameters, it can do the right thing, just like any other COM client.
Jack wrote re: Announcing HoboCopy
on 12-27-2006 3:11 AM
I am having the same error as Ken. I have two windows 2003 servers. One of them hobocopy works and on the other it dosen't. In a batch file it says "The system can not execute the specified program." I downloaded the MSVCR80.dll but that didn't help. I downloaded the hobocopy-0.6.0.0-w2k3-x32-release.zip. The depends had two errors, msjava.dll and msvcr80.dll. the errors in depends are gone now after downloading those two files but the program still has the same error.
Craig wrote re: Announcing HoboCopy
on 12-27-2006 5:45 AM
OK, instead of going at the DLLs piecemeal, I should have suggested installing the Visual C++ 2005 redistributable package, available here:

http://www.microsoft.com/downloads/details.aspx?familyid=32BC1BEE-A3F9-4C13-9C99-220B62A191EE&displaylang=en

Give that a shot and see if it fixes the problem. If it does, I'll start shipping it with HoboCopy. I have a new version packaged up and ready to go that I'll push out the door before too long.
Jack wrote re: Announcing HoboCopy
on 12-28-2006 2:36 AM
Wow that did fix it, thanks for all your work and a great program!
CraigBlog wrote Announcing HoboCopy 1.0.0.0
on 01-08-2007 5:36 AM
Jan wrote Run command as soon as the snapshot has been taken
on 10-05-2007 6:24 AM
Hi,

HoboCopy seems to be exactly the tool I've been looking for. I intend to use it to backup VMware virtual machine files. In order to get the VM in a consistent state, I need to suspend (pause) it and make a copy of that paused state.

I would like to use HoboCopy with its VSS capabilities to minimize downtime, i.e.

1. Suspend VM
2. Take Snapshot
3. Resume VM as soon as snapshot has been taken
4. Do the actual backup

Is there any way to know when VSS is done with taking the snapshot?

Thanks for the great app,
Jan
Craig wrote re: Announcing HoboCopy
on 10-06-2007 4:16 AM
I don't know of any way to do manually what you're asking. I suppose the easiest thing would be to modify Hobocopy so that you can give it a script that it runs before/after the snapshot. I'm not planning to spend any time on Hobocopy to do that right now, but you have the source and it shouldn't be a difficult modification.

Ideally, the way this would work is that VMWare would provide hooks into the VSS APIs that would take care of this automatically. VSS is designed specifically to allow for the exact case you describe (this is similar, for example, to what SQL Server does when you take a shadow copy) but apparently VMWare doesn't support it right now. Too bad. But when it does, hobocopy should "just work" the way you want it to.
Jan wrote re: Announcing HoboCopy
on 10-06-2007 7:38 AM
Hi Craig,

thanks for your hints on implementing it. My C++ skills are barely existent, but maybe I'll ask a friend to do it.

For why VMware Server (which I use) doesn't natively support VSS: I guess it's marketing strategy. "Server" is their free product, designed to get people hooked on virtualization. Their enterprise product, ESX, which costs quite a few Dollars, has, afair, advanced snapshot capablities (in combination with their own prorietary file system, VMFS) and there are a number of products availabled specifically designed to do live backups of VMs.

Cheers, Jan
Lee wrote re: Announcing HoboCopy
on 11-15-2007 1:14 PM
Hi,

i'm very interesting by your works, but i can't find VSSCoordinatorClass,

can you help me ?

Thanks
Craig wrote re: Announcing HoboCopy
on 11-16-2007 2:50 AM
I'm not sure where it comes from. Probably when you install the VSS SDK.
Lee wrote re: Announcing HoboCopy
on 11-16-2007 2:58 PM
I have already installed VSS SDK, but i don't know how add a reference to VSS in a .net project (i have no VSS class available in .net or com reference list).

Can u tell me where are u referenced the class in your .net project ?

sorry for my poor english language ...
Craig wrote re: Announcing HoboCopy
on 11-18-2007 3:13 AM
Actually, I'm not sure...just went looking for it, and couldn't track it down. I think it's probably a managed DLL that ships with the SDK, but I can't find it now. Sorry: been quite a while since I worked on this stuff.
Ned wrote re: Announcing HoboCopy
on 11-19-2007 10:53 PM
Hi Craig,

First - great tool! I'm trying to use this for a backup solution, and I can almost use this to reconstruct a bootable windoze HD. What I do is run Hobocopy on the entire HD (C:) to a network share. Then, I plug a new (empty) hd back in, boot off of a CD, format and copy the boot sector, mount the network share, and proceed to copy over everything to the "new" HD. When I boot, I get a number of "strange" errors. It does boot into windows, but the system is unstable and doesn't seem to work correctly. I checked the backup log, and it seems to have aborted and skipped all files in C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys, with Message "Error accessing File...Skipping". I'm also not entirely certain that the registry is copied over 100% intact. You mentioned that you use this yourself for your backups. Have you solved these problems? If so, can you share that? Thanks!
Craig wrote re: Announcing HoboCopy
on 11-20-2007 5:18 AM
I do use the tool myself, every night, on three different machines. But I don't try to back up the entire HD. It certainly seems like you're running into a simple security issue: just run Hobocopy as a user with sufficient privilege to copy all those files. Perhaps Local System?

As for the registry issue, I don't have any information on that - all Hobocopy does is create a shadow copy and then call CopyFile, so I'm not sure what it could do differently to correct any issues there...
Lee wrote re: Announcing HoboCopy
on 11-26-2007 1:12 PM
Hi Craig,

Can u tell me why Hobocopy can't make a shadow copy on one file. When i give just one file as a source parameter, hobocopy create a shadow copy because my disk is in activity. But i don't see the file in destination directory.

Thanks
Craig wrote re: Announcing HoboCopy
on 11-26-2007 4:07 PM
The usage is:

hobocopy sourcedir destdir filename

So you always have to specify two directories: the directory to copy from and the directory to copy to. You can restrict it to just one file by specifying the filename.
Lee wrote re: Announcing HoboCopy
on 11-26-2007 11:29 PM
Thanks a lot Craig, i have missing a line in your documentation ...
Rob wrote re: Announcing HoboCopy
on 12-05-2007 10:01 AM
I noticed if you try and copy a file to a unc path it the tool creates the directory structure where ever your cmd prompt location is set to. i.e. by default in xp the cmd prompt is c:\documents and settings\%username%, if you look in that directory you'll see the unc directory structure. if the dest is a drive letter it's all good.
Rob wrote re: Announcing HoboCopy
on 12-05-2007 10:03 AM
hobocopy is great though, nice job
Craig wrote re: Announcing HoboCopy
on 12-05-2007 10:36 AM
Sounds like a bug. I'll file it and if I ever get back to making improvements...