アンマネージ コードを使用してファイルを同期する方法

このトピックでは、Sync Framework ファイル同期プロバイダーを使用して、ファイルおよびサブフォルダーを同期するアプリケーションを、C++ などのアンマネージ言語で作成する方法について説明します。

このトピックは、C++ および COM の概念について基本的な知識がある方を対象としています。

このトピックの例では、次に示す Sync Framework のインターフェイスを中心に説明します。

ファイルの同期について

Sync Framework は、ファイル システム上のフォルダーに格納されているファイルおよびサブフォルダーを同期するために使用できる同期プロバイダーを実装します。このプロバイダーは、いくつかの構成可能な設定を公開して、同期をどのように発生させ、どの項目を同期するかについて詳細な制御を可能にします。2 つのフォルダー間でファイルを同期するために、アプリケーションは次の基本的な手順を実行します。

  1. 各フォルダーを表す IFileSyncProvider オブジェクトを作成します。

  2. 2 つのプロバイダーを ISyncSession オブジェクトに渡し、一方を同期元プロバイダー、もう一方を同期先プロバイダーとして指定します。

  3. 同期セッションを開始します。

ファイルの同期の詳細については、「ファイルの同期」を参照してください。

ビルド要件

  • Synchronization.h : Sync Framework コア コンポーネントの宣言

    #include <synchronization.h>
    
  • FileSyncProvider.h: ファイル同期プロバイダーの宣言

    #include <filesyncprovider.h>
    
  • Synchronization.lib: Sync Framework コア コンポーネントのインポート ライブラリ

  • FileSyncProvider.lib: ファイル同期プロバイダーのインポート ライブラリ

このコード例では、次の方法を示します。

  • 同期元ファイル同期プロバイダーおよび同期先ファイル同期プロバイダーを作成および初期化する方法

  • 同期に含める項目を制御するためのフィルターを設定する方法

  • 同期セッションを使用してプロバイダーによって表されるフォルダー間で項目を同期する方法

この例では、MFC (Microsoft Foundation Classes) ダイアログを使用して、ユーザーからフォルダー情報およびフィルター情報を取得します。ユーザーによって入力される文字列を 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 メソッドに渡します。同じフィルターを両方のプロバイダーに渡すことができるので、これは、同期セッションごとに 1 つだけフィルターを作成する必要があることを表します。フィルター情報は 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 のファイル同期コンポーネント