Throw exception from ATL COM for both VB and VC++ client 
Author Message
 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  
 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  
 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  
 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  
 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  
 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  
 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  
 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  
 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  
 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  
 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  
 
 [ 11 post ] 

 Relevant Pages 

1. VC ATL DLL crashin with VB COM client

2. Accessing a collection from a VB com server in a VC/ATL Client

3. ATL COM DLL :: DllRegisterserver throw exception 0x80029c4a

4. Problem calling VB COM dll from VC++ multithreaded COM EXE client

5. problems passing ADO Recordset from VB-COM client to VC-COM-Server dll

6. VB COM MIGRATION TO ATL VC COM

7. Accessing ATL com property from VB client

8. atl com and vb client - the interface not match

9. Passing a structure between a VB client and an ATL com server

10. Passing a 2D SafeArray from VB client to ATL COM component

11. Problems using a ATL COM EXE Server with VB Client

12. Testing a Variant Output argument in ATL Com object using VB client

 

 
Powered by phpBB® Forum Software