spDBInitialize.CreateInstance()
執行以下操作:
- 下HKEY_CLASSES_ROOT \ CLSID中查找在Windows註冊表中的CLSID
- 確定DLL從InProcServer
- 呼叫
LoadLibrary()
在DLL上
- 調用
GetProcAddress
代替「DllGetClassObject」
- 調用
DllGetClassObject
得到一個IClassFactory
- 用途返回
IClassFactory
來處理你的請求CreateInstance(NULL, IID_IDBInitialize, (void**) &spIDBInitialize)
在你的情況下,你不能獲得通過第一個步驟,因爲您的DLL沒有在Windows註冊表中註冊。
但是,因爲您知道SQL Server CE DLL的位置,您可以通過讓代碼只實現3,4,5和6來解決此問題。
下面是打開使用CoCreateInstance的更換SDF一個C ++控制檯應用程序:
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <oleauto.h>
#include <atlbase.h>
#include "C:\Program Files (x86)\Microsoft SQL Server Compact Edition\v3.5\Include\sqlce_oledb.h"
#include "C:\Program Files (x86)\Microsoft SQL Server Compact Edition\v3.5\Include\sqlce_err.h"
//----------------------------------------------------------------------
// Creates a COM object using an HMODULE instead of the Windows Registry
//----------------------------------------------------------------------
HRESULT DllCoCreateInstance(HMODULE hModule, REFCLSID rclsid, LPUNKNOWN pUnkOuter, REFIID riid, LPVOID FAR* ppv)
{
HRESULT hr = S_OK;
if (hModule == NULL)
{
return E_INVALIDARG;
}
BOOL (WINAPI*DllGetClassObject)(REFCLSID, REFIID, LPVOID) = NULL;
(FARPROC&) DllGetClassObject = GetProcAddress(hModule, "DllGetClassObject");
if (DllGetClassObject == NULL)
{
return HRESULT_FROM_WIN32(GetLastError());
}
CComPtr<IClassFactory> spIClassFactory;
hr = DllGetClassObject(rclsid, IID_IClassFactory, &spIClassFactory);
if (FAILED(hr))
{
return hr;
}
return spIClassFactory->CreateInstance(pUnkOuter, riid, ppv);
}
//----------------------------------------------------------------------
// Open a close a SDF file
//----------------------------------------------------------------------
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr = S_OK;
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
// Need a loaded library so we can CoCreateInstance without the Windows Registry.
HMODULE hModule = LoadLibrary(L"C:\\Program Files (x86)\\Microsoft SQL Server Compact Edition\\v3.5\\sqlceoledb35.dll");
// Open a SQL Server CE 3.5 database without using Windows Registry.
CComPtr<IDBInitialize> spIDBInitialize;
//hr = spIDBInitialize.CoCreateInstance(CLSID_SQLSERVERCE_3_5);
hr = DllCoCreateInstance(hModule, CLSID_SQLSERVERCE_3_5, NULL, IID_IDBInitialize, (void**) &spIDBInitialize);
CComPtr<IDBProperties> spIDBProperties;
hr = spIDBInitialize->QueryInterface(IID_IDBProperties, (void**) &spIDBProperties);
CComVariant varDataSource(OLESTR("InsertYourSampleDatabase.SDF"));
DBPROP prop = { DBPROP_INIT_DATASOURCE, DBPROPOPTIONS_REQUIRED, 0, DB_NULLID, varDataSource };
DBPROPSET propSet = {&prop, 1, DBPROPSET_DBINIT};
hr = spIDBProperties->SetProperties(1, &propSet);
spIDBProperties = NULL;
hr = spIDBInitialize->Initialize();
// @@TODO: Do your regular OLEDB code with the opened database.
//...
// Close COM objects
spIDBInitialize = NULL;
CoUninitialize();
return 0;
}
有些事情,是一個從代碼片段丟失:
- 呼叫
FreeLibrary()
當你完全與庫完(通常在程序終止之前)
- 處理不良HRESULT小時返回代碼
- 處理負載庫()故障
要獲取有意義的SQL Server CE操作錯誤消息,應參閱Microsoft MSDN文章Using OLE DB Error Objects (SQL Server Compact Edition)。
if (FAILED(hr))
{
CComPtr<IErrorInfo> spIErrorInfo;
GetErrorInfo(0, &spIErrorInfo);
if (spIErrorInfo != NULL)
{
CComBSTR bstrError;
spIErrorInfo->GetDescription(&bstrError);
// @@TODO: Do stuff with bstrError
wprintf("%s\r\n", (BSTR) bstrError);
}
}
它更容易,更安全,只是部署整個的SQL Server CE 3.5的文件夾,但是,如果你想最小的一組,我相信下面的文件是重要的:我通常與它的凝結版本從這裏開始那些爲您的方案:
- sqlceoledb35.dll - SQLCE OLEDB提供
- sqlceqp35.dll - SQLCE查詢處理器
- sqlcese35.dll - SQLCE存儲引擎
- sqlceer35EN.dll - SQLCE機錯誤字符串和資源
- sqlcecompact35.dll - SQLCE數據庫修復工具
作爲參考,我相信你不需要的文件有:
- sqlceca35.dll - SQLCE客戶端代理(對於合併複製到SQL Server)
- sqlceme35.dll - SQLCE託管擴展
- System.Data.SqlServerCe.Entity.dll - 管理大會
+1 - 我現在要檢查它。我只希望他們的OLEDB提供者不會在裏面做另一個'CreateInstance'。 – mark 2012-02-02 11:34:43
它會好的。過去我已經成功地將這種技術用於sdf文件。 – 2012-02-02 12:03:35
這是令人難以置信的!這意味着SQL Server CE是最小的嵌入式數據庫! sqlceoledb40.dll只有167K,而sqlite3.lib超過2M。漁獲在哪裏? – mark 2012-02-02 12:53:32