2011-02-16 16 views
7

Zbudowałem aplikację klienta COM, która używa dwóch bibliotek dll COM COM; Chcę, aby ta aplikacja działała bez rejestracji COM - czyli: winsxs/.manifestsdebugowanie bezpłatnej rejestracji COM (C++)

Otrzymuję (... prawie oczekiwano ...) wiadomość "Class not registered", gdy próbuję utworzyć instancję mojego obiektu COM z mojej aplikacji klienckiej.

Już wcześniej udało mi się tego rodzaju konfigurację, ale nie mogę zrozumieć, dlaczego ta się nie powiedzie.


oto kilka szczegółów:

  • modułów mam:
    • klient MFC, która zależy od 2 serwerów COM (dll1.dll i dll2.dll)
    • Serwer dll1.dll COM zależy od dll2.dll
    • dll2.dll nie ma zależności od systemu operacyjnego

obiekty COM mam:

  • w dll1.dll (język .idl)

-

[ 
    object, 
    uuid(262D00FB-3B9F-4A76-98FC-3051FDCAF0A6), 
    dual, 
    nonextensible, 
    helpstring("IDialogManager Interface"), 
    pointer_default(unique) 
] 
interface IDialogManager : IDispatch{ 
}; 
[ 
     uuid(58562535-BCA5-4D04-BB92-78F90EDA201E), 
     //... 
] 
dispinterface _IDialogManagerEvents 
{ 
}; 
[ 
     uuid(D599D3F0-A4D1-44A7-87A9-16032CC613CA), 
     //... 
] 
coclass DialogManager 
{ 
     [default] interface IDialogManager; 
     [default, source] dispinterface _IDialogManagerEvents; 
}; 

-

  • w dll2. dll

-

[ 
    object, 
    uuid(2A183A2E-A620-4E00-B657-C9D2E59201D4), 
    nonextensible, 
    helpstring("ICadWizardsManager Interface"), 
    pointer_default(unique) 
] 
interface ICadWizardsManager : IDispatch{ 
}; 
[ 
    object, 
    uuid(FE97F3FB-8930-43BC-947D-64C90F45A071), 
    nonextensible, 
    helpstring("ICadWizard Interface"), 
    pointer_default(unique) 
] 
interface ICadWizard : IDispatch{ 
}; 
[ 
    uuid(5365D4E6-ADFB-4429-9DEA-C44CC94AA3EF), 
] 
dispinterface _ICadWizardEvents 
{ 
}; 
[ 
    uuid(CAC2D0BF-AD5B-4CC8-A04D-53AB23A0CDF4), 
] 
coclass CadWizard 
{ 
    [default] interface ICadWizard; 
    [default, source] dispinterface _ICadWizardEvents; 
}; 
[ 
    uuid(3164FAC4-6F5F-4E4D-9B09-DC4115850D78), 
] 
dispinterface _ICadWizardsManagerEvents 
{ 
}; 
[ 
    uuid(707CB6C8-311E-45EC-9DCB-50477F588BAF), 
] 
coclass CadWizardsManager 
{ 
    [default] interface ICadWizardsManager; 
    [default, source] dispinterface _ICadWizardsManagerEvents; 
}; 

-

  • połączenie klient

-

IDialogManagerPtr dialogManager; 
dialogManager.CreateInstance(CLSID_DialogManager); // <<< returns "Class not registered" 

-

  • client.exe.2.manifest

-

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 

<assemblyIdentity name="client" version="1.0.0.0" type="win32" processorArchitecture="x86"/> 
<file name="dll2.dll"> 
<comClass 
    clsid="{707CB6C8-311E-45EC-9DCB-50477F588BAF}" 
    threadingModel="apartment"> 
</comClass> 
<comClass 
    clsid="{CAC2D0BF-AD5B-4CC8-A04D-53AB23A0CDF4}" 
    threadingModel="apartment"> 
</comClass> 
</file> 

<file name="dll1.dll"> 
<comClass 
    clsid="{D599D3F0-A4D1-44A7-87A9-16032CC613CA}" 
    threadingModel="apartment"> 
</comClass> 
</file> 

</assembly> 

-


nie mam błąd podczas SxS można wygenerować kontekstu aktywacji: - brak błędów w dziennik systemu Windows (powinien oznaczać, że moja składnia jest poprawna) - brak błędu wykrytego przez sxstrace (log kończy się na "INFO: Generowanie kontekstu aktywacji powiodło się."Komunikat i nie zawiera błędu lub sucpicious wiadomość; zresztą, widzę, że mój manifest został prawidłowo załadowany)

Każdy pomysł

czy istnieje sposób do debugowania SXS głębiej że z sxstrace coraz listę rzeczywiście zarejestrowany? com lub CLR klas na przykład ???

Dziękuję według wcześniej

+0

Czy implementujesz dwa interfejsy? – wqw

+0

Edytowałem mój wpis, aby dodać pełną definicję idl IDialogManager, ICadWizardsManager i ICadWizard; które są interfejsami, które implementuję – loic

Odpowiedz

2

Zwykle podczas tworzenia kontekstu aktywacji w celu uzyskania bezpłatnej rejestracji COM zwykle występują co najmniej dwa manifesty.

Istnieje manifest EXE, który określa jego zależne złożenia, w tym zespół zawierający komponenty COM, a także manifest zespołu, opisujący biblioteki dll, klasy okien i obiekty COM w zespole.

This Blog zawiera informacje o tym, co oznacza .2. Zasadniczo, gdy system szuka manifestu, szuka modulename.exe [.resid] .manifest - W przypadku, gdy resid jest 1, jest pomijany.

Używasz więc MFC, co oznacza DevStudio, co oznacza, że ​​Twój projekt powinien już być skonfigurowany do automatycznego tworzenia zasobu RT_MANIFEST z ustawieniami c-runtime i common control 6 w nim.

Visual Studio 2005 obsługuje tej składni do łączenia elementów dependentAssembly z aplikacjami oczywistych bez konieczności spróbować połączyć XML bezpośrednio:

#pragma comment(linker, \ 
    "\"/manifestdependency:type='Win32' "\ 
    "name='client' "\ 
    "version='1.0.0.0' "\ 
    "processorArchitecture='*' "\ 
    "language='*'\"") 

Tak więc, jeśli dodać, że w KPP lub nagłówka w .exe, a następnie zapisz swój plik client.exe.2.manifest jako "client.manifest", powinieneś przejść wszystkie systemy.

6

prostym wytłumaczeniem jest to, że manifest plik nie jest używane. która jest wysoce prawdopodobne w tym scenariuszu .exe prawie z pewnością zawiera już manifest, osadzony jako zasób. Bardzo często aplikacja MFC do włączania stylów wizualnych. I dla kodu skompilowanego przez kompilatory VS2005 lub 2008, które osadzają manifest, aby znaleźć biblioteki DLL środowiska wykonawczego.

Aby to sprawdzić, użyj Plik + Otwórz + Plik i wybierz skompilowany plik .exe. Wyszukaj węzeł RT_MANIFEST. Jeśli system Windows znajdzie taki osadzony manifest, nie będzie kontynuował szukania pliku opartego na plikach. Musisz scalić swoje wpisy COM bez rejestracji w osadzone. Chciałbym dać ci dobry link do MSDN Library, ale dokumenty na temat manifestów zasysają poważny kamień.

+3

+1 dla użytecznej odpowiedzi; i dałbym +10 za "dokumenty dotyczące manifestów ssania poważnego rocka" :-) –

+0

Czy to jest ważne, nawet jeśli sxstracja zarejestrowała, że ​​mój manifest został poprawnie przeanalizowany? – loic

+0

Moim zdaniem, sstras wyraźnie wskazuje, że manifest jest rzeczywiście używany. O ile rozumiem, kiedy monitoruję obciążenie aplikacji (procmon) Wygląda na to, że system Windows szuka pliku client.exe.manifest __if nie ma RT_MANIFEST res__; w przeciwnym razie szuka pliku client.exe.2.manifest. Tak więc w moim umyśle stosuje się manifest "zewnętrzny", nawet jeśli osadzone manifesty istnieją – loic