アンマネージ コードを使用してファイルを同期する方法
このトピックでは、Sync Framework ファイル同期プロバイダーを使用して、ファイルおよびサブフォルダーを同期するアプリケーションを、C++ などのアンマネージ言語で作成する方法について説明します。
このトピックは、C++ および COM の概念について基本的な知識がある方を対象としています。
このトピックの例では、次に示す Sync Framework のインターフェイスを中心に説明します。
ファイルの同期について
Sync Framework は、ファイル システム上のフォルダーに格納されているファイルおよびサブフォルダーを同期するために使用できる同期プロバイダーを実装します。このプロバイダーは、いくつかの構成可能な設定を公開して、同期をどのように発生させ、どの項目を同期するかについて詳細な制御を可能にします。2 つのフォルダー間でファイルを同期するために、アプリケーションは次の基本的な手順を実行します。
各フォルダーを表す IFileSyncProvider オブジェクトを作成します。
2 つのプロバイダーを ISyncSession オブジェクトに渡し、一方を同期元プロバイダー、もう一方を同期先プロバイダーとして指定します。
同期セッションを開始します。
ファイルの同期の詳細については、「ファイルの同期」を参照してください。
ビルド要件
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 インターフェイス