【问题标题】:C# - Hook into existing COM objectC# - 挂钩到现有的 COM 对象
【发布时间】:2010-12-06 11:46:08
【问题描述】:

假设我们有一个现有的进程(或应用程序),它从诸如“MyCOMLibrary.ocx”之类的 ocx 文件调用 COM 对象。

有没有办法编写一个 C# 库来精确复制 ocx 文件?让原始应用程序可以调用您的 C# 代码而不是原始 COM 对象?

当然,您必须使用与原始 ocx 相同的 CLSID 和 ProgID。并假设不涉及签名,例如 .Net 世界中的 SNK。

另外,是否有任何工具可以自动执行此操作?接受一个 ocx 并输出一个 C# 文件,其中包含要实现的方法。

编辑:我想补充一点,原始应用程序是 VB6,根本不使用 .Net。他们很可能将 ocx 加载为 VB6 应用程序(ProgId 或 Guid)。这会导致任何问题吗?

我们完全重写 ocx 也没有问题——我们很可能只返回所有方法的成功错误代码,并且只使用我们情况所需的方法/事件。

编辑:您会认为这不会太难完成。我们能否制作一个可以替换旧 ocx 的 VB6 ocx 文件,并将所有调用传递给 .Net 程序集?

编辑:我尝试使用以下开源库:EasyHook

但似乎这个问题应该仍然可行。 VB6 似乎以防止挂钩的方式加载 COM 对象。我没有看到使用 EasyHook 在类/接口或类的构造函数上挂钩实例方法的方法。

【问题讨论】:

  • 你的建议是可能的,但很危险。您将为任何应用程序替换此控件。除非您尝试破解某些东西,否则我不建议这样做,我也不建议这样做。 :)
  • 我们正在尝试模拟硬件设备以与旧的销售点应用程序进行互操作。为 PC 全局替换此 ocx 不会有任何问题。

标签: c# .net com interop hook


【解决方案1】:

您可以使用 ActiveX Import AxImp 来导入 OCX,创建一个包装类,然后调用它。该程序在此处描述:http://msdn.microsoft.com/en-us/library/8ccdh774(VS.80).aspx 基本上,您需要做的是在命令提示符上执行以下操作:

c:/>AxImp MyControl.ocx

结果是一个 MyControl.dll 和一个 AxMyControl.dll。第一个您可以在项目中用作普通的 .NET DLL(即,没有图形用户界面),第二个可以用于在表单上绘制,就像您通常使用任何其他控件(如 TextBoxLabel.

要使用它,请转到 Visual Studio,右键单击您的项目并选择添加引用。浏览到新创建的 DLL 并添加它。就是这样。

【讨论】:

  • TlBimp.exe,做同样的事情而不吐出 ActiveX 控件。您确实意识到,我正在尝试替换 COM 对象而不是调用它,对吗?我可以看到我可以在 Reflector 中打开生成的 Interop.??.dll 并将其导出为 C# 文件以实现这些方法。这是你的意思吗?
  • 如果您有源代码,您只能完全替换二进制 COM 对象(即,没有包装器):将其转换为 .NET。 .NET 体系结构和 COM 非常不同。您可以使用 .NET 创建 COM,也可以为 .NET 导入 COM。但是 COM 二进制文件本身在任何方面都不符合 CLR,并且不能在不重写的情况下转换为 .NET 本身。
  • On:“有没有办法编写一个 C# 库来精确复制 ocx 文件”答案是:是的,但只能作为完全重写(使用 ComVisible 等人)。可以将 OCX 和包装器添加为资源,并通过注册到 ``AssemblyLoad 事件来转移 AppDomain 程序集加载过程。但这变得非常复杂,需要深入了解Domain、程序集加载以及可能的动态 OCX 包装。
  • 现有应用程序是 VB6,除了在我们的类上使用 ComVisible、Guid、ProgId 和使用 RegAsm 注册我们的程序集(当然我们会取消注册原始程序集)之外,我们还需要什么。我们还没有让这个工作。
  • 有一些帖子讨论了整个过程。这是一个:foxsys.blogspot.com/2007/03/…你完成了所有这些步骤吗?
【解决方案2】:

我们的 Deviare 挂钩库可用于挂钩 COM 对象。您可以从我们的博客中看到与此主题相关的文章:Hooking Outlook COM objects with Deviare

【讨论】:

    【解决方案3】:

    显然是 VBMigration 合作伙伴can automatically upgrade a VB6 COM component to a VB.Net component that has binary compatibility with the original VB6 component。我不知道它是否支持OCXs。如果是这样,我建议先使用它,然后再尝试使用 C#(如有必要)。

    【讨论】:

      【解决方案4】:

      这个问题并不是一个完整的答案,但我认为可能会有用。如果您在要替换的对象的 CLSID 下添加一个名为“TreatAs”的键,并将默认值设置为您要创建的对象的 CLSID,这会指示 COM 运行时创建您的对象而不是原始对象.然后无需强制您的新替换对象具有与旧对象相同的 CLSID 和 ProgID。

      例如,如果您的原始对象具有 ProgID“MyComLibrary.Object”和 CLSID“{ABC}”,而您的新对象具有 ProgID“MyDotNet.Object”和 CLSID“{123}”,则在 HKLM/CLSID/ {ABC} 添加一个名为 TreatAs 的键,默认值为 {123}。然后对“MyComLibrary.Object”或“MyDotNet.Object”的任何请求都将获得新对象的副本(假设它们实现相同的接口)。

      【讨论】:

      • 在我们的最终解决方案中,我们实现了一个二进制兼容的 C# COM 对象,并使用 Reg-Free COM 为目标应用程序设置它。所以我们的目标应用程序通过 COM 加载我们的程序集,认为它仍在与原始 COM 对象通信。
      猜你喜欢
      • 2010-12-29
      • 1970-01-01
      • 1970-01-01
      • 2019-06-12
      • 1970-01-01
      • 1970-01-01
      • 2013-05-18
      • 2011-09-16
      • 1970-01-01
      相关资源
      最近更新 更多