Исключение из COM-объекта написанного на шарпе
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 11.05.13 15:04
Оценка:
Привет всем.

Помогите, пожалуйста, разобраться в базой вещи — как из метода COM-объекта, написанного на шарпе, следует возвращать ошибки?

Наверное, вообще никаких напрягов быть не должно. Но что-то не получается.

Есть код вида
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[SuppressUnmanagedCodeSecurity]
[Guid("bla-bla-bla")]
public unsafe interface IMyComInterface
{
 [PreserveSig]
 com.HResultCode Method();
};//interface IMyComInterface

unsafe class TMyComInterface:IMyComInterface
{
 [PreserveSig]
 public com_lib.HResultCode Method()
 {
  var exc=new ApplicationException("TEST EXCEPTION!");

  throw exc;
 }//Read
};//class TMyComInterface


Программа на плюсах, когда вызывает Method, получает код ошибки S_OK. Хотя ApplicationException содержит hr=COR_E_APPLICATION.

Если убрать PreserveSig, то процесс валится (походу исключение вылетает и всё убивает).

Вообщем — где я перемудрил? Или мне нужно самому возвращать hr и вызывать SetErrorInfo?

Заранее спасибо!
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re: Исключение из COM-объекта написанного на шарпе
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 11.05.13 16:38
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Привет всем.


КД>Помогите, пожалуйста, разобраться в базой вещи — как из метода COM-объекта, написанного на шарпе, следует возвращать ошибки?


КД>Наверное, вообще никаких напрягов быть не должно. Но что-то не получается.


ComException не пробовал кидать? А так PreserveSig вполне работал, когда я с СОМом возился. Надо только явно return делать с нужным кодом и SetErrorInfo.

КД>Программа на плюсах, когда вызывает Method, получает код ошибки S_OK. Хотя ApplicationException содержит hr=COR_E_APPLICATION.


Так либо PreserveSig, либо ComException, а не все одновременно.
... << RSDN@Home 1.2.0 alpha 5 rev. 99 on Windows 8 6.2.9200.0>>
AVK Blog
Re[2]: Исключение из COM-объекта написанного на шарпе
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 11.05.13 16:56
Оценка:
Здравствуйте, AndrewVK, Вы писали:

КД>>Наверное, вообще никаких напрягов быть не должно. Но что-то не получается.


AVK>ComException не пробовал кидать? А так PreserveSig вполне работал, когда я с СОМом возился. Надо только явно return делать с нужным кодом и SetErrorInfo.


КД>>Программа на плюсах, когда вызывает Method, получает код ошибки S_OK. Хотя ApplicationException содержит hr=COR_E_APPLICATION.


AVK>Так либо PreserveSig, либо ComException, а не все одновременно.


Попробовал кидать ComException. Та же ботва
— с PreserveSig возвращается S_OK
— без PreserveSig — тупо валится.

Да оно и понятно. PreserveSig — это хрень которая подавляет генерацию ComException когда я вызываю интерфейсный метод.

А у меня же не вызов — это меня вызывают, и я должен вернуть код ошибки и объект с описанием ошибки.

AVK>Надо только явно return делать с нужным кодом и SetErrorInfo.


А в чем тогда профит, если надо писать явный код? Явный код и дурак напишет.

Может атрибут какой надо у методов замутить "трансляция_исключений_в_OleAutomationError"?

----
А как нахаляву передать .NET исключение в SetErrorInfo? Что-то я IErrorInfo в списке реализуемых интерфейсов не наблюдаю ... (пока ILSpy-ем в системных сборках копаюсь)
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[3]: Исключение из COM-объекта написанного на шарпе
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 11.05.13 17:20
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>А в чем тогда профит, если надо писать явный код?


Ни в чем. А почему ты решил что профит должен быть?

КД>А как нахаляву передать .NET исключение в SetErrorInfo? Что-то я IErrorInfo в списке реализуемых интерфейсов не наблюдаю ... (пока ILSpy-ем в системных сборках копаюсь)


Не знаю. Когда ты исключение кидаешь, то этим занимается CCW. А вот так чтобы исключение не кидать — не встречал. ILSpy тебе вряд ли поможет, CCW это нативный код.
... << RSDN@Home 1.2.0 alpha 5 rev. 99 on Windows 8 6.2.9200.0>>
AVK Blog
Re[4]: Исключение из COM-объекта написанного на шарпе
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 11.05.13 17:33
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, Коваленко Дмитрий, Вы писали:


КД>>А в чем тогда профит, если надо писать явный код?


AVK>Ни в чем. А почему ты решил что профит должен быть?


Да VladD2 как-то мимоходом сказал, что на .NET писать комы проще.

КД>>А как нахаляву передать .NET исключение в SetErrorInfo? Что-то я IErrorInfo в списке реализуемых интерфейсов не наблюдаю ... (пока ILSpy-ем в системных сборках копаюсь)


AVK>Не знаю. Когда ты исключение кидаешь, то этим занимается CCW. А вот так чтобы исключение не кидать — не встречал. ILSpy тебе вряд ли поможет, CCW это нативный код.


Меня тут мысль посетила насчет ISupportErrorInfo. Однако поиск в сети тут же выдал ссылку на StackOverflow — Implementing ISupportErrorInfo on a C# object exposed to COM.

Народ вроде говорит, что трансляция исключений осуществляется автоматически.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re: Исключение из COM-объекта написанного на шарпе
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 11.05.13 17:41
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Привет всем.


КД>Помогите, пожалуйста, разобраться в базовой вещью — как из метода COM-объекта, написанного на шарпе, следует возвращать ошибки?


КД>Наверное, вообще никаких напрягов быть не должно. Но что-то не получается.


КД>Есть код вида


Забыл сказать об одной вещи (наверное она важна) — я пишу не сервер COM-объектов, а обычный код, который хочет передать свой COM-объект (с данными) в другой COM-объект.

То есть снаружи этот TMyComInterface недоступен.

Возможно в этом есть какая-нибудь скрытая проблема...
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[5]: Исключение из COM-объекта написанного на шарпе
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 11.05.13 18:33
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Да VladD2 как-то мимоходом сказал, что на .NET писать комы проще.


Использование PreserveSig, да так чтобы еще и ErrorInfo потребовался, скажем так, не самая частая ситуация. Лично мне PreserveSig несколько раз был нужен, но всегда этобыла ситуация когда вокруг HResult была построена логика, а не потому что так ошибка возвращалась.

КД>Народ вроде говорит, что трансляция исключений осуществляется автоматически.


Правильно говорит. И ISupportErrorInfo CCW реализуент в полном объеме. Вот только транслируется оно в СОМ-исключение, которое, видимо, в твоем случае вызывающий код не обрабатывает.
... << RSDN@Home 1.2.0 alpha 5 rev. 99 on Windows 8 6.2.9200.0>>
AVK Blog
Re[6]: Исключение из COM-объекта написанного на шарпе
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 11.05.13 19:14
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Использование PreserveSig, да так чтобы еще и ErrorInfo потребовался, скажем так, не самая частая ситуация. Лично мне PreserveSig несколько раз был нужен, но всегда этобыла ситуация когда вокруг HResult была построена логика, а не потому что так ошибка возвращалась.


Мне нужен не PreserveSig, я его заюзал по-привычке (до сих пор я работал в обратном направлении — из .NET c "настоящими" COM-ами, написанными на плюсах). Мне нужно разобраться в том, как правильно реализуется COM-объект на C# (.NET). Собственно говоря, сам объект-то у меня работает. Непонятно как заставить фреймворк правильно обрабатывать исключения, которые внутри моего .NET COM-объекта генерируются.

КД>>Народ вроде говорит, что трансляция исключений осуществляется автоматически.


AVK>Правильно говорит. И ISupportErrorInfo CCW реализуент в полном объеме. Вот только транслируется оно в СОМ-исключение, которое, видимо, в твоем случае вызывающий код не обрабатывает.


Вызывающая сторона (это код на плюсах) как минимум обрабатывает код ошибки. CCW, по идее, должен был выдрать код ошибки из исключения и вернуть его. Но он почему-то это не делает (хотя и ловит исключения) и всегда возвращает S_OK.

Ладно, утро вечера мудреннее. Может завтра что в голову новое прийдет
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[7]: Исключение из COM-объекта написанного на шарпе
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 11.05.13 19:29
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Мне нужно разобраться в том, как правильно реализуется COM-объект на C# (.NET).


Правильно — это полностью положиться на CCW. Обычно в вызывающем коде SEH присутствует. А вот если CCW не устраивает — тут уж рукопашный трах по полной.

КД>Непонятно как заставить фреймворк правильно обрабатывать исключения, которые внутри моего .NET COM-объекта генерируются.


Причем тут фреймворк? Фреймворк делает совершенно тривиальную вещь — конвертирует исключение в понятное СОМ. Т.е. в большинстве случаев ты просто кидаешь исключение и дальнейшее — не твоя забота.
... << RSDN@Home 1.2.0 alpha 5 rev. 99 on Windows 8 6.2.9200.0>>
AVK Blog
Re: Исключение из COM-объекта написанного на шарпе
От: breee breee  
Дата: 11.05.13 20:24
Оценка: 22 (2)
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Есть код вида

КД>
КД>[ComVisible(true)]
КД>[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
КД>[SuppressUnmanagedCodeSecurity]
КД>[Guid("bla-bla-bla")]
КД>public unsafe interface IMyComInterface
КД>{
КД> [PreserveSig]
КД> com.HResultCode Method();
КД>};//interface IMyComInterface

КД>unsafe class TMyComInterface:IMyComInterface
КД>{
КД> [PreserveSig]
КД> public com_lib.HResultCode Method()
КД> {
КД>  var exc=new ApplicationException("TEST EXCEPTION!");

КД>  throw exc;
КД> }//Read
КД>};//class TMyComInterface
КД>


1. Убираем PreserveSig.
2. Вместо HResultCode возвращаем viod.
3. В C#-коде об ошибках сообщаем, бросая исключения.
4. В C++-коде импортируем (#import) tlb с атрибутом raw_interfaces_only. В этом случае исключения будут транслироваться в HRESULT. Без этого атрибута будет выбрасываться _com_error.
Re[2]: Исключение из COM-объекта написанного на шарпе
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 12.05.13 05:24
Оценка:
Здравствуйте, breee breee, Вы писали:

BB>1. Убираем PreserveSig.

BB>2. Вместо HResultCode возвращаем viod.
BB>3. В C#-коде об ошибках сообщаем, бросая исключения.

Ага, спасибо!

Попробовал кидать ComException с E_FAIL и S_FALSE — вызывающая сторона на плюсах получает их без проблем. ApplicationException c его COR_E_APPLICATION — тоже нормально обрабатывается.

Похоже это — ПОБЕДА!
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[3]: Исключение из COM-объекта написанного на шарпе
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 12.05.13 10:05
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

BB>>1. Убираем PreserveSig.

BB>>2. Вместо HResultCode возвращаем viod.
BB>>3. В C#-коде об ошибках сообщаем, бросая исключения.

КД>Ага, спасибо!


КД>Попробовал кидать ComException с E_FAIL и S_FALSE — вызывающая сторона на плюсах получает их без проблем. ApplicationException c его COR_E_APPLICATION — тоже нормально обрабатывается.


Я допёр

1. Почему у меня валился процесс без PreserveSig, но с возвратом com.HResultCode через return. CCW (по ходу) обрабатывало этот return как некий OUT-параметр метода и убивало стек.

2. Почему CCW (когда указан PreserveSig) не пытается выдрать из исключения код ошибки и вернуть его. Потому что PreserveSig означает "не трогай моё возвращаемое значение из функции". Соответственно, CCW и не пытается это делать — вдруг я возвращаю не HRESULT, а (к примеру) LCPWSTR. А S_OK (ноль) возвращается потому что CCW использовало это значение для инициализации результата перед вызовом метода.

TMethodReturnValue result=<значение для инициализации>;

try
{
 result=controlled_object.Method(); //throw
}
catch(Exception e)
{
 if(!PreserveSig)
 {
  result=ExtractErrorCodeFromException(e);
 }
}//catch

return result;


Вот теперь в голове вроде все сложилось и можно двигаться дальше

ВСЕМ СПАСИБО!
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[4]: Исключение из COM-объекта написанного на шарпе
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 13.05.13 20:43
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>1. Почему у меня валился процесс без PreserveSig, но с возвратом com.HResultCode через return. CCW (по ходу) обрабатывало этот return как некий OUT-параметр метода и убивало стек.


Мне, честно говоря, даже в голову не пришло, что ты PreserveSig убрал, а возвращаемое значение оставил.

КД>2. Почему CCW (когда указан PreserveSig) не пытается выдрать из исключения код ошибки и вернуть его. Потому что PreserveSig означает "не трогай моё возвращаемое значение из функции".


Именно так.
... << RSDN@Home 1.2.0 alpha 5 rev. 99 on Windows 8 6.2.9200.0>>
AVK Blog
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.