如何使用非托管代码同步文件

本主题说明如何使用非托管语言(如 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(Microsoft 基础类)对话自用户获取文件夹和筛选器信息。用户输入的字符串将封装到 CString 对象中,随后将使用这些对象初始化提供程序和筛选器。

创建和初始化文件同步提供程序

通过使用 CoCreateInstance 来创建一个 IFileSyncProvider 对象。

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 文件同步组件