2010-07-09 11 views

Odpowiedz

3

Jeśli używasz prawdziweregistration free COM, powinieneś być w stanie uzyskać to działa zarówno dla obiektów COM w trybie in-proc i out-of-proc.

Jak zauważył Sharptooth, tak naprawdę nie korzystasz z darmowej rejestracji. Zamiast tego naprawdę zmieniasz swoją własną, fałszując połączenia, których używa COM podczas aktywacji. Twoje rozwiązanie MOŻE działać, jeśli kontrolujesz zarówno aplikację, jak i serwer COM, który aktywujesz, ale w przeciwnym wypadku może się nie powieść.

+0

Nie jestem pewien, czy pierwszy paragraf jest prawdziwy, ponieważ w artykule, do którego się on prowadzi, jedyne wzmianki o przetwarzających poza proces serwerach EXE mówią, że nie można ich używać z COM bez rejestracji. Ten wątek jest również użyteczne i wskazuje na problemy z ROT którego rejestrację wolne COM najwyraźniej zaniedbuje zarządzanie: http://social.msdn.microsoft.com/Forums/vstudio/en-US/3849f22d-c8b8-429e- a03a-37601411acec/registrationfree-exe-com-server- Wygląda na to, że podstawowe obiekty COM DLL są również obsługiwane przez mechanizm reg-free, a do wszystkiego, co bardziej egzotyczne, musisz przetasować. . –

+0

Odpowiedzi dotyczące wyłącznie linków są naprawdę złe, ponieważ linki mają tendencję do znikania ... jak te w tej odpowiedzi. – Stephane

1

Można przekazać składnik COM w wywołaniu funkcji jako wskaźnik.

Załóżmy, że zaimplementowałeś obiekt w swoim EXE i ładowałeś inny obiekt COM z biblioteki DLL, możesz przekazać obiekt oparty na EXE do obiektu z biblioteki DLL. Załadowany obiekt musiałby obsługiwać interfejs, który ma funkcję akceptującą wskaźnik, np.

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

Jeśli obiekt DLL oparte wdraża, że ​​można nazwać to z EXE i przekazać obiekt , które nie są zarejestrowane w dowolnym, więc nie ma potrzeby rejestrowania obiektów w EXE do osiągnięcia tego celu .

Jedyne wymagania to na prawidłową realizację IUnknown: nie zniszczyć obiekt aż Release został nazwany odpowiednią liczbę razy, i upewnić się, że QueryInterface może być używany do przechodzenia między stałym zestawem interfejsów na obiekcie i że zapytanie dla IUnknown zawsze zwraca ten sam adres.

Z drugiej strony można zarejestrować EXE jako serwer obiektów, ale to wprowadza wiele złożoności; COM musi uruchamiać EXE, a następnie wysyłać wiadomości za pośrednictwem kolejki komunikatów systemu Windows. Jest to tylko szeroko stosowane w OLE; może być dość kruchy.

Aktualizacja

Pełniejszy rozwiązaniem jest zdefiniowanie standardowy sposób, aby utworzyć instancję typu obiektu, ale aby umożliwić EXE aby określić, jak to działa. EXE będzie realizować:

interface IComponent; 

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

Każdy element musi obsługiwać ten interfejs:

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

Teraz, aby uzyskać standardowe zachowanie gdzie EXE chce korzystać z rejestru, aby znaleźć elementy, można go wdrożyć CreateInstance Metoda taka jak ta:

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; 
} 

Ale oczywiście może to zmienić i "wstrzyknąć" niektóre elementy. Dlatego zamiast (lub oprócz) rejestru można użyć pliku konfiguracyjnego. Lub (jak prosiłem) EXE może mieć wbudowane implementacje niektórych komponentów:

Ponieważ każdy składnik jest powiadamiany o środowisku, gdy jest on utworzony, można go używać do tworzenia środowiska dalsze składniki:

// 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... 

Zawsze, gdy komponent jest tworzony, środowisko (zdefiniowane w EXE) może kontrolować dokładnie, w jaki sposób można znaleźć implementację komponentu. Każde stworzenie przechodzi przez EXE.

Jest to czasami nazywane "wstrzyknięciem zależności" lub "odwróceniem kontroli".

+0

Dzięki, nie wiem, jak bardzo rozumiem Twoje rozwiązanie, wygląda na to, że jest to alternatywny sposób: 1. Uruchom EXE i umieść punkt obiektu na komponencie COM opartym na DLL. 2. gdy potrzebuję użyć obiektu EXE implement Component, powinienem go pobrać przez komponent DLL, który implementuje wskaźnik Container zawiera komponent zaimplementowany w plikach EXE. Mam to? – Gohan

+0

Myślę, że rozumiem cię i wierzę, że go masz. –

2

Nie, nie możesz. Konieczne jest uporządkowanie konfiguracji COM między programem a serwerem COM. Aby to osiągnąć, musisz zadzwonić pod numer CoInitialize(), a następnie CoCreateInstance() lub CoGetClassObject().

można opisać za pomocą serwera w-proc Ścieżka - wywołanie CoLoadLibrary() a następnie DllGetClassObject() - w rzeczywistości jest brudny Hack - omija normalne mechanizmy COM, a więc na przykład nie marshalling rozpocznie się, nawet jeśli jest to konieczne do zaspokojenia wątków wymagania modelowe (rzeczy STA/MTA). Taki brudny hack jest możliwy, ponieważ serwer w-proc jest zwykłą biblioteką DLL z kilkoma dobrze znanymi funkcjami. To samo jest niemożliwe dla outcroc serwera COM - w takim przypadku musisz polegać na COM.

Powiązane problemy