Jump to content

COM error handler return values


Recommended Posts

Hello,

I'm trying to have a more transparent behaviour when trapping COM errors. This means that I want a call to a COM object to map through to something I can easily check, preferably the @error variable.

The example in ObjEvent uses "$g_eventerror = 1" to pass the error back to the script. But that is not so transparent because it needs to be reset every time before performing a potentially error-generating COM call.

I also see a lot of SetError(1) at the end of COM scripts, but when I print @error after the COM call, it seems to be set to the COM error, no matter what is written in the error handler. This behaviour would actually be exactly what I need, except that the @error doesn't get reset by the COM call itself, so e.g.

$oShell = ObjCreate("shell.application")
_DebugReport(@error & " " & @extended)
$oshell.open("D:")
_DebugReport(@error & " " & @extended)
$oshell.open ; missing parameter!
_DebugReport(@error & " " & @extended)
$oshell.open("c:")
_DebugReport(@error & " " & @extended)

will set the @error at the open call without parameters, but @error remains set from there on, even after the next successful call. So it would be necessary to reset it manually again just like $g_eventerror.

In some scripts I see attempts to return 0 from the error handler as well.

So my questions are:

  • Is there a specification about if and what the error handler should return and SetError()?
  • Is there a best practice of how to pass caught COM errors into the script for handling, that is as transparent and natural as possible (no preparation, preferably just mapped into @error)?
Thanks in advance!
Link to comment
Share on other sites

This is how I understand COM error handling:

According to the help file: "@error is always set to 0 when entering in a function." As long as you don't call a function @error wil not change. Using properties/methods of an object is not a function call and hence doesn't reset @error.

If a COM error occurres the error has to be handled by the user. In this error handling routine you have to reset @error using function Seterror.

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

This is how I understand COM error handling:

According to the help file: "@error is always set to 0 when entering in a function." As long as you don't call a function @error wil not change. Using properties/methods of an object is not a function call and hence doesn't reset @error.

If a COM error occurres the error has to be handled by the user. In this error handling routine you have to reset @error using function Seterror.

This is all false for new AutoIt.

COM error handling was written bad, used bad, though bad. That's not the case any more.

If COM error handler touches global variables in any way then that's badly written code. Check error handlers you know written and see how man are not bad. That all need changing.

To answer the questions...

So my questions are:

  • Is there a specification about if and what the error handler should return and SetError()?
  • Is there a best practice of how to pass caught COM errors into the script for handling, that is as transparent and natural as possible (no preparation, preferably just mapped into @error)?
Error handler should not set error.

After invoking just check @error value. Don't use COM error handler if you are not writing debugging code. This means that normal scripts don't need COM error handler.

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

@water:

Yes, that's what I also concluded, but that leaves the 2 questions open. I tried playing with SetError inside my own error handler and it didn't make a difference, I always saw the COM error propagate back to the user script (which is nice BTW). The problem of presetting it to zero before the call, as you say, remains.

So that's why I asked:

  • Knowing what happens with the @error and the regular return value within a user error handler would be nice, because I think it is not well specified in the documentation.
  • And having some level of abstraction (possibly not using @error) to make COM calls and have one single check after the call (without having to prepare for the call) would also be nice.

For the moment I made something like

; Returns true if the last COM call returned COM_S_OK
; Must be called once after each COM call, to prepare for handling
; the next call
Func COMSuccess()
Local $success = $__COMError[0] = $COM_S_OK
; Consume the error and prepare for next COM call
$__COMError[0] = $COM_S_OK
Return $success
EndFunc

but I don't like the mandatory aspect of HAVING to call the COMSuccess() to make sure the next COM call is prepared, it's easy to forget if you don't see the COM call clearly (e.g. a property access) or don't care about the error. From a software architecture point of view it should be ideal to have some transparent layer handling this. But I don't see how it could be wedged in, as you say: there's no user-definable hook into a COM outgoing call.

Edited by Vomit
Link to comment
Share on other sites

@trancexx

That's interesting to hear: so you say I can simply NOT install a COM error handler, and not having the script bomb out?

And just check @error?

I'll try that tomorrow, thanks for the tip!

Still leaves the clearing of @error to 0, I think, because I distinctly tested if it got reset by a COM call and it didn't.

Link to comment
Share on other sites

I was talking - and most of the time do talk - about the latest production version of AutoIt. My reference to the help file was to the latest release (3.3.8.1) too.

There might be a lot of changes in the beta, but it is - a beta.

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

I was talking - and most of the time do talk - about the latest production version of AutoIt. My reference to the help file was to the latest release (3.3.8.1) too.

There might be a lot of changes in the beta, but it is - a beta.

If you insist... you were more than half-wrong about 3.3.8.1 too. (Re)setting @error from error handler is wrong. Have you tried that? If COM error handler is running then @error is set to error value of the invocation, and if it's not running then the script will just fatal-error.

...There is still one glitch about setting @error to 0 on successful invocation. I'll fix that for the next beta, I'm not sure how I missed that.

Edited by trancexx

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

  • 8 months later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...