如何从 C# 等托管代码中为 ActiveX 组件使用嵌入式免注册清单?

Posted

技术标签:

【中文标题】如何从 C# 等托管代码中为 ActiveX 组件使用嵌入式免注册清单?【英文标题】:How to use embedded registration-free manifest for ActiveX component from managed code like C#? 【发布时间】:2014-02-21 02:42:44 【问题描述】:

我想使用未在系统范围或用户范围内注册的特定版本的 ActiveX 组件。如果我使用清单文件,一切都会按预期工作。但是嵌入式清单仅适用于 C++ 客户端代码。

这里是依赖声明

<dependency>
  <dependentAssembly>
    <assemblyIdentity type="win32" name="MapWinGIS.ocx" version="4.9.1.0" />
  </dependentAssembly>
</dependency>

如果我使用 SxStrace,我会看到以下内容

INFO: Parsing Manifest File C:\OSGeo4W\bin\TestApplication.exe.
    INFO: Manifest Definition Identity is MyApplication.app,version="1.0.0.0".
    INFO: Reference: MapWinGIS.ocx,type="win32",version="4.9.1.0"
INFO: Resolving reference MapWinGIS.ocx,type="win32",version="4.9.1.0".
    INFO: Resolving reference for ProcessorArchitecture MapWinGIS.ocx,type="win32",version="4.9.1.0".
        INFO: Resolving reference for culture Neutral.
            INFO: Applying Binding Policy.
                INFO: No binding policy redirect found.
            INFO: Begin assembly probing.
                INFO: Did not find the assembly in WinSxS.
                INFO: Attempt to probe manifest at C:\OSGeo4W\bin\MapWinGIS.ocx.DLL.
                INFO: Attempt to probe manifest at C:\OSGeo4W\bin\MapWinGIS.ocx.MANIFEST.
                INFO: Attempt to probe manifest at C:\OSGeo4W\bin\MapWinGIS.ocx\MapWinGIS.ocx.DLL.
                INFO: Attempt to probe manifest at C:\OSGeo4W\bin\MapWinGIS.ocx\MapWinGIS.ocx.MANIFEST.
                INFO: Did not find manifest for culture Neutral.
            INFO: End assembly probing.
    ERROR: Cannot resolve reference MapWinGIS.ocx,type="win32",version="4.9.1.0".
ERROR: Activation Context generation failed.

显然,无论如何它只需要 DLL。问题是我从 AxImp 获得的 DLL 没有嵌入式清单。有没有使用嵌入式清单的好方法?我觉得我可以尝试让 mt 将一个嵌入到我从 AxImp 获得的 DLL 中,但这似乎很老套。

附:我不确定将 ocx 重命名为 dll 是否是一个好方法,因为 AxImp 也会为 COM 内容生成同名 DLL,而且看起来没有标志可以为 COM CLR 代理显式提供输出名称。

【问题讨论】:

【参考方案1】:

您的清单缺少基本条目,例如 &lt;comClass&gt;。这就是为什么您会看到 Windows 继续寻找另一个清单以找到它需要的内容。您找到的解决方法不是很好,它将清单条目放在错误的文件中。它应该在 EXE 的清单中。

做到这一点的聪明方法是让构建系统处理这个问题。注册 .ocx 并将引用的 Isolated 属性设置为 True。这将使构建系统从注册表中读取所需的清单条目并将它们合并到应用程序清单中。

如果您出于某种原因不想让 .ocx 保持注册状态,那么只需执行一次。在构建目录中找到 .manifest 文件。使用文本编辑器打开它并将条目复制/粘贴到您的应用清单中。请注意,这可能会调用 DLL Hell,如果您更新 COM 服务器,那么您的清单将会过时。总是很难排除故障,因为这将在一两年后发生,并且可能会发生在一个不知道你做了什么的程序员身上。

【讨论】:

comClass 条目嵌入到 OCX 资源的清单中。仅在 C++ 客户端的清单中具有依赖关系就足够了。在 EXE 中放置带有 TLB 内容的清单似乎有点奇怪。会尝试,但我想应该可以。尽管关于第 2 段和第 3 段,我有点迷失了。如果OCX注册了,我为什么要关心Isolated?如果我设置Isolated,我为什么要将带有TLB 内容的清单从OCX 复制到CLR EXE 中。我不介意在开发机器上注册,但不介意在部署机器上注册。 您在注册时关心隔离。在部署机器上。它只需要在您的开发机器上注册,以便可以自动确定清单条目。就像你对 mt.exe 所做的一样 我是否只是将生成的清单文件添加到项目中以便嵌入?同样奇怪的是,只有当 OCX 本身作为参考添加时才可以设置 Isolated。这样就不能传递像tlbimp 这样的选项,例如命名空间。【参考方案2】:

嗯……诀窍

regsvr32 MapWinGIS.ocx
AxImp MapWinGIS.ocx
mt -inputresource:MapWinGIS.ocx;#2 -outputresource:MapWinGIS.dll;#2
regsvr32 /u MapWinGIS.ocx

为我工作。虽然看起来并不整洁。有没有办法不将嵌入式清单复制到 CLR 代理和中间注册中?

【讨论】:

你有没有得到这个工作?我正在尝试和 MapWinGIS 做同样的事情。 保罗,那是很久以前的事了。我在我的 OSGeo4W bin 文件夹中看到了一些 MW GIS TestApp,它从那里开始,所以它按照 Hans 的建议工作,因为隔离设置为 true 并且 VS 抱怨它没有注册。如果不介意在开发人员的机器上注册 OCX,我认为这种方法是可行的。我没有尝试按用户注册。然而,我最初的想法是使用 CMake 作为非特权用户进行静默构建。如果它对 MW 过于具体,这里是phorum thread for that stuff。

以上是关于如何从 C# 等托管代码中为 ActiveX 组件使用嵌入式免注册清单?的主要内容,如果未能解决你的问题,请参考以下文章

C# .Net 4.0 应用程序中托管的 C++ ActiveX 控件中的 Xml.Serializer 非法强制转换异常

C#:如何在 Blazor Wasm 托管中将动态 Razor 组件从服务器发送到客户端?

如何将字节数组从 c# 传递到 MFC ActiveX

从 C# 引用不同的 ActiveX 版本作为一个

如何从托管项目中引用本机 WinRT 组件?

如何在托管代码(C#)中从本机代码(C++)获取字符串数组