Marshal.ReleaseComObject выбрасывает исключение - PullRequest
4 голосов
/ 24 августа 2010

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

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

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

Трассировка стека: в System.Runtime.InteropServices.Marshal.ReleaseComObject (Объект о)

Класс выглядит следующим образом:

[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(), оно получает исключение, описанное выше.

Есть идеи для решения этой проблемы?

EDIT: К сожалению, я не могу предоставить код клиентского приложения для создания экземпляра моего объекта. Однако я знаю, что клиент использует тот же метод для создания реальных объектов COM.

Ответы [ 4 ]

3 голосов
/ 03 июля 2013

Я получил эту проблему недавно, когда переопределял собственный 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

0 голосов
/ 19 декабря 2018

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

if (comObject != null)
{
      if (System.Runtime.InteropServices.Marshal.IsComObject(comObject))
      {                
          System.Runtime.InteropServices.Marshal.ReleaseComObject(comObject);
      }
      comObject= null;
}
0 голосов
/ 24 августа 2010

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

MyViewer viewer = new MyViewer();

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

0 голосов
/ 24 августа 2010

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

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

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

...