2010-08-24 63 views
3

尝试通过其他.NET应用程序使用COM可见.NET类,并得到例外:Marshal.ReleaseComObject的抛出异常

消息:该对象的类型必须是 __ComObject或__ComObject的。

参数名:○

堆栈跟踪:在 System.Runtime.InteropServices.Marshal.ReleaseComObject(对象 O)

类如下所示:

[ComVisible(true)] 
[InterfaceType(ComInterfaceType.InterfaceIsDual)] 
public interface IViewer : IComInteropDefinedInterface 
{ 
} 

[ClassInterface(ClassInterfaceType.None)] 
[ComVisible(true)] 
[Guid("[some guid]")] 
public class MyViewer : UserControl, IViewer  
{ 
    //IViewer implementation 
} 

我注册的组件:

regasm [Assembly Path] /tlb /codebase 

客户端应用程序也在.NET中实例化了给定的类,但是当他调用Marshal.ReleaseComObject()时,它会得到上述异常。

解决此问题的任何想法?

编辑: 不幸的是,我不能提供实例化我的对象的客户端应用程序代码。但是我知道客户端使用相同的方法来实例化实际的COM对象。

+0

您可以包括在您的实例化对象和你在哪里调用'ReleaseComObject'过的代码?什么类型的对象你释放?它似乎不是一个COM对象。另外:在这种情况下你想使用COM的原因是什么?如果不使用COM,使用.NET的.NET程序集会更容易(实际上,我怀疑您已经这么做了;-) – 2010-08-24 08:27:59

+0

您可以发布客户端代码,很高兴看到组件是如何实例化的 – 2010-08-24 08:28:40

+0

不幸的是,我无法提供实例化我的对象的客户端应用程序代码。但是我知道客户端使用相同的方法来实例化实际的COM对象。 – Aaron 2010-08-24 08:51:03

回答

0

但你如何创建类实例?简单地使用表达式new MyViewer()不会创建COM对象。相反,它会创建一个普通的.Net对象,它不能与ReleaseComObject方法一起使用。

根据您的示例代码,特别是关于具有实现的MyViewer的行,听起来不像是在处理COM对象。相反,它看起来像你有一个实现COM接口的托管对象。

为了使用ReleaseComObject,你需要实际拥有一个COM/RCW对象。

+0

如果包含'MyViewer'的程序集被添加为COM引用,那么您是不是应该使用new MyViewer()来获得COM对象(而不是普通的旧.NET对象)?我想不出为什么要这样做,但它可能是可能的。 – 2010-08-24 08:35:33

+0

@ 0xA3是,如果这种类型是PIA中的一个CoClass(至少AFAIK)。但在这种情况下,它只是一个普通的旧管理对象,所以新事物并没有做任何特别的事情。 – JaredPar 2010-08-24 08:37:16

+0

不COM注册.NET类的意思是有一个对象,实现所有基本的COM功能,包括发布? – Aaron 2010-08-24 11:05:55

0

我的猜测是你实际上不使用COM,而只是使用一个被引用的.NET类。如果您的项目包含像

MyViewer viewer = new MyViewer(); 

代码,并已添加不作为COM参考,你实际上没有使用COM含MyViewer库。

2

最近,当将本地COM重新实现为托管代码时,我遇到了此问题。 解决方法是询问对象是否是Marshal.IsComObject的本机COM,只有本机COM必须与Marshal.ReleaseComObject一起释放。

这是代码:

if (Marshal.IsComObject(comObject)) 
{ 
    Marshal.ReleaseComObject(comObject); 
} 
comObject = null; 

重要:你必须肯定的是,没有使用该对象之后被释放。

对于更详细的解释阅读这篇文章:http://blogs.msdn.com/b/visualstudio/archive/2010/03/01/marshal-releasecomobject-considered-dangerous.aspx

+0

该博文是非常具体的Marshal.IsComObject()**不是**是适当的解决方案。 – 2013-07-02 21:32:10

+0

该博客文章说,如果我们确定comObject不是并且在它被释放之后永远不会被用在别的地方**,即使在代码重构之后,也可以使用** Marshal.IsComObject()解决方案。不确定,那么最好不要释放它(手工),并让垃圾收集器做些什么,当... – franckspike 2014-10-22 14:25:34