How to: Synchronize Files by Using Unmanaged Code
This topic shows how to use an unmanaged language, such as C++, to create an application that synchronizes files and subfolders by using the Sync Framework file synchronization provider.
This topic assumes a basic familiarity with C++ and COM concepts.
The examples in this topic focus on the following Sync Framework interfaces:
Understanding File Synchronization
Sync Framework implements a synchronization provider that can be used to synchronize files and subfolders that are contained in a folder on a file system. This provider exposes several configurable settings to give a finer degree of control over exactly how synchronization occurs and which items are synchronized. To synchronize files between two folders, an application completes the following basic steps:
Creates an IFileSyncProvider object to represent each folder.
Passes the two providers to an ISyncSession object, and specifies one as the source provider and the other as the destination provider.
Starts the synchronization session.
For more information about synchronizing files, see Synchronizing Files.
Build Requirements
Synchronization.h: declarations for Sync Framework core components.
#include <synchronization.h>
FileSyncProvider.h: declarations for the file synchronization provider.
#include <filesyncprovider.h>
Synchronization.lib: import library for Sync Framework core components.
FileSyncProvider.lib: import library for the file synchronization provider.
Example
The example code shows the following tasks:
How to create and initialize a source file synchronization provider and a destination file synchronization provider.
How to establish a filter to control which items are included in synchronization.
How to use a synchronization session to synchronize items between the folders that are represented by the providers.
This example uses an MFC (Microsoft Foundation Classes) dialog to obtain folder and filter information from the user. The strings that a user entered are packaged into CString objects, and these objects are then used to initialize the providers and filter.
Creating and Initializing a File Synchronization Provider
Create an IFileSyncProvider object by using CoCreateInstance
.
IFileSyncProvider* pProvSrc = NULL;
hr = CoCreateInstance(CLSID_FileSyncProvider, NULL, CLSCTX_INPROC_SERVER,
__uuidof(pProvSrc), (void**)&pProvSrc);
The provider must be initialized before it can be used. This is also an opportunity to configure any settings. This implementation passes a filter, pFilter, to control which items are included in synchronization. The next section shows how to set up the filter.
hr = pProvSrc->Initialize(*pguidReplicaSrc, pstrFolderSrc->GetString(),
pstrMetaSrc->GetString(), NULL,
FILESYNC_INIT_FLAGS_NONE, pFilter, NULL, NULL);
Using a File Sync Scope Filter
Create a filter by using the IFileSyncProvider::CreateNewScopeFilter method. This new filter has no relationship to its creating provider. To connect a filter to a provider, pass the filter to the IFileSyncProvider::Initialize method. This means only one filter must be created per synchronization session, because the same filter can be passed to both providers. Be aware that the filter information is stored by the provider in the Initialize
method. Therefore, later changes to the filter will not be reflected in the provider.
This implementation obtains filter option values from the user by using an MFC dialog. The dialog code is not shown. But the option values are stored in several CString
objects, such as m_strFilenameExc
. Our example sets the filter options to the values supplied by the user.
// Create a scope filter and fill it (some strings may be empty).
IFileSyncScopeFilter* pFilter = NULL;
hr = pProvSrc->CreateNewScopeFilter(&pFilter);
if (SUCCEEDED(hr))
{
hr = pFilter->SetFilenameExcludes(m_strFilenameExc.GetString());
if (SUCCEEDED(hr))
{
hr = pFilter->SetSubDirectoryExcludes(m_strDirExc.GetString());
}
if (SUCCEEDED(hr))
{
DWORD dwMask = wcstoul(m_strAttrExc.GetString(), NULL, 16);
hr = pFilter->SetFileAttributeExcludeMask(dwMask);
}
if (SUCCEEDED(hr))
{
// Only set the include list if we have something in it, because
// setting the include list to empty effectively excludes all files.
if (!m_strFilenameInc.IsEmpty())
{
hr = pFilter->SetFilenameIncludes(m_strFilenameInc.GetString());
}
}
if (SUCCEEDED(hr))
{
// Initialize the providers.
hr = pProvSrc->Initialize(*pguidReplicaSrc, pstrFolderSrc->GetString(),
pstrMetaSrc->GetString(), NULL,
FILESYNC_INIT_FLAGS_NONE, pFilter, NULL, NULL);
if (SUCCEEDED(hr))
{
hr = pProvDest->Initialize(*pguidReplicaDest, pstrFolderDest->GetString(),
pstrMetaDest->GetString(), NULL,
FILESYNC_INIT_FLAGS_NONE, pFilter, NULL, NULL);
}
}
pFilter->Release();
}
Starting Synchronization
Now that the providers and the filter have been configured and initialized, create and start a synchronization session.
IApplicationSyncServices* pSvc = NULL;
hr = CoCreateInstance(CLSID_SyncServices, NULL, CLSCTX_INPROC_SERVER,
IID_IApplicationSyncServices, (void**)&pSvc);
if (SUCCEEDED(hr))
{
ISyncSession* pSession = NULL;
hr = pSvc->CreateSyncSession(pProvDest, pProvSrc, &pSession);
if (SUCCEEDED(hr))
{
SYNC_SESSION_STATISTICS syncStats;
hr = pSession->Start(CRP_NONE, &syncStats);
pSession->Release();
}
pSvc->Release();
}
Complete Code Example
The following code is the complete code for this example. The previous examples in this section were taken from this code.
HRESULT CFileSynchronizerDlg::Synchronize(const GUID* pguidReplicaSrc, CString* pstrFolderSrc,
CString* pstrMetaSrc, const GUID* pguidReplicaDest, CString* pstrFolderDest,
CString* pstrMetaDest)
{
HRESULT hr = E_UNEXPECTED;
// Create the source and destination providers.
IFileSyncProvider* pProvSrc = NULL;
hr = CoCreateInstance(CLSID_FileSyncProvider, NULL, CLSCTX_INPROC_SERVER,
__uuidof(pProvSrc), (void**)&pProvSrc);
if (SUCCEEDED(hr))
{
IFileSyncProvider* pProvDest = NULL;
hr = CoCreateInstance(CLSID_FileSyncProvider, NULL, CLSCTX_INPROC_SERVER,
__uuidof(pProvDest), (void**)&pProvDest);
if (SUCCEEDED(hr))
{
// Create a scope filter and fill it (some strings may be empty).
IFileSyncScopeFilter* pFilter = NULL;
hr = pProvSrc->CreateNewScopeFilter(&pFilter);
if (SUCCEEDED(hr))
{
hr = pFilter->SetFilenameExcludes(m_strFilenameExc.GetString());
if (SUCCEEDED(hr))
{
hr = pFilter->SetSubDirectoryExcludes(m_strDirExc.GetString());
}
if (SUCCEEDED(hr))
{
DWORD dwMask = wcstoul(m_strAttrExc.GetString(), NULL, 16);
hr = pFilter->SetFileAttributeExcludeMask(dwMask);
}
if (SUCCEEDED(hr))
{
// Only set the include list if we have something in it, because
// setting the include list to empty effectively excludes all files.
if (!m_strFilenameInc.IsEmpty())
{
hr = pFilter->SetFilenameIncludes(m_strFilenameInc.GetString());
}
}
if (SUCCEEDED(hr))
{
// Initialize the providers.
hr = pProvSrc->Initialize(*pguidReplicaSrc, pstrFolderSrc->GetString(),
pstrMetaSrc->GetString(), NULL,
FILESYNC_INIT_FLAGS_NONE, pFilter, NULL, NULL);
if (SUCCEEDED(hr))
{
hr = pProvDest->Initialize(*pguidReplicaDest, pstrFolderDest->GetString(),
pstrMetaDest->GetString(), NULL,
FILESYNC_INIT_FLAGS_NONE, pFilter, NULL, NULL);
}
}
pFilter->Release();
}
if (SUCCEEDED(hr))
{
// Synchronize!
IApplicationSyncServices* pSvc = NULL;
hr = CoCreateInstance(CLSID_SyncServices, NULL, CLSCTX_INPROC_SERVER,
IID_IApplicationSyncServices, (void**)&pSvc);
if (SUCCEEDED(hr))
{
ISyncSession* pSession = NULL;
hr = pSvc->CreateSyncSession(pProvDest, pProvSrc, &pSession);
if (SUCCEEDED(hr))
{
SYNC_SESSION_STATISTICS syncStats;
hr = pSession->Start(CRP_NONE, &syncStats);
pSession->Release();
}
pSvc->Release();
}
}
pProvDest->Release();
}
pProvSrc->Release();
}
return hr;
}
See Also
Reference
IFileSyncProvider Interface
IFileSyncScopeFilter Interface
Concepts
Synchronizing Files
Sync Framework File Synchronization Components