从.NET注册免费激活本机COM(activex)组件

我有一个本地dll(这是一个ActiveX控件),我需要使用我的.NET应用程序,而不必注册该DLL在registry中。

我已经阅读了几个关于注册免费激活的深度post,其中一些更好

史蒂夫·怀特(Steve White)和莱斯利·穆勒(Leslie Muller)

这个从塞缪尔杰克

另一个来自Mike Makarov

从我所能看到的是可能的。 然而,几个小时和几百个testing后,我只是不能得到它的工作。 在我的职业生涯中,我已经做了一些PInvoking,甚至在.NET中使用ActiveX控件,所以如果任何人有任何可能在此之前踢过目标的意见,我会很感激。

到目前为止,我遵循Steves的build议,就构build一个可以工作的应用程序而言,然后试图通过反复运行regsvr32命令来添加和删除registry中的非托pipeDLL来制定获胜的清单文件语法。 只是一个简单的.Net控制台应用程序与约10行代码…

我感到困惑的一个部分是互操作性。 本机DLL的我也与托pipe运行时可调用包装(RCW的)。 在我的.NET应用程序中,我添加了对这些RCW的引用,然后可以使用非托pipedll提供的相应类和function。 我不是通过dllimport PInvoking。

在创build清单文件时,我不确定是否需要担心这些RCW以及它们如何在免注册的情况下工作,或者即使它们需要在编译的输出中。

我也尝试过几种工具,比如(OLE / COM对象查看器,Windows SDK中的Mt.exe和codeproject中的regsvr42)。 但是清单结构和必要的GUID在工具和post之间都是不同的。

当前状态是我收到一个InvalidCastException “无法将typesSystem .__ ComObject的COM对象转换为MyFunkyDllLib.FunkyDllControltypes的接口。此操作失败,因为IID'{某种guid}'接口的COM组件上的QueryInterface调用失败到以下错误:库未注册。

任何人都可以确认应用程序和dll清单文件的正确语法? 在线职位甚至不同的名称与一些使用sxs的名字….

更新1:虽然乔的回答下面没有工作,它给了我一些更好的见解免费的COM。 在Interop dll(从开发机器上已安装的COM组件列表中添加到项目引用中)的属性中,我将Isolated属性更改为True。 这使VS转储COM DLL的副本(而不是互操作,它被embedded在EXE)的bin \ debug文件夹的效果。 VS也会创build一个myapplication.exe.manifest。

在这个清单文件被认为是足够的信息reg免费com。 我发现其他职位表示成功与此方法,但在我的情况下,我仍然结束了相同的InvalidCastException

再读一遍塞缪尔·杰克斯(Samuel Jacks)的post,我尝试了在Isolated=true时使用VStudio输出清单中的clsid信息创buildexe和COM DLL的清单。 (我也从exe.manifest中删除了由VS创build的<file/>部分)。 注销registry后,我现在已经成功! 应用程序启动并不会出错。 为什么这种方法有效,而不是Isolated=true我不知道,因为它超出了我对舱单和集会的知识。

不过我们还是不在托奇城堡呢。

现在我回到我在这个线程上发布的同一个问题。 但是在这种情况下unit testing不涉及。 只是一个简单的控制台应用程序与10行代码。 在正常的注册COM模式下工作正常,但不处于免注册模式。

Solutions Collecting From Web of "从.NET注册免费激活本机COM(activex)组件"

经过几个小时的反复试验,我终于找到了如何成功实现RegFree COM的解决方案。 这是一个完整的解释,帮助别人。

  1. 我在VS中创建一个新的.NET类库
  2. 右键单击引用并选择感兴趣的COM组件。 (注意:要使COM在列表中可见,必须在开发机器上注册,这可以通过使用Windows附带的Regsvr32.exe工具来实现,调用“regsvr32 mycomdll.dll”将其注册到Windows注册表中)
  3. 右键单击COM引用,转到属性,然后设置Isolated = True。 这会导致VS输出一个.manifest文件,该文件应该包含消耗.exe所需的所有注册表详细信息,以了解要加载哪些资源,而不是查询注册表。 但在我的情况下,这是不完整的。 调用Interop方法是可行的,但来自COM组件的事件不会。 请参阅第5步以获得解决方案)
  4. 建立这个项目。 .manifest应该出现在构建输出中。
  5. 在记事本或类似的打开清单。 在<assembly />标签内,我需要添加一个带有适当的IIDtlbidproxyStubClsid32 GUID元素的<comInterfaceExternalProxyStub />标签。 清单的元素记录在msdn上 。 在我的情况下,代理/存根是proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"/>这是内置的Windows代理。 我最初通过Process Monitor发现了iid和tlbid,同时调用了regsvr32。 我后来发现一个更简单,更可靠的选项是使用像SxS清单制造商这样的工具,因为它添加了我原来没有的第二个<comInterfaceExternalProxyStub />
  6. 在VS中创建一个exe项目并引用先前构建的库。
  7. 建立exe项目。
  8. 运行regsvr32 / u mycomdll.dll。 删除所有注册表关联。
  9. 运行该exe文件。 在我的情况下,类库中COM组件的调用和事件完美地工作。

注意事项:我不知道VS为什么不在.manifest中自动包含<comInterfaceExternalProxyStub />元素。 在编写的时候,自动更新清单的唯一方法是在VS中添加一个后期构建任务。 在我的情况下,我将整个XML清单复制到类库项目中的XML中,然后只是覆盖构建输出中的.manifest文件。

COM的单元(集成)测试不一致。 目前在我的情况下调用互操作方法的工作,但事件不。 这与Test Runner没有编译依赖的知识有关,因此在激活上下文中不存在。

你可能错过了一个typelib声明…但现在忽略了…相反,执行以下操作…

在打开和关闭一段时间后,我决定最简单的方法是使用MSBuild和GenerateApplicationManifest任务。 我一直在使用它与一个非托管的应用程序,但我不明白为什么它不适用于托管的应用程序。 我说“应用程序”…因为我的应用程序是托管的,但我有ComVisible类的COM库和.NET程序集。

从你的描述中,听起来好像你正在处理COM,而不必担心从COM使用.NET程序集。 您可以谷歌MSBUILD和GenerateApplicationManifest获得一个示例MSBuild文件。

所以,我假设你不需要填充任务的“Dependencies”属性。 您需要使用您的COM DLL列表来填充“IsolatedComReferences”属性。 他们可以是一个简单的分号分隔列表,但通常他们在MSBuild项目文件中的“ItemGroup”声明。 COM DLL需要在生成清单的时候注册。

至于你的RCW,没有什么特别的你需要做的。 海事组织,他们不需要在清单。 只要与你的应用程序/ DLL在同一个目录下,.NET就可以找到它们。

如果您使用MSBuild,则不必为您的COM DLL生成清单…他们可能已经有清单了…通常,向导自动生成清单并嵌入它们。 唯一需要COM类型信息的清单是您使用MSBuild生成的清单。

以这种方式使用的清单的全部重点是使用将在注册表中的所有COM信息来填充清单空间。