Question

J'ai construit une application client COM qui utilise deux DLL de serveur COM; Je veux que cette application fonctionne sans enregistrement com - c'est-à-dire: winsxs / .manifests

Je reçois un (... presque attendu ...) message "Classe non enregistrée" lorsque j'essaie de créer une instance de mon objet COM à partir de mon application client.

J'ai déjà réussi ce genre de configuration avant, mais je ne peux pas comprendre pourquoi celui-ci échoue.


Voici quelques détails de plus:

  • les modules que j'ai:
    • Un client MFC qui dépend de 2 serveurs COM (DLL1.DLL et DLL2.DLL)
    • dll1.dll com Server dépend de DLL2.DLL
    • dll2.dll n'a aucune dépendance COM

      Les objets COM J'ai:

      • dans dll1.dll (language .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;
        };
        

        -

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

          -

          • L'appel client

            -

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

            -

            • le 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>
              

              -


              Je n'ai aucune erreur pendant la génération de contexte d'activation SXS: - Aucune erreur dans le journal Windows (devrait signifie que ma syntaxe manifeste est correcte) - Aucune erreur détectée par SxSTRace (le journal se termine par "INFO: la génération de contexte d'activation a réussi." Message et ne contient aucune erreur ni message impicicieux; d'ailleurs, je vois que mon manifeste est chargé correctement)

              aucune idée?

              Y a-t-il un moyen de déboguer SXS plus profond que avec SxStrace? Obtenir la liste des classes COM ou CLR réellement enregistrées par exemple ???

              Merci d'avance

Était-ce utile?

La solution

There are usually - at least - two manifests involved when building the activation context for registration free COM.

There is the EXE manifest, that specifies its dependent assemblies, including the assembly containing the COM components, and there is the assembly manifest, describing the dll's, window classes, and COM objects in the assembly.

This Blog contains information about what the .2 means. Basically, when the system looks for a manifest, it looks for modulename.exe[.resid].manifest - In the case that resid is 1, it is omitted.

So, you are using MFC, which means DevStudio, which means that your project should already be configured to produce a RT_MANIFEST resource automatically with the c-runtime and common control 6 settings in it.

Visual Studio 2005 supports this syntax to merge dependentAssembly elements with your applications manifest without having to try and merge XML directly:

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

So, if you add that to a cpp or header in your .exe, and then save your client.exe.2.manifest as "client.manifest", you should be all systems go.

Autres conseils

The simple explanation is that the .manifest file isn't being used. Which is highly likely in this scenario, your .exe almost certainly already contains a manifest, embedded as a resource. Very common for a MFC app to enable visual styles. And for code compiled by the VS2005 or 2008 compilers which embeds a manifest to find the runtime DLLs.

To verify this, use File + Open + File and select the compiled .exe file. Look for the RT_MANIFEST node. If Windows finds such an embedded manifest it isn't going to continue looking for a file-based one. You need to merge your regfree COM entries into the embedded one. I wish I could give you a good MSDN Library link but the docs about manifests suck serious rock.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top