2010-04-27 3 views
3

COM 인터페이스를 통해 노출 된 수십 개의 개체가 있는데, 각각 수 많은 메서드가 포함 된 여러 메서드가 있습니다. 이러한 인터페이스는 내 앱에서 스크립팅 엔진으로 비즈니스 객체를 노출합니다.예외로부터 COM 인터페이스 보호

예외를 던져서 예외를 잡아서 (예외적으로 Google에 불가능하기 때문에 아무 문서도 찾을 수없는 COM의 Error() 함수를 사용하여 오류를 반환하기 위해) 이러한 모든 메서드 중 하나를 보호해야합니다. 내 이해를 위해,이 방법 중 하나의 배짱 주위에 try/catch를 추가해야합니다. catch 블록은이 수백 가지 방법 중 하나 하나에 대해 비슷하거나 비슷할 것입니다. 문제의 원인이 강하게 (DRY 원칙을 크게 위반 함) 있지만 모든 방법을 변경하지 않는 방법은 없습니다. 내가 알 수있는 한, 이러한 메소드는 COM에 의해 직접 호출되며, 예외를 잡기 위해 간섭 할 수있는 코드가 없습니다. 나의 현재의 최선의 아이디어는 catch 블록을위한 매크로를 만드는 것이지만, 그것은 자신의 종류의 코드 - 냄새가있다. 누구든지 더 나은 접근법을 제시 할 수 있습니까?

BTW, 내 응용 프로그램의 예외는 std :: 예외에서 파생되지 않으므로 표준 예외를 자동으로 처리하는 COM의 방법이 있으면 도움이되지 않습니다. 그리고 슬프게도 std :: exception에서 파생 된 기존 예외를 변경할 수 없습니다.

답변

3

가장 신뢰할 수있는 C++ 방법은 여기에서 매크로를 사용하는 것입니다. 나는 이것을 말하는 downvotes를 받아 들일 준비가되어 있지만, 우리는 몇 년 동안이 솔루션을 사용해 왔고 지금까지 심각한 문제를 보지 못했습니다.

IErrorInfotry {을 지우고 } catch의 "end method"및 오류 처리를위한 "begin method"매크로를 정의하십시오. 매크로를 올바르게 디자인하면 가장 필요한 오류 처리 코드를 제외한 모든 코드를 도우미 함수에 넣을 수 있습니다.이 코드는 정교하고 유지 보수가 쉬운 코드로 허용 가능하고 신뢰할 수있는 솔루션이 될 것입니다.

예, 해당 doesn't look good at all,하지만 적어도 그것은 당신이 원하는 것을 달성하는 신뢰할 수 있고 표준을 준수하는 방법입니다.

0

Comet은 관련된 작업을 크게 단순화하는 방법 중 하나입니다.

+0

흥미로운 것처럼 보이지만,이 레거시 시스템에서는 사용하기에 엄청난 양의 작업이 될 것이라고 생각합니다. 내가 COM을 사용하는 새로운 시스템을 설계하는 불행을 겪었다면 계속 명심해야한다. – rmeador

0

모든 COM 인터페이스 메서드는 __stdcall 규칙을 사용하며 COM 개체를 직접 만들 수 있다고 가정하면 QueryInterface을 통해 래핑 된 COM 인터페이스를 반환하는 래퍼 COM 개체를 간단히 만들 수 있습니다. 이 래핑 된 COM 인터페이스는 모든 vtable 항목이 try/catch으로 원래 vtable 함수를 래핑하는 썽크로 대체되는 COM 인터페이스 여야합니다.

실제로이 작업을 권장하지는 않지만 외부 시스템에서 COM 개체를 구현하는 런타임을 차단할 수있는 방법 중 하나입니다.

+0

이 작업을 수행하는 방법에 대한 링크 또는 예제 코드가 있습니까? C++은 이런 식으로 vtable을 수정하도록 허용합니까? 아니면 직접 메모리 조작을 사용해야합니까? 그리고 아키텍쳐와 OS에 의존하지 않을 것인가? (아마 내 상사로부터 "아니오"를 이끌어 낼 것인가?) – rmeador

3

여기에 만족할만한 답변이 없습니다. C++ 또는 SEH 예외가 COM 메소드를 종료하도록하는 것은 불법입니다. 을 잡아서 적절한 HRESULT로 번역해야합니다. coclass는 클라이언트가 예외 정보를 다시 얻을 수 있도록 ISupportsErrorInfo 및 IErrorInfo 인터페이스를 구현해야합니다. CLR은 사용자 지정된 예외 메시지를 생성하기 위해 쉽게 수행합니다.

당신이 말하는 Error() 방법은 ATL CComCoClass::Error() method 일 가능성이 큽니다. IErrorInfo가 리턴 할 예외 정보를 설정합니다.

가능한 모든 예외를 catch하기 위해 단일 try/catch 블록을 주입하는 메커니즘이 없으며 COM 메서드는 클라이언트에서 직접 호출됩니다. 예외를 throw 할 수있는 C++ 코드를 호출하는 개별 COM 메서드마다 이렇게해야합니다. 불쾌하지만 코드가 작성되었을 때이 작업이 완료되었을 것입니다. 이제는 던져 버릴 수있는 코드를 호출하는 것이 어렵다는 것을 알아 내고 나서 각각의 코드를 하나씩 감쌀 필요가있을 것입니다.

기술적으로 클래스 팩토리를 변경하여 대신 인터페이스의 각 메소드를 구현하고 실제 메소드에 위임하는 래퍼를 만들 수 있습니다. 보일러 플레이트 try/catch 핸들러. 매우 기계적으로, 당신은 아마도 타격을 줄이기 위해 어떤 매크로를 생각해 낼 수 있습니다.

+0

또는 SetErrorInfo(), 아마도 ATL 메서드가 래핑하는 것일 것입니다. http://msdn.microsoft.com/en-us/library/aa910593(v=MSDN.10).aspx –

관련 문제