我一直在讨论这个问题已经有一段时间了,我已经接近得出结论,我想要做的事情是不可能的,但是我想给Stack Overflow的人们一个机会,希望在此之前证明我错了继续采用替代战略。
我想做什么 我的项目是一个.NET程序集,它作为ActiveX控件(控件A)向COM公开,旨在在浏览器中运行。它依赖于我试图通过Control A的免费注册COM使用的第三方ActiveX控件(Control B)。
所以希望的堆栈看起来像这样:
Internet Explorer
[COM]
Ax Control A(我的控制)
[Reg-Free COM]
Ax Control B(第三方)
为什么我要尝试这样做 我想使用免注册COM,因为与使用Control B的另一个应用程序的版本控制冲突结合了Control B没有正确实现版本控制的事实(两个不兼容的版本存在相同的GUID)。免注册COM似乎是将两个版本的Control B相互隔离的唯一可行方法。
我不需要浏览器通过免注册COM调用我的控件(控件A),我只是计划使用正常的机制。
到目前为止我做了什么 鉴于浏览器是运行整个堆栈的最终应用程序,并且让用户为Internet Explorer添加清单文件是不切实际或不可取的,我的方法是将清单嵌入到控件A中以使其成为可能。使用免注册COM调用Control B.
我已设法将清单嵌入到Control A中,并使用第三方工具来验证它是否确实已嵌入。为了简化我的测试,我将浏览器排除在外,并从一个简单的C#表单应用程序中测试了免注册COM。但是,我似乎无法在该环境中使用免注册COM。
出于测试目的,我使用我在控件A中嵌入的信息为测试表单应用程序创建了一个清单,在该配置中,无论是否注册了Control B,它都能正常工作。如果我的应用程序将在该测试应用程序而不是浏览器中运行,那么这很棒。我做了这个测试只是为了确认我嵌入的清单是正确的,我相信我已经确认了。
什么不起作用 测试Windows窗体应用程序运行完美并显示控件A和(嵌套)控件B,而控件B已注册。但是,当我取消注册Control B并尝试依赖免注册COM时,应用程序会立即抛出此错误(UFV = Control A):
Description: The process was terminated due to an unhandled exception.
Exception Info: System.Runtime.InteropServices.COMException
Stack:
at System.Windows.Forms.AxHost.CreateInstance()
at System.Windows.Forms.AxHost.GetOcxCreate()
at System.Windows.Forms.AxHost.TransitionUpTo(Int32)
at System.Windows.Forms.AxHost.CreateHandle()
at System.Windows.Forms.Control.CreateControl(Boolean)
at System.Windows.Forms.Control.CreateControl(Boolean)
at System.Windows.Forms.AxHost.EndInit()
at UniversalFileViewer.UFV.InitializeComponent()
at UniversalFileViewer.UFV..ctor()
at TestFormsProject.TestForm.InitializeComponent()
at TestFormsProject.TestForm..ctor()
at TestFormsProject.Program.Main()
我的问题
(1)我在错误的树上吠叫?也就是说,甚至可以在堆栈中间使用无注册的COM,就像我正在尝试一样,或者清单是否必须嵌入EXE文件本身(或清单文件中)?
(2)如果无法做到这一点,为什么清单合并工具(MT.EXE)甚至允许你将一个清单嵌入到DLL文件中?
(3)如果有可能,我在某个地方错过了一步吗?这样做有诀窍吗?