Throw exception from ATL COM for both VB and VC++ client
Author |
Message |
Do Quyet Tie #1 / 11
|
 Throw exception from ATL COM for both VB and VC++ client
Hi, in a my component, intended for using both VC++ and VB client, I used CComCoClass::Error method for report any error to VB client and _com_raise_error for throw exception for VC++ client (using smart pointer with try/catch), but unfortunately, it's seemed that they can't exist together, VB eat exception threw by _com_raise_error :D what's the bug here, if any? thanks, Tien,
|
Sun, 09 May 2004 09:46:22 GMT |
|
 |
Vitali Brusentse #2 / 11
|
 Throw exception from ATL COM for both VB and VC++ client
Hi! The default implementation of _com_raise_error looks like that: void __stdcall _com_raise_error(HRESULT hr, IErrorInfo* perrinfo) throw(_com_error) { throw _com_error(hr, perrinfo); Quote: }
In other words, the c++ exception mechanism is used. There is no binary standard for throwing c++ exceptions across COM boundaries, and VB doesn't support it. Just return HRESULT with failed state and provide additional info via IErrorInfo inteface. MSDN recommends the following: "If your object uses the IErrorInfo interface to report errors back to the client, then your object must support the ISupportErrorInfo interface. The template class ISupportErrorInfoImpl provides an easy way to implement this if you only have a single interface that generates errors on your object." -- With best regards, Vitali
Quote: > Hi, > in a my component, intended for using both VC++ and VB client, I used > CComCoClass::Error method for report any error to VB client and > _com_raise_error for throw exception for VC++ client (using smart pointer > with try/catch), but unfortunately, it's seemed that they can't exist > together, VB eat exception threw by _com_raise_error :D > what's the bug here, if any? > thanks, > Tien,
|
Sun, 09 May 2004 12:22:02 GMT |
|
 |
Vitali Brusentse #3 / 11
|
 Throw exception from ATL COM for both VB and VC++ client
Hi! You can freely use smart pointers and try/catch in your C++ COM object, but with essential limitation: all possible exceptions must be caught _inside_ object. Passing exception across COM boundaries will lead to Access Violation. In your failure handler (i.e, catch block) of COM method you should do the following: - obtain the IErrorInfo interface pointer (either from _com_error helper object or manually, by calling ::CreateErrorInfo() - ICreateErrorInfo::SetSource(...) - ICreateErrorInfo::SetDescription(...) - ICreateErrorInfo::QueryInterface(IID_IErrorInfo, ...) ); - call API function SetErrorInfo() and pass obtained pointer as parameter. - return E_FAIL (or any other error value) from method. It wouldn't work if you didn't implement the ISupportErrorInfo interface (see class ISupportErrorInfoImpl in ATL). -- With best regards, Vitali.
Quote: > thanks, but as you said, we cannot use try/catch feature with COM smart > pointer (and support IErrorInfo fo VB), can we?
|
Mon, 10 May 2004 15:51:51 GMT |
|
 |
Do Quyet Tie #4 / 11
|
 Throw exception from ATL COM for both VB and VC++ client
thanks, but as you said, we cannot use try/catch feature with COM smart pointer (and support IErrorInfo fo VB), can we?
Quote: > Hi! > The default implementation of _com_raise_error looks like that: > void __stdcall _com_raise_error(HRESULT hr, IErrorInfo* perrinfo) > throw(_com_error) > { > throw _com_error(hr, perrinfo); > } > In other words, the c++ exception mechanism is used. > There is no binary standard for throwing c++ exceptions across COM > boundaries, and VB doesn't support it. > Just return HRESULT with failed state and provide additional info via > IErrorInfo inteface. > MSDN recommends the following: > "If your object uses the IErrorInfo interface to report errors back to the > client, then your object must support the ISupportErrorInfo interface. The > template class ISupportErrorInfoImpl provides an easy way to implement this > if you only have a single interface that generates errors on your object." > -- > With best regards, > Vitali
> > Hi, > > in a my component, intended for using both VC++ and VB client, I used > > CComCoClass::Error method for report any error to VB client and > > _com_raise_error for throw exception for VC++ client (using smart pointer > > with try/catch), but unfortunately, it's seemed that they can't exist > > together, VB eat exception threw by _com_raise_error :D > > what's the bug here, if any? > > thanks, > > Tien,
|
Mon, 10 May 2004 14:03:28 GMT |
|
 |
Do Quyet Tie #5 / 11
|
 Throw exception from ATL COM for both VB and VC++ client
oh, I see, but I want to write the flexible component, like many others, it can raise error with smart pointer for VC++ client, as well as provide IErrorInfo for VB client, you know? thanks,
Quote: > Hi! > You can freely use smart pointers and try/catch in your C++ COM object, but > with essential limitation: all possible exceptions must be caught _inside_ > object. Passing exception across COM boundaries will lead to Access > Violation. > In your failure handler (i.e, catch block) of COM method you should do the > following: > - obtain the IErrorInfo interface pointer (either from _com_error helper > object or manually, by calling ::CreateErrorInfo() - > ICreateErrorInfo::SetSource(...) - ICreateErrorInfo::SetDescription(...) - > ICreateErrorInfo::QueryInterface(IID_IErrorInfo, ...) ); > - call API function SetErrorInfo() and pass obtained pointer as parameter. > - return E_FAIL (or any other error value) from method. > It wouldn't work if you didn't implement the ISupportErrorInfo interface > (see class ISupportErrorInfoImpl in ATL). > -- > With best regards, > Vitali.
> > thanks, but as you said, we cannot use try/catch feature with COM smart > > pointer (and support IErrorInfo fo VB), can we?
|
Tue, 11 May 2004 10:16:50 GMT |
|
 |
Chris Donova #6 / 11
|
 Throw exception from ATL COM for both VB and VC++ client
Quote: >oh, I see, but I want to write the flexible component, like many others, it >can raise error with smart pointer for VC++ client, as well as provide >IErrorInfo for VB client, you know?
They are the same thing! VC++ smart pointer wrapper methods check the return code; it it's negative, they use the IErrorInfo interface to fill in the _com_error object, and throw that object. VB does the same thing; it does an "on error" thingy if the COM method return value is negative. The Err object gets its information from IErrorInfo. If you implement IErrorInfo properly in your object, it does what you want in both VB and VC++. Chris
|
Wed, 12 May 2004 07:38:45 GMT |
|
 |
Do Quyet Tie #7 / 11
|
 Throw exception from ATL COM for both VB and VC++ client
sozy, I have tried but it was failed, when a COM method reach unexpected error, I throw out the error by CComCoClass::Error method, but only VB client know this exception, in VC++ client with catch (_com_error) catched nothing. could you give me some samples code? thanks,
Quote:
> >oh, I see, but I want to write the flexible component, like many others, it > >can raise error with smart pointer for VC++ client, as well as provide > >IErrorInfo for VB client, you know? > They are the same thing! > VC++ smart pointer wrapper methods check the return code; it it's > negative, they use the IErrorInfo interface to fill in the _com_error > object, and throw that object. VB does the same thing; it does an "on > error" thingy if the COM method return value is negative. The Err > object gets its information from IErrorInfo. > If you implement IErrorInfo properly in your object, it does what you > want in both VB and VC++. > Chris
|
Fri, 14 May 2004 22:44:27 GMT |
|
 |
Chris Donova #8 / 11
|
 Throw exception from ATL COM for both VB and VC++ client
Quote: >sozy, I have tried but it was failed, when a COM method reach unexpected >error, I throw out the error by CComCoClass::Error method, but only VB >client know this exception, in VC++ client with catch (_com_error) catched >nothing.
Just to check, by smart pointers, I assume you mean the _com_ptr smart pointers generated by #import. Correct? After you call CComCoClass::Error, do you return the HRESULT as the return value of your method? CComCoClass::Error doesn't actually throw an exception, it just creates and populates the ErrorInfo object. You must return a negative hresult, then the wrapper functions in your .tli file will throw the exception. (You can't throw an exception across a COM boundary.) I suggest you use the de{*filter*} in your VC++ client. Break on the call to your method. Step into the .tli file. You'll see something like (this is an example for a string property, but other properties and methods are similar: BSTR _result; HRESULT _hr = get_YourProperty(&_result); if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); return _bstr_t(_result, false); Step through this and see what the HRESULT is. This should tell you if your method is returning a failure code. If it is, then you should see the _com_error exception thrown in the next line. If hr is 0 (S_OK) or positive, then your method is not returning a failure code. You can repeat this experiment, but step into your method (assuming both client and server source and debugging files are available -- easiest way is to make a workspace that contains them both.) Step through your method and see what's happening. Calling CComCoClass::Error should work, though I must admit I've never used it -- I have always just populated the error object using ::CreateErrorInfo and associated API functions, and then returned the HRESULT. Chris
|
Fri, 14 May 2004 23:53:59 GMT |
|
 |
Do Quyet Tie #9 / 11
|
 Throw exception from ATL COM for both VB and VC++ client
first, thanks so much for your answer, like you, I've used ::CreateErrorInfo too, but because it seemed that there is something wrong, so I doubt myshelf ;) I will try it again, of course,
Quote:
> >sozy, I have tried but it was failed, when a COM method reach unexpected > >error, I throw out the error by CComCoClass::Error method, but only VB > >client know this exception, in VC++ client with catch (_com_error) catched > >nothing. > Just to check, by smart pointers, I assume you mean the _com_ptr smart > pointers generated by #import. Correct? > After you call CComCoClass::Error, do you return the HRESULT as the > return value of your method? CComCoClass::Error doesn't actually throw > an exception, it just creates and populates the ErrorInfo object. You > must return a negative hresult, then the wrapper functions in your > .tli file will throw the exception. (You can't throw an exception > across a COM boundary.) > I suggest you use the de{*filter*} in your VC++ client. Break on the call > to your method. Step into the .tli file. You'll see something like > (this is an example for a string property, but other properties and > methods are similar: > BSTR _result; > HRESULT _hr = get_YourProperty(&_result); > if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); > return _bstr_t(_result, false); > Step through this and see what the HRESULT is. This should tell you if > your method is returning a failure code. If it is, then you should see > the _com_error exception thrown in the next line. > If hr is 0 (S_OK) or positive, then your method is not returning a > failure code. You can repeat this experiment, but step into your > method (assuming both client and server source and debugging files are > available -- easiest way is to make a workspace that contains them > both.) Step through your method and see what's happening. > Calling CComCoClass::Error should work, though I must admit I've never > used it -- I have always just populated the error object using > ::CreateErrorInfo and associated API functions, and then returned the > HRESULT. > Chris
|
Sat, 15 May 2004 08:50:05 GMT |
|
 |
Do Quyet Tie #10 / 11
|
 Throw exception from ATL COM for both VB and VC++ client
sorry, I've tried, and it's my fault ;), I've called the raw method (start with raw_<method> name) instead of its original name, thanks,
Quote:
> >sozy, I have tried but it was failed, when a COM method reach unexpected > >error, I throw out the error by CComCoClass::Error method, but only VB > >client know this exception, in VC++ client with catch (_com_error) catched > >nothing. > Just to check, by smart pointers, I assume you mean the _com_ptr smart > pointers generated by #import. Correct? > After you call CComCoClass::Error, do you return the HRESULT as the > return value of your method? CComCoClass::Error doesn't actually throw > an exception, it just creates and populates the ErrorInfo object. You > must return a negative hresult, then the wrapper functions in your > .tli file will throw the exception. (You can't throw an exception > across a COM boundary.) > I suggest you use the de{*filter*} in your VC++ client. Break on the call > to your method. Step into the .tli file. You'll see something like > (this is an example for a string property, but other properties and > methods are similar: > BSTR _result; > HRESULT _hr = get_YourProperty(&_result); > if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); > return _bstr_t(_result, false); > Step through this and see what the HRESULT is. This should tell you if > your method is returning a failure code. If it is, then you should see > the _com_error exception thrown in the next line. > If hr is 0 (S_OK) or positive, then your method is not returning a > failure code. You can repeat this experiment, but step into your > method (assuming both client and server source and debugging files are > available -- easiest way is to make a workspace that contains them > both.) Step through your method and see what's happening. > Calling CComCoClass::Error should work, though I must admit I've never > used it -- I have always just populated the error object using > ::CreateErrorInfo and associated API functions, and then returned the > HRESULT. > Chris
|
Sat, 15 May 2004 09:38:56 GMT |
|
 |
Chris Donova #11 / 11
|
 Throw exception from ATL COM for both VB and VC++ client
Quote: >sorry, I've tried, and it's my fault ;), I've called the raw method (start >with raw_<method> name) instead of its original name,
That would do it. :) Glad you figured it out. Chris
|
Sat, 15 May 2004 23:58:42 GMT |
|
|
|