Почему я получаю исключение ExecutionEngineException при попытке агрегации COM - PullRequest
1 голос
/ 27 марта 2012

Я пытаюсь объединить объект .NET в COM-объекте (внешнее неизвестное), используя следующий код:

Object obj = ... // some ComVisible .NET object

var comObj  = (IMyComInterface)Activator.CreateInstance(Type.GetTypeFromProgID("some.progid"));

var unknown = Marshal.GetIUnknownForObject(comObj);

var innerUnknown = Marshal.CreateAggregatedObject(unknown, obj);

// This is where the ExecutionEngineException is thrown.         
var aggObj = Marshal.GetObjectForIUnknown(innerUnknown);

// Make outer object aware of our dotnet object, say.
comObj.DotNetObj = aggObj;

Marshal.Release(unknown);

...

Есть ли что-нибудь "очевидное" неправильно в этом коде?Это исключение оставляет мне очень мало, чтобы продолжить.Также раздражает то, что исключение не всегда происходит, хотя это происходит чаще, чем нет.Есть ли другой способ добиться этого?(т. е. направить innerUnknown IntPtr в мой COM-объект)

ПРИМЕЧАНИЕ. Я должен настроить таргетинг на версию 2 платформы и не пробовал версию 4, и, насколько я знаю, полностью обновлен.

1 Ответ

3 голосов
/ 28 марта 2012

Чтобы ответить на вопрос, причина его неудачи в том, что innerUnknown - это неверное неизвестное. Метод предназначен для получения активного RCW для COM IUnknown, но этот IUnknown является оборачиваемой оболочкой для управляемого объекта.

В любом случае, внешнему объекту нужен указатель innerUnknown. Если вы дадите ему тот, который пытаетесь использовать, вы получите переполнение стека в QueryInterface.

В приведенном выше примере объект .Net считает, что он был агрегирован объектом COM, но объект COM не знает. Предполагая, что это ваш COM-объект, вам нужно дать ему innerUnknown, а затем реализовать делегирование IUnknown (если вы этого еще не сделали). Вам не нужно вызывать GetObjectForIUnknown.

Вы вроде как делаете это задом наперед. Обычно COM-объект вызывает CoCreateInstance, передавая себя как внешнее неизвестное. Затем среда выполнения вызывает CreateAggregatedObject для вас.


Если вы хотите, чтобы объект .Net агрегировал COM-объект, вы должны наследовать от RCW. Это создаст COM-объект как агрегированный объект, передающий внутреннее неизвестное .Net в CoCreateInstance. Но это должен быть объект, который поддерживает агрегацию.

Если вы хотите, чтобы COM-объект агрегировал .Net-объект, вы должны использовать COM-объект, который это делает. Типичными примерами являются агрегирующие ADO поставщики OLEDB, агрегирующие ADSI расширения ADSI, WMI (я думаю). Но он должен поддерживаться объектом, вы не можете сказать, чтобы какой-либо старый объект собирал вас. Обычно это происходит с помощью другого объекта, вызывающего CoCreateInstance, который обрабатывается средой выполнения .Net, которая вызывает для вас CreateAggregatedObject и передает innerUnknown обратно вызывающей стороне.

...