Как синхронизировать файлы с помощью неуправляемого кода
В этом разделе показано использование неуправляемого кода, например на языке C++, для создания приложения, синхронизирующего файлы и вложенные папки с помощью службы синхронизации файлов платформы Sync Framework.
В этом разделе предполагается, что читатель знаком с основными понятиями языка C++ и модели COM.
В примерах, приведенных в этом разделе, обсуждаются следующие интерфейсы Sync Framework:
Основные сведения о синхронизации файлов
Платформа Sync Framework реализует службу синхронизации, позволяющую синхронизировать файлы и вложенные папки файловой системы. Эта служба предоставляет доступ к настраиваемым параметрам обеспечивающим более тонкое управление элементами и процессом синхронизации. Для синхронизации файлов в двух папках приложение выполняет ряд простых шагов.
Оно создает объект IFileSyncProvider, представляющий каждую папку.
Передает два поставщика объекту ISyncSession и указывает один из них в качестве поставщика источника, а другой — в качестве поставщика назначения.
Приложение запускает сеанс синхронизации.
Дополнительные сведения о синхронизации файлов см. в разделе Синхронизация файлов.
Требования построения
Synchronization.h: декларации основных компонентов Sync Framework.
#include <synchronization.h>
FileSyncProvider.h: объявления службы синхронизации файлов.
#include <filesyncprovider.h>
Synchronization.lib: библиотека импорта для основных компонентов Sync Framework.
FileSyncProvider.lib: библиотека импорта для службы синхронизации файлов.
Пример
В примере кода показаны следующие задачи.
Как создать и инициализировать исходные файлы службы-источника синхронизации и службы-назначения синхронизации.
Как настроить фильтр, управляющий включением элементов в синхронизацию.
Как синхронизировать элементы в папках, представленных службами, с помощью сеанса синхронизации.
В этом примере сведения о папке и фильтре указывает пользователь с помощью диалога классов MFC. Введенные пользователем строки упаковываются в объекты CString, и эти объекты используются для инициализации служб и фильтра.
Создание и инициализация службы синхронизации файлов
Создайте объект IFileSyncProvider с помощью интерфейса CoCreateInstance
.
IFileSyncProvider* pProvSrc = NULL;
hr = CoCreateInstance(CLSID_FileSyncProvider, NULL, CLSCTX_INPROC_SERVER,
__uuidof(pProvSrc), (void**)&pProvSrc);
Службу необходимо инициализировать, чтобы ее использовать. Кроме того, это дает возможность настроить необходимые параметры. Эта реализация проходит через фильтр pFilter, управляющий включением элементов в синхронизацию. В следующем разделе показана настройка фильтра.
hr = pProvSrc->Initialize(*pguidReplicaSrc, pstrFolderSrc->GetString(),
pstrMetaSrc->GetString(), NULL,
FILESYNC_INIT_FLAGS_NONE, pFilter, NULL, NULL);
Использование фильтра области синхронизации файлов
Создайте фильтр с помощью метода IFileSyncProvider::CreateNewScopeFilter. Новый фильтр не имеет связи со службой, которой он был создан. Чтобы подключить фильтр к службе, передайте его методу IFileSyncProvider::Initialize. Это означает, что в одном сеансе синхронизации должен создаваться только один фильтр, поскольку обеим службам должен передаваться один и тот же фильтр. Имейте в виду, что сведения из фильтра служба хранит в методе Initialize
. Таким образом, дальнейшие изменения фильтра не отразятся на работе службы.
В данной реализации значения параметров фильтра указываются пользователем через диалог MFC. Код диалога не показан. Однако значения параметров хранятся в нескольких объектах CString
, например в m_strFilenameExc
. В нашем примере в качестве значений параметров фильтра задаются значения, введенные пользователем.
// 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();
}
Запуск синхронизации
Теперь, когда службы и фильтр созданы и инициализированы, следует создать и запустить сеанс синхронизации.
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();
}
Полный пример кода
Ниже приведен полный код для данного примера. Предыдущие примеры в этом разделе взяты именно из этого фрагмента кода.
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;
}
См. также
Справочник
Интерфейс IFileSyncProvider
Интерфейс IFileSyncScopeFilter
Основные положения
Синхронизация файлов
Компоненты синхронизации файлов Sync Framework