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;
}