2010-08-24 2 views
3

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

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

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

трассировки стека: на System.Runtime.InteropServices.Marshal.ReleaseComObject (Object о)

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

[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-объектов.

+0

Вы можете включить код, где ваш являются создание экземпляра объекта и где вы вызываете 'ReleaseComObject' тоже? Какой тип имеет объект, который вы выпускаете? Кажется, что это не COM-объект. И как в сторону: в чем причина того, что вы хотите использовать COM в этом случае? Использование .NET-сборки из .NET работает намного проще без COM (и на самом деле у меня есть подозрение, что вы уже это делаете ;-) –

+0

Можете ли вы опубликовать код клиента, было бы хорошо посмотреть, как создается экземпляр компонента –

+0

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

ответ

0

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

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

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

+0

Если сборка, содержащая 'MyViewer', была добавлена ​​в качестве ссылки на COM, разве вы не получили бы COM-объект с' new MyViewer() 'then (вместо простого старого .NET-объекта)? Я не могу придумать причину, почему это возможно, но это возможно. –

+0

@ 0xA3 да, если этот тип был CoClass в PIA (по крайней мере, AFAIK). Но в этом случае это просто простой старый управляемый объект, поэтому новый не делает ничего особенного. – JaredPar

+0

не зарегистрирован в COM-среде .NET-класс, имеющий объект, который реализует все базовые функции COM, включая Release? – Aaron

0

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

MyViewer viewer = new MyViewer(); 

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

2

В последнее время эта проблема возникла при переопределении собственного 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

Это сообщение в блоге довольно специфично относительно Marshal.IsComObject() **, а не ** является правильным решением. –

+0

В этом сообщении в блоге говорится, что решение ** Marshal.IsComObject() МОЖЕТ использоваться, если мы ПРЕДЫДУЩИМ, что comObject НЕ И НЕ БУДЕТ использоваться где-то еще ** после его выпуска даже после рефакторинга кода ... Когда unsure, тогда лучше не выпускать его вообще (вручную), и пусть сборщик мусора сделает это когда-нибудь ... – franckspike

Смежные вопросы