7

我构建了一个使用两个 COM 服务器 dll 的 COM 客户端应用程序;我希望这个应用程序在没有 COM 注册的情况下运行 - 即:winsxs / .manifests

当我尝试从我的客户端应用程序创建我的 COM 对象的实例时,我收到一个(...几乎预期的...)“类未注册”消息。

我以前已经成功过这种配置,但我不知道为什么这个配置会失败。


这里还有一些细节:

  • 我拥有的模块:
    • 一个依赖于 2 个 COM 服务器(dll1.dll 和 dll2.dll)的 MFC 客户端
    • dll1.dll COM 服务器依赖于 dll2.dll
    • dll2.dll 没有 COM 依赖

我拥有的 COM 对象:

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

-

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

-

  • 客户电话

-

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>

-


在 sxs 激活上下文生成过程中我没有错误: - windows 日志中没有错误(应该意味着我的清单语法是正确的) - sxstrace 没有检测到错误(日志以“信息:激活上下文生成成功。”消息结尾并且不包含错误或可疑消息;此外,我看到我的清单已正确加载)

任何想法?

有没有办法用 sxstrace 更深入地调试 sxs?例如,获取实际注册的 com 或 clr 类的列表???

提前谢谢你

4

2 回答 2

6

简单的解释是 .manifest 文件没有被使用。在这种情况下,您的.exe可能已经包含一个作为资源嵌入的清单。MFC 应用程序启用视觉样式非常常见。对于由 VS2005 或 2008 编译器编译的代码,它们嵌入了一个清单以查找运行时 DLL。

要验证这一点,请使用 File + Open + File 并选择已编译的 .exe 文件。查找 RT_MANIFEST 节点。如果 Windows 找到这样的嵌入式清单,它不会继续寻找基于文件的清单。您需要将您的 regfree COM 条目合并到嵌入式条目中。我希望我能给你一个很好的 MSDN 库链接,但是关于清单的文档很糟糕。

于 2011-02-16T18:44:49.057 回答
2

在为免注册 COM 构建激活上下文时,通常至少涉及两个清单。

有一个 EXE 清单,它指定了它的依赖程序集,包括包含 COM 组件的程序集,还有一个程序集清单,描述了程序集中的 dll、窗口类和 COM 对象。

此博客包含有关 .2 含义的信息。基本上,当系统查找清单时,它会查找 modulename.exe[.resid].manifest - 如果 resid 为 1,则将其省略。

因此,您正在使用 MFC,这意味着 DevStudio,这意味着您的项目应该已经配置为自动生成 RT_MANIFEST 资源,其中包含 c-runtime 和 common control 6 设置。

Visual Studio 2005支持这种语法来将dependentAssembly 元素与您的应用程序清单合并,而无需尝试直接合并 XML:

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

因此,如果您将其添加到 .exe 中的 cpp 或标头中,然后将您的 client.exe.2.manifest 保存为“client.manifest”,那么您应该可以使用所有系统。

于 2011-02-17T20:11:11.593 回答