Nota: Considerare l'utilizzo di un manifestarsi come nella risposta qui per una soluzione migliore:
Come farlo senza una manifesta
Il COM registro è un servizio che è opti onal per un server inproc.
Ancora: Non è necessario registrare un oggetto per crearlo. Se non è registrato, (e non in un manifest) non è possibile crearlo con CoCreateInstance
, perché il registro (o manifest) è ciò che dice a CoCreateInstance
quale DLL caricare.
Tuttavia è possibile crearlo con LoadLibrary
, GetProcAddress
, DllGetClassObject
e IClassFactory::CreateInstance
.
(Nota che non si otterranno servizi COM + e non è possibile creare oggetti out-of-process in questo modo o oggetti il cui modello di threading non è compatibile con il thread di creazione. fallo per te queste cose diventano il tuo problema).
Il servizio fornito da CoCreateInstance
consiste nel trovare la DLL corretta per la chiamata a LoadLibrary e chiamare semplicemente le altre funzioni. (E controllando i modelli di threading sono compatibili, creando sul thread appropriato e usando CoMarshalInterthreadInterfaceInStream/CoUnmarshalInterfaceAndReleaseStream per eseguire il marshalling dell'interfaccia se non lo sono. Sembra un sacco di lavoro ma se hai solo uno STA therad puoi praticamente ignorare tutto le questioni.)
Qualcosa del genere dovrebbe fare il trucco:
// 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;
}
Nota: questo vi permetterà di creare l'oggetto. Tuttavia, se l'oggetto che chiami è di per sé affidabile, esso non funzionerà correttamente.
In particolare, molte implementazioni IDispatch
si basano sulla libreria dei tipi. Se questo è il caso per un oggetto particolare, allora GetIDsOfNames
e GetTypeInfo
non riusciranno e non sarai in grado di utilizzare metodi con limite di lunghezza dell'oggetto. Ciò include l'uso di dynamic
in C# e lingue dinamiche come Python.
Altri metodi come i metodi di interfaccia doppia e le interfacce che non ereditano da IDispatch potrebbero funzionare anche se i metodi IDispatch non funzionano.
Bottom line: per la COM senza registrazione per il lavoro, l'oggetto da istanziare non deve fare affidamento sulla propria registrazione.
L'articolo fornisce molti dettagli, che altro avete bisogno? Che cosa hai provato? Quali errori stai ottenendo? – Polyfun
Suppongo che tu debba sapere se il manifest è collegato all'exe o a una delle DLL - immagino l'exe perché imposta il processo. A parte questo, la sintassi XML non è chiara? – Rup
In realtà, è necessaria la registrazione gratuita? Finché rules.dll viene installato nello stesso posto (che richiederebbe comunque i diritti di amministratore, correggere?) E implementa gli stessi oggetti e le stesse interfacce con cui è costruito CPForms.dll, perché è necessario che non sia registrato e registrato nuovamente ogni tempo? (La domanda senza registrazione è di per sé interessante, però.) – Rup