Как синхронизировать файлы с помощью неуправляемого кода

В этом разделе показано использование неуправляемого кода, например на языке C++, для создания приложения, синхронизирующего файлы и вложенные папки с помощью службы синхронизации файлов платформы Sync Framework.

В этом разделе предполагается, что читатель знаком с основными понятиями языка C++ и модели COM.

В примерах, приведенных в этом разделе, обсуждаются следующие интерфейсы Sync Framework:

Основные сведения о синхронизации файлов

Платформа Sync Framework реализует службу синхронизации, позволяющую синхронизировать файлы и вложенные папки файловой системы. Эта служба предоставляет доступ к настраиваемым параметрам обеспечивающим более тонкое управление элементами и процессом синхронизации. Для синхронизации файлов в двух папках приложение выполняет ряд простых шагов.

  1. Оно создает объект IFileSyncProvider, представляющий каждую папку.

  2. Передает два поставщика объекту ISyncSession и указывает один из них в качестве поставщика источника, а другой — в качестве поставщика назначения.

  3. Приложение запускает сеанс синхронизации.

Дополнительные сведения о синхронизации файлов см. в разделе Синхронизация файлов.

Требования построения

  • 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