Marshal.ReleaseComObject выбрасывает исключение

Попытка использовать видимый COM класс.NET через другое приложение.NET и получить исключение:

Сообщение: тип объекта должен быть __ComObject или производным от __ComObject.

Имя параметра: o

Трассировка стека: в System.Runtime.InteropServices.Marshal.ReleaseComObject(Object 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.

4 ответа

Я получил эту проблему недавно, когда переопределяю собственный COM в управляемый код. Решение состояло в том, чтобы спросить, является ли объект собственным COM с Marshal.IsComObject, только исходные 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

Но как вы создаете экземпляр класса? Просто используя выражение new MyViewer() не создает COM-объект. Вместо этого он создает простой старый объект.Net, который нельзя использовать с методом ReleaseComObject.

На основе вашего примера кода, в частности, строка о MyViewer имея реализацию, не похоже, что вы имеете дело с COM-объектом. Вместо этого похоже, что у вас есть управляемый объект, который реализует интерфейс COM.

Чтобы использовать ReleaseComObject, вам действительно нужно иметь объект COM / RCW.

Я предполагаю, что вы на самом деле не используете COM, а просто используете ссылочный класс.NET. Если ваш проект содержит такой код

MyViewer viewer = new MyViewer();

и вы добавили библиотеку, содержащую MyViewer не в качестве ссылки COM, вы на самом деле не используете COM.

Я бы лучше попробовал:

if (comObject != null)
{
      if (System.Runtime.InteropServices.Marshal.IsComObject(comObject))
      {                
          System.Runtime.InteropServices.Marshal.ReleaseComObject(comObject);
      }
      comObject= null;
}
Другие вопросы по тегам