защита COM-интерфейсов от исключений - PullRequest
3 голосов
/ 27 апреля 2010

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

Мне была дана задача защитить каждый из этих методов от генерируемых исключений (чтобы отловить их и вернуть ошибку, используя функцию Error() COM, к которой, кстати, я не могу найти документацию, потому что гуглить невозможно) , Насколько я понимаю, это требует, чтобы я добавил попробовать / поймать вокруг каждого из этих методов. Блоки захвата будут одинаковыми или идентичными для каждого из этих сотен методов, которые сильно пахнут проблемой (в значительной степени нарушает принцип DRY), но я не могу придумать какой-либо способ избежать изменения каждого метода. Насколько я могу судить, эти методы вызываются непосредственно COM, без какого-либо промежуточного кода, который я могу подключить, чтобы перехватить исключения. Моя текущая лучшая идея - сделать макрос для блока catch, но у него есть свой собственный запах кода. Может кто-нибудь придумать лучший подход?

Кстати, исключения моего приложения не являются производными от std :: exception, поэтому, если есть какой-то способ автоматической обработки стандартных исключений COM, это не поможет. И я, к сожалению, не могу изменить существующие исключения для получения из std :: exception.

Ответы [ 4 ]

3 голосов
/ 28 апреля 2010

Самый надежный способ C ++ - использовать здесь макросы. Я готов принять отрицательные отзывы за это, но мы использовали это решение в течение многих лет и до сих пор не сталкивались с серьезными проблемами.

Определите макрос «метод начала» для очистки IErrorInfo и try { и «метод конца» для } catch и обработку ошибок. Если вы правильно спроектируете макросы - поместите все, кроме самого необходимого кода обработки ошибок в вспомогательные функции, это будет приемлемым и надежным решением с чистым, в меру обслуживаемым кодом.

Да, не очень хорошо выглядит , но, по крайней мере, это надежный и совместимый со стандартами способ достижения того, чего вы хотите.

3 голосов
/ 28 апреля 2010

Нет счастливых ответов здесь. Недопустимо, чтобы исключение C ++ или SEH завершало метод COM. Вы должны поймать их и перевести на соответствующий HRESULT. Ваш Coclass должен реализовать интерфейсы ISupportsErrorInfo и IErrorInfo, чтобы клиент мог получить информацию об исключении обратно. CLR с готовностью сделает это для создания настроенного сообщения об исключении.

Метод Error (), о котором вы говорите, - это, скорее всего, метод ATL CComCoClass :: Error () . Он устанавливает информацию об исключении, которую возвращает IErrorInfo.

Нет механизма для внедрения одного блока try / catch для перехвата всех возможных исключений, COM-методы вызываются непосредственно из клиента. Вы должны сделать это для каждого отдельного COM-метода, который вызывает код C ++, который может вызвать исключение. Неприятно, но это должно было быть сделано, когда код был написан. Вам, вероятно, нужно обернуть каждый из них, поскольку выяснить, вызывает ли он код, который может выдать, сейчас сложно.

Технически, вы можете изменить фабрику классов, чтобы создать оболочку, которая реализует каждый метод интерфейса и делегирует его фактическому методу. С шаблоном попробуйте / поймать обработчики. Очень механический, вы можете придумать несколько макросов, чтобы уменьшить удар.

0 голосов
/ 27 апреля 2010

Учитывая, что все методы интерфейса COM используют соглашение __stdcall и, если вы можете подключиться к созданию объектов COM самостоятельно, вы можете просто создать COM-объект-оболочку, который возвращает обернутый интерфейс COM через QueryInterface. Этот обернутый COM-интерфейс должен быть COM-интерфейсом, где каждая запись vtable заменяется на thunk, который оборачивает исходную vtable-функцию с try/catch.

На самом деле я не рекомендую делать это, но это один из способов изолировать среду выполнения, реализующую объект COM, от внешних систем.

0 голосов
/ 27 апреля 2010

Комета - это один из способов значительно упростить прилагаемые усилия.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...