使用C#创建COM扩展 - 是否值得?

时间:2022-08-30 00:05:39

I'm dealing with the following issue: a (third-party) software (Software A ) we are using extensively allows the programming of what it calls 'extensions' using a Component Object Model (COM) interface (actually several interfaces). It provides the MIDL files for these interfaces as well as a 'project template' for Visual C++ as part of an SDK (IDL files, headers and interfaces are already there, only the implementations for the interface functions are missing). To be comaptible, all extensions have to conform to (i.e. must implement) the given COM interface structure.

我正在处理以下问题:我们广泛使用的(第三方)软件(软件A)允许使用组件对象模型(COM)接口(实际上是几个接口)对其所谓的“扩展”进行编程。它提供了这些接口的MIDL文件以及作为SDK的一部分的Visual C ++的“项目模板”(IDL文件,标头和接口已经存在,只缺少接口函数的实现)。为了可以兼容,所有扩展必须符合(即必须实现)给定的COM接口结构。

However, as my familiarity with C++ is rather limited I was hoping to implement the COM in C# and .NET - on the other hand, the pre-defined interfaces make heavy use of pointers and custom data structures, so I'm wondering if I'm not better off implemementing the interfaces in their native C++ rather than trying to recreate everything in C#.

但是,由于我对C ++的熟悉程度相当有限,我希望在C#和.NET中实现COM - 另一方面,预定义的接口大量使用指针和自定义数据结构,所以我想知道我是否最好不要在他们的原生C ++中实现接口,而不是尝试在C#中重新创建所有东西。

A little more background maybe: the ultimate goal is to control a piece of custom hardware (via USB) from inside Software A. I have already written a small .NET app wrapping the driver (another third party software) using DLLimport, which was surprisingly painless. In other words, the COM object I am trying to build is essentially a bridge between (third-party) Software A and (third-party) device driver B, which must conform to the interface specifications given by A.

还有一点背景:最终目标是从软件A内部控制一块自定义硬件(通过USB)。我已经编写了一个使用DLLimport包装驱动程序(另一个第三方软件)的小型.NET应用程序,这令人惊讶无痛。换句话说,我试图构建的COM对象本质上是(第三方)软件A和(第三方)设备驱动程序B之间的桥梁,它必须符合A给出的接口规范。


sample MIDL code:

示例MIDL代码:

[ id(0x00000004)]
HRESULT GetWaveData([in] BSTR name, [out] IWaveData ** data );
[ id(0x00000005)]
HRESULT GetImageData([in] BSTR name, [out] IImageData ** data, [out] Palette * Palette );
[ id(0x00000006)]
HRESULT SetVariable([in] BSTR name, [in] IVariableData * variable );

4 个解决方案

#1


It's not really possible to answer this question without knowing the problem completely. But generally, I would go with the C++ route. By adding CLR to the world, you'll have to deal with interop issues and possibly handle with nasty pointer issues (since the nature of it is dealing with low level hardware related stuff) in C#. As a result, probably, your real choices are an unclean C# source or going with C++. I guess I'd choose the latter.

如果不完全了解问题,就不可能回答这个问题。但一般来说,我会选择C ++路线。通过向世界添加CLR,您将不得不处理互操作问题,并可能在C#中处理讨厌的指针问题(因为它的性质是处理低级硬件相关的东西)。因此,您的真正选择可能是不洁净的C#源或使用C ++。我想我会选择后者。

#2


Technically, you're not implementing the interfaces in C++ but MIDL. It's a separate interface language and it's worth knowing if you're going to do COM work.

从技术上讲,您不是在C ++中实现接口而是使用MIDL。它是一种单独的界面语言,值得知道你是否要做COM工作。

Anyway, it's not uncommon to use .NET interops to implement COM objects, but the two are not really compatible technologies. You WILL run into gotchas unless you're writing very simple objects.

无论如何,使用.NET interops来实现COM对象并不罕见,但这两者并不是真正兼容的技术。除非你写的是非常简单的对象,否则你会遇到陷阱。

To get you started, here's some random assortment of pointers along with a couple of articles that I've used in the past.

为了帮助您入门,这里有一些随机的指针以及我过去使用过的几篇文章。

  • COM is an interface-driven technology. Repeat that to yourself again and again.
  • COM是一种接口驱动的技术。一遍又一遍地对自己重复一遍。

  • Develop the interface definition separately, using MIDL.
  • 使用MIDL单独开发接口定义。

  • COM garbage collection is deterministic (reference counting), but this starts to fall apart when used with .NET, where the garbage collection happens automatically and unpredictably.
  • COM垃圾收集是确定性的(引用计数),但是当与.NET一起使用时,它开始崩溃,其中垃圾收集自动且不可预测地发生。

  • Dealing with Eventsinks/event handlers is ugly.
  • 处理Eventsinks /事件处理程序很难看。

A small taste of the type of headaches you'll run into: http://www.codeproject.com/KB/cs/LingeringCOMObjects.aspx

您将遇到的一小部分头痛:http://www.codeproject.com/KB/cs/LingeringCOMObjects.aspx

More on why you should NOT let Visual Studio auto-generate the COM interface for you: http://blogs.msdn.com/mbend/archive/2007/04/17/classinterfacetype-none-is-my-recommended-option-over-autodispatch-autodual.aspx

更多关于为什么你不应该让Visual Studio为你自动生成COM接口的原因:http://blogs.msdn.com/mbend/archive/2007/04/17/classinterfacetype-none-is-my-recommended-option-过autodispatch,autodual.aspx

Bridging events: http://www.west-wind.com/presentations/dotnetfromVfp/DotNetFromVfp_EventHandling.asp

桥接事件:http://www.west-wind.com/presentations/dotnetfromVfp/DotNetFromVfp_EventHandling.asp

#3


You should only use .NET for this purpose if it gives you advantages. For example, we once needed webservices invokation and support for it in .NET is much better, so we went that way. In your case the advantage is that you're more familiar with .NET and that might be worth choosing.

如果它为您提供了优势,那么您应该只为此目的使用.NET。例如,我们曾经需要webservices invokation,并且在.NET中对它的支持要好得多,所以我们采用了这种方式。在您的情况下,优势在于您更熟悉.NET并且可能值得选择。

However if you implement the COM object in .NET you will have to require .NET runtime an every machine where the object will have to be used. Plus you may have problems implementing interfaces that have custom types difficult to marshal.

但是,如果在.NET中实现COM对象,则必须要求.NET运行时使用必须使用该对象的每台机器。此外,您可能在实现难以编组的自定义类型的接口时遇到问题。

You need to compare the advantage - more familiarity in you case - with the technical burden you encounter - possible deployment and marshalling issues.

您需要比较优势 - 在您的情况下更熟悉 - 与您遇到的技术负担 - 可能的部署和编组问题。

My personal opinion is that the .NET path is only to be chosen if one needs functionality readily available there (like webservices invokation).

我个人认为,如果需要一个随时可用的功能(如webservices invokation),则只选择.NET路径。

#4


It sounds like the decision you're making is one of whether to go for a native application, or a .NET-based application.

听起来您正在做的决定是使用本机应用程序还是基于.NET的应用程序。

You need to think about the following:

您需要考虑以下事项:

  1. Deployment issues: where are you going to deploy this app? Is it something that will run on hundreds of workstations, or just a couple? How much control are you going to have over the machines on which it is installed? Remember that you're going to have to ensure that the correct version of the .NET platform is installed;

    部署问题:您要在哪里部署此应用程序?它会在数百个工作站或仅仅几个工作站上运行吗?您将对安装它的机器进行多少控制?请记住,您必须确保安装了正确版本的.NET平台;

  2. Maintenance issues: you're clearly more familiar with .NET, but who is going to look after the application in the long term? Are they going to be expected to be familiar with C++? Native development really is a different kettle of fish from managed development, since "housekeeping" is a very important part of it;

    维护问题:您显然更熟悉.NET,但是谁会长期照顾应用程序?他们会被期望熟悉C ++吗?由于“家务管理”是其中非常重要的一部分,因此本土开发实际上是与管理开发不同的鱼类。

  3. Third party dependencies: it sounds to me like you're trying to use a third party COM library to communicate with your device through USB. However, you've mentioned that you've written a .NET wrapper for the hardware driver--can you elaborate, since this is a little confusing. If possible, and if not too much hassle, don't introduce dependencies;

    第三方依赖:听起来像你试图使用第三方COM库通过USB与你的设备通信。但是,你已经提到你已经为硬件驱动程序编写了一个.NET包装器 - 你能详细说明一下,因为这有点令人困惑。如果可能的话,如果没有太多的麻烦,不要引入依赖;

  4. Resource constraints: if your app is going to be installed "in the wild", what are the constraints re hardware? Programming using an unmanaged environment allows you fine-grained control over how much memory your application will use, and how CPU-intensive it is--this is, of course, a trade-off against having a managed layer take care of that resource management.

    资源限制:如果您的应用程序将“在野外”安装,那么硬件的约束是什么?使用非托管环境进行编程允许您对应用程序将使用多少内存以及CPU密集程度进行细粒度控制 - 当然,这是对托管层负责管理资源管理的权衡。

In general, if you're developing an application where you don't need to deploy to thousands of users with disparate hardware configurations, I would choose the .NET platform. COM interop on .NET is relatively painless, and programming on a managed platform means that you can concentrate on what is important. If you've never programmed in an unmanaged environment before (C/C++), you're in for a bit of shocker.

通常,如果您正在开发一个不需要使用不同硬件配置部署到数千个用户的应用程序,我会选择.NET平台。 .NET上的COM互操作相对轻松,在托管平台上进行编程意味着您可以专注于重要的事情。如果您以前从未在非托管环境中编程(C / C ++),那么您会感到有些震惊。

#1


It's not really possible to answer this question without knowing the problem completely. But generally, I would go with the C++ route. By adding CLR to the world, you'll have to deal with interop issues and possibly handle with nasty pointer issues (since the nature of it is dealing with low level hardware related stuff) in C#. As a result, probably, your real choices are an unclean C# source or going with C++. I guess I'd choose the latter.

如果不完全了解问题,就不可能回答这个问题。但一般来说,我会选择C ++路线。通过向世界添加CLR,您将不得不处理互操作问题,并可能在C#中处理讨厌的指针问题(因为它的性质是处理低级硬件相关的东西)。因此,您的真正选择可能是不洁净的C#源或使用C ++。我想我会选择后者。

#2


Technically, you're not implementing the interfaces in C++ but MIDL. It's a separate interface language and it's worth knowing if you're going to do COM work.

从技术上讲,您不是在C ++中实现接口而是使用MIDL。它是一种单独的界面语言,值得知道你是否要做COM工作。

Anyway, it's not uncommon to use .NET interops to implement COM objects, but the two are not really compatible technologies. You WILL run into gotchas unless you're writing very simple objects.

无论如何,使用.NET interops来实现COM对象并不罕见,但这两者并不是真正兼容的技术。除非你写的是非常简单的对象,否则你会遇到陷阱。

To get you started, here's some random assortment of pointers along with a couple of articles that I've used in the past.

为了帮助您入门,这里有一些随机的指针以及我过去使用过的几篇文章。

  • COM is an interface-driven technology. Repeat that to yourself again and again.
  • COM是一种接口驱动的技术。一遍又一遍地对自己重复一遍。

  • Develop the interface definition separately, using MIDL.
  • 使用MIDL单独开发接口定义。

  • COM garbage collection is deterministic (reference counting), but this starts to fall apart when used with .NET, where the garbage collection happens automatically and unpredictably.
  • COM垃圾收集是确定性的(引用计数),但是当与.NET一起使用时,它开始崩溃,其中垃圾收集自动且不可预测地发生。

  • Dealing with Eventsinks/event handlers is ugly.
  • 处理Eventsinks /事件处理程序很难看。

A small taste of the type of headaches you'll run into: http://www.codeproject.com/KB/cs/LingeringCOMObjects.aspx

您将遇到的一小部分头痛:http://www.codeproject.com/KB/cs/LingeringCOMObjects.aspx

More on why you should NOT let Visual Studio auto-generate the COM interface for you: http://blogs.msdn.com/mbend/archive/2007/04/17/classinterfacetype-none-is-my-recommended-option-over-autodispatch-autodual.aspx

更多关于为什么你不应该让Visual Studio为你自动生成COM接口的原因:http://blogs.msdn.com/mbend/archive/2007/04/17/classinterfacetype-none-is-my-recommended-option-过autodispatch,autodual.aspx

Bridging events: http://www.west-wind.com/presentations/dotnetfromVfp/DotNetFromVfp_EventHandling.asp

桥接事件:http://www.west-wind.com/presentations/dotnetfromVfp/DotNetFromVfp_EventHandling.asp

#3


You should only use .NET for this purpose if it gives you advantages. For example, we once needed webservices invokation and support for it in .NET is much better, so we went that way. In your case the advantage is that you're more familiar with .NET and that might be worth choosing.

如果它为您提供了优势,那么您应该只为此目的使用.NET。例如,我们曾经需要webservices invokation,并且在.NET中对它的支持要好得多,所以我们采用了这种方式。在您的情况下,优势在于您更熟悉.NET并且可能值得选择。

However if you implement the COM object in .NET you will have to require .NET runtime an every machine where the object will have to be used. Plus you may have problems implementing interfaces that have custom types difficult to marshal.

但是,如果在.NET中实现COM对象,则必须要求.NET运行时使用必须使用该对象的每台机器。此外,您可能在实现难以编组的自定义类型的接口时遇到问题。

You need to compare the advantage - more familiarity in you case - with the technical burden you encounter - possible deployment and marshalling issues.

您需要比较优势 - 在您的情况下更熟悉 - 与您遇到的技术负担 - 可能的部署和编组问题。

My personal opinion is that the .NET path is only to be chosen if one needs functionality readily available there (like webservices invokation).

我个人认为,如果需要一个随时可用的功能(如webservices invokation),则只选择.NET路径。

#4


It sounds like the decision you're making is one of whether to go for a native application, or a .NET-based application.

听起来您正在做的决定是使用本机应用程序还是基于.NET的应用程序。

You need to think about the following:

您需要考虑以下事项:

  1. Deployment issues: where are you going to deploy this app? Is it something that will run on hundreds of workstations, or just a couple? How much control are you going to have over the machines on which it is installed? Remember that you're going to have to ensure that the correct version of the .NET platform is installed;

    部署问题:您要在哪里部署此应用程序?它会在数百个工作站或仅仅几个工作站上运行吗?您将对安装它的机器进行多少控制?请记住,您必须确保安装了正确版本的.NET平台;

  2. Maintenance issues: you're clearly more familiar with .NET, but who is going to look after the application in the long term? Are they going to be expected to be familiar with C++? Native development really is a different kettle of fish from managed development, since "housekeeping" is a very important part of it;

    维护问题:您显然更熟悉.NET,但是谁会长期照顾应用程序?他们会被期望熟悉C ++吗?由于“家务管理”是其中非常重要的一部分,因此本土开发实际上是与管理开发不同的鱼类。

  3. Third party dependencies: it sounds to me like you're trying to use a third party COM library to communicate with your device through USB. However, you've mentioned that you've written a .NET wrapper for the hardware driver--can you elaborate, since this is a little confusing. If possible, and if not too much hassle, don't introduce dependencies;

    第三方依赖:听起来像你试图使用第三方COM库通过USB与你的设备通信。但是,你已经提到你已经为硬件驱动程序编写了一个.NET包装器 - 你能详细说明一下,因为这有点令人困惑。如果可能的话,如果没有太多的麻烦,不要引入依赖;

  4. Resource constraints: if your app is going to be installed "in the wild", what are the constraints re hardware? Programming using an unmanaged environment allows you fine-grained control over how much memory your application will use, and how CPU-intensive it is--this is, of course, a trade-off against having a managed layer take care of that resource management.

    资源限制:如果您的应用程序将“在野外”安装,那么硬件的约束是什么?使用非托管环境进行编程允许您对应用程序将使用多少内存以及CPU密集程度进行细粒度控制 - 当然,这是对托管层负责管理资源管理的权衡。

In general, if you're developing an application where you don't need to deploy to thousands of users with disparate hardware configurations, I would choose the .NET platform. COM interop on .NET is relatively painless, and programming on a managed platform means that you can concentrate on what is important. If you've never programmed in an unmanaged environment before (C/C++), you're in for a bit of shocker.

通常,如果您正在开发一个不需要使用不同硬件配置部署到数千个用户的应用程序,我会选择.NET平台。 .NET上的COM互操作相对轻松,在托管平台上进行编程意味着您可以专注于重要的事情。如果您以前从未在非托管环境中编程(C / C ++),那么您会感到有些震惊。