C# Marshal.ReleaseComObject引发异常

C# Marshal.ReleaseComObject引发异常,c#,interop,com-interop,comvisible,C#,Interop,Com Interop,Comvisible,试图通过其他.NET应用程序使用COM visible.NET类并获取异常: 消息:对象的类型必须为 __共对象或从_共对象派生的 参数名称:o 堆栈跟踪:在 System.Runtime.InteropServices.Marshal.ReleaseComObject(对象 o) 该类如下所示: [ComVisible(true)] [InterfaceType(ComInterfaceType.InterfaceIsDual)] public interface IViewer : ICom

试图通过其他.NET应用程序使用COM visible.NET类并获取异常:

消息:对象的类型必须为 __共对象或从_共对象派生的

参数名称:o

堆栈跟踪:在 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对象。

但是如何创建类实例?仅使用表达式
newmyviewer()
不会创建COM对象。相反,它创建了一个普通的旧.Net对象,不能与ReleaseComObject方法一起使用

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


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

我的猜测是,您实际上没有使用COM,只是使用了一个引用的.NET类。如果您的项目包含以下代码:

MyViewer viewer = new MyViewer();

您已经添加了包含
MyViewer
的库,而不是作为COM引用,您实际上没有使用COM。

最近,我在将本机COM重新实现为托管代码时遇到了这个问题。 解决方案是询问对象是否是具有Marshal.IsComObject的本机COM,只有本机COM必须使用Marshal.ReleaseComObject进行释放

这是代码:

if (Marshal.IsComObject(comObject))
{
     Marshal.ReleaseComObject(comObject);
}
comObject = null;
重要信息:您必须确保,该对象在释放后不会被使用

要获得更详细的解释,请阅读本文:

我宁愿尝试:

if (comObject != null)
{
      if (System.Runtime.InteropServices.Marshal.IsComObject(comObject))
      {                
          System.Runtime.InteropServices.Marshal.ReleaseComObject(comObject);
      }
      comObject= null;
}

您是否可以包括实例化对象的代码以及调用
ReleaseComObject
的代码?您正在释放的对象的类型是什么?似乎它不是一个COM对象。顺便说一句:在这种情况下,您希望使用COM的原因是什么?使用.NET中的.NET程序集在没有COM的情况下工作要容易得多(事实上,我怀疑您已经在这样做了;-)您可以发布客户端代码吗?如果能够看到组件是如何实例化的,那将很好。不幸的是,我无法提供用于实例化对象的客户端应用程序代码。但是,我知道客户端正在使用相同的方法实例化真正的COM对象。如果包含
MyViewer
的程序集被添加为COM引用,那么您不希望使用
new MyViewer()
获得COM对象(而不是普通的旧.NET对象)吗?我想不出这样做的原因,但这可能是有可能的。@0xA3是的,如果该类型是PIA中的一个CoClass(至少是AFAIK)。但在这种情况下,它只是一个普通的旧托管对象,所以新对象没有做任何特殊的事情。COM注册的.NET类难道不意味着拥有一个实现所有基本COM功能(包括发布)的对象吗?@Aaron这取决于对象的哪个部分。Net端没有Add/Release方法,因为在.Net对象上不需要它。CLR生成的CCW(COM可调用包装器)将不必要地使用它们。该博客文章非常明确地指出Marshal.IsComObject()不是合适的解决方案。该博客文章说Marshal.IsComObject()是如果我们确信comObject在发布后不会也永远不会在其他地方使用,即使在代码重构之后,也可以使用该解决方案。。。当不确定时,最好不要释放它(用手),让垃圾收集器在某个时候做它。。。