spDBInitialize.CreateInstance()
выполняет следующие действия:
- Поиск вашего CLSID в реестре Windows по адресу HKEY_CLASSES_ROOT \ CLSID
- Определяет DLL из InProcServer
- Звонки
LoadLibrary()
в DLL
- Вызывает
GetProcAddress
для "DllGetClassObject"
- Звонит
DllGetClassObject
, чтобы получить IClassFactory
- Возвращено
IClassFactory
для обработки вашего CreateInstance(NULL, IID_IDBInitialize, (void**) &spIDBInitialize)
запроса
В вашем сценарии вы не можете пройти первый шаг, потому что ваша DLL не зарегистрирована в реестре Windows.
Однако, так как вы знаете, где находятся библиотеки SQL Server CE, вы можете обойти это, сделав свой код просто реализующим 3, 4, 5 и 6.
Вот консольное приложение C ++, которое открывает SDF с помощью замены CoCreateInstance:
#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 hr
- Обработка ошибок LoadLibrary ()
Чтобы получить содержательные сообщения об ошибках для операций SQL Server CE, следует обратиться к статье Microsoft MSDN Использование объектов ошибок OLE DB (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 Provider
- sqlceqp35.dll - SQLCE Query Processor
- sqlcese35.dll - SQLCE Storage Engine
- sqlceer35EN.dll - SQLCE Собственные строки ошибок и ресурсы
- sqlcecompact35.dll - Инструмент восстановления базы данных SQLCE
Для справки, я полагаю, вам не нужны следующие файлы:
- sqlceca35.dll - Клиентский агент SQLCE (для репликации слиянием на SQL Server)
- sqlceme35.dll - SQLCE Управляемые расширения
- System.Data.SqlServerCe.Entity.dll - Управляемая сборка