在.NET中释放COM对象的“所有权”

时间:2012-05-02 16:16:25

标签: c# vb.net com

我有一个客户/合作伙伴正在尝试使用我们公开的COM功能将他们的应用程序与我们的应用程序链接。到目前为止,他们有一个COM对象代表我们软件包的一个实例,然后使用我们的COM方法根据用户在应用程序中的操作以编程方式为用户构建一些东西。它本质上是一个“导出”功能。

他们要求我做什么,我无法解决该怎么做是允许用户决定何时关闭实例。我的意思是当我们的软件包被加载时,它是可见的并且被用户与之交互。完成后,他们会自然地点击右上角的十字架退出软件。这不起作用,因为COM对象在其应用程序中仍处于“活动状态”。我们的软件包只能通过终止任务管理器中的进程来关闭,同时通过COM加载它的应用程序仍然打开。一旦他们的申请退出,我们的申请将自动关闭。由于COM调用,似乎他们的应用程序“拥有”我们的应用程序。

我在C#中制作了一个快速演示应用,尝试使用像Marshal.FinalReleaseComObject(myObject)这样的东西无济于事。

我意识到使用COM来实现这种目的并不是它的目的,但希望有某种解决方法吗?客户/合作伙伴正在使用VB.NET,但C#很好。

1 个答案:

答案 0 :(得分:3)

您遗漏了一些关于您自己的应用程序的重要信息,包括最重要的是如何实现您向客户端应用程序公开的COM接口。您的描述的一个方面对我来说是一个红旗是您的应用程序的实例化。你说客户端应用程序是“使用VB通过引用我们的exe来启动一个新进程”。如果您正确实现并注册了COM服务器,则不需要这样做。让我告诉你我将用来完成你所要求的架构,希望这对你有用。

首先,如果要在单独的进程中提供COM对象,正确的方法是实现COM进程外服务器。使用进程外服务器,当客户端通过COM请求您的某个接口时,COM将自动启动您的应用程序。进程外服务器的部分实现要求是在最后一个COM客户端释放其最后一个接口指针时自动关闭。

为了从进程外服务器公开用户界面,您需要使用消息循环生成单独的单线程单元(STA)线程。这将允许您关闭STA线程上的任何窗口,包括主窗口,而不会杀死您的COM服务器。那是因为COM服务器实现将运行它自己的多线程公寓(MTA)消息循环线程,以支持COM调用proc调用。 MTA线程是主应用程序线程,服务器将在最后一个客户端接口发布时关闭它。

当接口保持未释放状态时,COM服务器不应关闭。这意味着客户端应用程序有责任正确释放接口。但是你的.NET测试框架应该这样做了,所以看起来你的实现是不对的。

假设您遵循此指南,您将需要一个计划来处理最后一个客户端界面发布但仍有开放UI窗口的场景。一旦正确设置了所有内容,这应该不是主要问题。例如,您可以在UI打开时简单地引用自己的某个接口,这样可以防止MTA关闭。