Uwaga: rozważyć stosowanie manifestu jako odpowiedź tutaj dla lepszego rozwiązania:
Jak to zrobić bez oczywistego
COM rejestru jest usługa która jest opti onal dla serwera inproc.
Jeszcze raz: Nie musisz rejestrować obiektu, aby go utworzyć. Jeśli nie jest zarejestrowany, (a nie w manifeście), nie można go utworzyć przy użyciu CoCreateInstance
, ponieważ rejestr (lub manifest) jest tym, co mówi CoCreateInstance
, którą bibliotekę DLL załadować.
Można jednak utworzyć go za pomocą LoadLibrary
, GetProcAddress
, DllGetClassObject
i IClassFactory::CreateInstance
.
(Uwaga: nie dostaniesz żadnych usług COM + i nie możesz tworzyć obiektów poza procesem w ten sposób lub obiektów, których model wątku nie jest kompatybilny z tworzonym wątkiem. Jeśli nie poprosisz o COM zrób to dla ciebie, te rzeczy stają się twoim problemem).
Usługa, którą zapewnia CoCreateInstance
, polega na zlokalizowaniu poprawnej biblioteki DLL dla wywołania funkcji LoadLibrary i po prostu wywołaj inne funkcje. (Sprawdzenie, czy modele wątków są zgodne, tworzenie na odpowiednim węźle i używanie CoMarshalInterthreadInterfaceInStream/CoUnmarshalInterfaceAndReleaseStream do sterowania interfejsem, jeśli tak nie jest. To brzmi jak dużo pracy, ale jeśli masz tylko jednego terapeuta STA, możesz prawie zignorować wszystkie kwestie.)
coś jak to powinno załatwić sprawę:
// Really you should break this up int GetClassFactoryFromDLL, then reuse the class factory.
// But this is all from memory...
// Load CLSID_MyID, from DLL pszMyDllPath
typedef HRESULT __stdcall (*_PFNDLLGETCLASSOBJECT)(
__in REFCLSID rclsid,
__in REFIID riid,
__out LPVOID *ppv
) PFNDLLGETCLASSOBJECT;
HRESULT CreateInstanceFromDll(LPCTSTR pszMyDllPath, CLSID clsidMyClass, IUknown** ppunkRet)
{
// Handle bad callers
*ppunkRet = NULL;
HANDLE hDLL = LoadLibrary(pszMyDllPath);
if(hDLL == NULL)
{
// Failed to load
return HRESULT_FROM_NTSTATUS(GetLastError());
}
PFNDLLGETCLASSOBJECT pfnDllGetClassObject = GetProcAddress(hDLL);
if(pfnDllGetClassObject == NULL)
{
// Not a COM dll
HRESULT hrRet = HRESULT_FROM_NTSTATUS(GetLastError());
FreeLibrary(hDLL);hDLL = NULL;
return hrRet;
}
IClassFactory* pClassFactory = NULL;
HRESULT hr = pfnDllGetClassObject(clsidMyClass, IID_IClassFactory, &pClassFactory);
if(FAILED(hr)){
FreeLibrary(hDLL);hDLL = NULL;
return hr;
}
hr = pClassFactory->CreateInstance(NULL, IID_IUnknown, &ppunkRet);
pClassFactory->Release();
if(FAILED(hr))
{
*ppunkRet = NULL;
FreeLibrary(hDLL);
return hr;
}
return hr;
}
Uwaga: to pozwoli na utworzenie obiektu. Jednak jeśli obiekt, który wywołujesz, sam w sobie jest niezawodny, nie będzie działał poprawnie. W szczególności wiele implementacji polega na bibliotece typów. Jeśli tak jest w przypadku konkretnego obiektu, to nie powiedzie się GetIDsOfNames
i GetTypeInfo
i nie będzie można używać metod związanych z opóźnieniem z obiektem. Obejmuje to używanie dynamic
w języku C# i języków dynamicznych, takich jak Python.
Inne metody, takie jak metody podwójnego interfejsu i interfejsy, które nie dziedziczą z IDispatch, mogą działać, nawet jeśli metody IDispatch tego nie robią. Podsumowując: Aby wolny od rejestracji COM działał, tworzony obiekt nie może opierać się na własnej rejestracji.
Artykuł zawiera wiele szczegółów, czego więcej potrzebujesz? Co próbujesz? Jakie błędy dostałeś? – Polyfun
Zgaduję, że powinieneś wiedzieć, czy plik manifestu jest dołączony do .exe lub jednej z bibliotek DLL - zgaduję, że .exe, ponieważ konfiguruje ten proces. Poza tym, czy składnia XML nie jest czysta? – Rup
Czy to wymaga rejestracji? Tak długo, jak rules.dll jest instalowany w tym samym miejscu (co i tak wymagałoby uprawnień administratora, prawda?) I implementuje te same obiekty i interfejsy, z którymi zbudowany jest CPForms.dll, dlaczego musi być wyrejestrowywany i ponownie rejestrowany co czas? (Pytanie bez rejestracji jest interesujące samo w sobie.) – Rup