Domanda

So che possiamo utilizzare Coloadlibrary e DllgetClassobject per ottenere l'interfaccia ICLASSFactory e ottenere l'interfaccia Componente COM senza registrare la DLL.

Ma per quanto riguarda un componente COM in un exe?C'è un modo in cui posso ottenere un'interfaccia Componente COM da un server COM di tipo EXE semplicemente fornendo un percorso di file diverso?

È stato utile?

Soluzione

Se si utilizza Real registrazione gratuita com, dovresti essere in grado di operare questo funzionamento per gli oggetti COM IN-PROC che Out-of-PROC.

Come ha sottolineato Sharptoth, non usi davvero la registrazione gratuita com.Invece stai davvero lanciando il tuo fingendo le chiamate che ci utilizza durante l'attivazione.La tua soluzione può funzionare se controlli sia la tua applicazione che il server COM che stai attivando, ma è probabile che fallisca diversamente.

Altri suggerimenti

No, non puoi.È necessaria la configurazione di COM SETUP tra il tuo programma e il server COM out-proc.Per ottenere ciò devi chiamare CoInitialize() e quindi CoCreateInstance() o CoGetClassObject().

Il percorso che descrivi con un server in-proc - chiamando CoLoadLibrary() e poi DllGetClassObject() - è infatti un hack sporco - aggira i normali meccanismi della COM e quindi, ad esempio, nessun marshalling calcirà anche se è necessario soddisfare il modello di filettaturaRequisiti (roba STA / MTA).Tale hack sporco è possibile perché un server IN PROC è una DLL normale con diverse funzioni ben note esposte.Lo stesso è impossibile per un server COM out-proc - è necessario fare affidamento su com in tal caso.

È possibile passare un componente COM in una chiamata di funzione, come puntatore.

Quindi supporti l'implementazione di un oggetto nel tuo exe, e questo carichi un altro oggetto COM da una DLL, è possibile passare l'oggetto basato su EXE all'oggetto dalla DLL. L'oggetto caricato dovrebbe supportare un'interfaccia che ha una funzione che accetta un puntatore, ad esempio.

interface ILoadedObject
{
    HRESULT GiveObject(IUnknown *pObj);
};
.

Se l'oggetto basato sulla DLL lo implementa, è possibile chiamarlo dal tuo exe e passarlo un oggetto che non è registrato ovunque , quindi non è necessario registrare oggetti in un exe da raggiungere Questo.

Gli unici requisiti sono sulla corretta implementazione di IUnknown: non distruggere l'oggetto finché non è stato chiamato Release il numero giusto di volte e assicurarsi che QueryInterface possa essere utilizzato per attraversare un set fisso di interfacce sull'oggetto e Quella interrogazione per IUnknown restituisce sempre lo stesso indirizzo.

D'altra parte, è possibile registrare un exe come server di oggetti, ma questo introduce molta complessità; Com deve avviare l'esecuzione EXE e quindi inviarlo messaggi tramite la coda dei messaggi di Windows. Questo è solo ampiamente utilizzato per OLE; Può essere piuttosto fragile.

Aggiornamento

Una soluzione più completa è definire un modo standard per creare un'istanza di un tipo di oggetto, ma per consentire all'eXE di definire come funziona. L'EXE avrebbe implementare:

interface IComponent;

interface IEnvironment : IUnknown
{
    HRESULT CreateInstance(REFCLSID clsid, IComponent **ppNew);
}
.

Ogni componente deve supportare questa interfaccia:

interface IComponent : IUnknown
{
    HRESULT SetEnvironment(IEnvironment *pEnv);
}
.

Ora, per ottenere il comportamento standard in cui l'EXE desidera utilizzare il registro per trovare i componenti, può implementare il metodo CreateInstance come questo:

HRESULT Env::CreateInstance(REFCLSID clsid, IComponent **ppNew)
{
    HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,
                     __uuidof(IComponent), (void **)&ppNew);
    if (FAILED(hr))
        return hr;

    (*ppNew)->SetEnvironment(this);
    return S_OK;
}
.

Ma ovviamente può cambiarlo e "iniettare" alcuni componenti. Quindi, invece di (o in aggiunta a) il registro, può essere utilizzato un file di configurazione. O (come hai chiesto) L'EXE potrebbe avere implementazioni integrate di alcuni componenti:

Poiché ogni componente viene informato dell'ambiente quando viene creato, può utilizzare l'ambiente per creare ulteriori componenti:

// inside some component:
HRESULT Comp::SetEnvironment(IEnvironment *e)
{
    m_env = e; // using a smart pointer for ref-counting
    return S_OK;
}

// in some method of the component

ComPtr<IComponent> button;
m_env->CreateInstance(CLSID_Button, &button);

// now query button for more useful interface...
.

Quindi ogni volta che viene creato un componente, l'ambiente (definito nell'eXE) può controllare esattamente come viene trovata l'implementazione del componente. Ogni creazione va attraverso l'exe.

Questo a volte è chiamato "iniezione di dipendenza" o "inversione del controllo".

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top