Introduction

Microsoft's SyncToy has really been a godsend. I use it to syncrhonize files between two load balanced W2K3 servers that run websites. Despite what MS says, it also works on W2K3 as well as XP.

I had initially set it up as a scheduled task to run all by itself. However, when you do this, it must have a logged on user for the UI. This was unacceptable, and I looked for a suitable replacement... I found that there is a file installed with SyncToy called SyncToyEngine.dll. Thanks Microsoft for seperating the UI from the logic! This DLL is a .NET 2.0 assembly, so you can include it in any .NET project you want. Luckily, it didn't take too long to figure out how it worked either! Below is my code for a console application that simply calls the SyncToy APIs...

Prerequisites

Before using this code, it is assumed that you've already used the given UI to set up a folder pair. When you do this, the configuration is saved into a C:\Documents and Settings\[username]\My Documents\SyncToyData\SyncToyDirPairs.bin file. The file is actually a binary serialized object of type SyncToy.SyncEngineConfig. Again, thanks MS for making it so easy!!! Also in this directory, SyncToy stores the snapshot files of each of the left and right directories.

The code

This is optional, but DimWithEvents a SyncEngine object. This will allow you to view the events when files are moved.

DimWithEvents se1 As SyncToy.SyncEngine

Next, get the configuration. (I used a command parameter to pass this in.)

Now, you must call preview() for the API to create its own SyncActions. The preview actually looks at both files and defines what the actions are to be done, if any.

se1.Preview()

Finally, run the sync() command...

se1.Sync()

That's it! Good luck. Download the attached source file if you want a little more detail on error handling and notifying the user what's happening.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

Share

About the Author

I've been writing software applications since the early 90's from ASP and VB5 to C# and ASP.NET. I am currently working on law enforcement and criminal justice applications delivered over the web. I've always been astounded by the fact that the only 2 industries that refer to customers as "users" are narcotics and software development.

Comments and Discussions

Excellent article and code.
I have imported it into a project i have been working on successfully and have had success with it - Thanks
Quick Question - has anyone tried updating the last run datetime and have the new value display against a folder pair within the synctoy application?

There are only 10 types of person in this world
Those that understand binary and those that don’t!

Hi,
I think this code is fantastic. I am adding an additional challenge though. What if you are able to create a service that constantly listens for changes in the right and left directories, and triggers the synchronization if something changes on either side?
I accomplished this using windows service. The service reads the configuration file and puts all the pairs in listening mode, so if something changes, it immediately synchronizes accordingly. Here is the code. Feel free to update me if you find errors, I use it to synchronize my web servers.

Now that we know how to read a SyncToy config file in a variable of type "SyncToy.SyncEngineConfig" and pass it to the SyncToyEngine, does anyone know how to write a variable of type "SyncToy.SyncEngineConfig" to a config file? I can dynamically create the SyncToyEngine config and I pass it to the SyncToyEngine, but I'd like to write this config to a file and then run the SyncToy.exe -R"FolderPairName" to get the GUI interface rather than the console.

I see to read the SyncToy config file, we "deserialize" the input stream, but I can't figure out to "serialize" the output string to get it into the correct format to write to a file.

This is what I figured I would need to do, my code is almost identical to your psudeo code:
Dim sc As SyncToy.SyncEngineConfig
Dim db As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter

' set sc's properties here

db.Serialize(sc, "c:\test.dat")

When I try to compile, I get the error "Value of type 'SyncToy.SyncEngineConfig' cannot be converted to 'System.IO.Stream'" I see when we read fromthe config file, we use CTYPE to convert it to the SyncToy.SyncEngineConfig type. I can't figure out how to convert it into a serializable type.

That is because Serialize() is looking for a stream as input, not just a string representing the file path. There are many types of streams (file of course is one of them). Try the following (I haven't tested this):

Signature of Serialize(): Public Sub Serialize(ByVal serializationStream As System.IO.Stream, ByVal graph As Object)

When I run the program, it will only process the first folder pair in my SyncToy configuration. I have been studying the SyncEngine object model and can not see any way to iterate through the various folder pairs. If I run the 'real' SyncToy, then examine the log file that it produces, it is doing a Preview() and a Sync() for each pair.

I'm stumped at this point, it works great for one folder pair, but not for the whole configuration.

Your comment leads me to believe that all folder pairs are stored in one config file. I hadn't tested that out. If that is the case, Copy the file to another location after you create each folder pair. This way, the file will only have one file pair in the config. You can also step through the code to check this when it deserializes the file. If you can seperate the config into multiple files, then just call the exe with each file name. Otherwise, if you see that all configs are in one file, then maybe you can tweak the code a bit to add a for each loop...

I built the console application with Visual Studio 2005 and got my exe file. Trying to run it, but I'm not sure what it is I am passing in - is it the name of the folder pair? I suspect so, but that never seems to work. Just dumps me back out.

Aha - the parameter to pass in is the string directory path and filename for SyncToyDirPairs.bin. Then it works! Runs like a charm!

But now, how do you choose which one of several folder pairs to run? Thought it was just doing the first in the list so I made a new pair with a name alphabetically earlier, but it still choose the same pair - now second in the list.

In step 2 above, you'll see that a file name is passed as a parameter to the console application. This file is the config file that is created by the syncToy UI. It is typically stored in C:\Documents and Settings\[username]\My Documents\SyncToyData as noted in the prerequisites section.