Jump to content

What does ObjEvent ("AutoIt.Error", "__UserComError") DO


Recommended Posts

G'day all

mdiesel and I have been bouncing this back a forward but neither of us are COM experts so we need to know WHAT it does.

We have a FUNCTION in mdiesels UDF that uses ObjEvent ("AutoIt.Error", "__UserComError") but we're worried that if the script this was included in also used ObjEvent ("AutoIt.Error", "__UserComError") before calling the function it would be reset by our function and their script would mysteriously break.

So mdiesel came up with a solution but he and I are unsure that is does what we think it will do and was hoping that a COM expert would confirm or fix it up for us.

Here are the important parts extracted

Global $oMyError

test()

Func test()
    Local $oMyErrorOld = ObjEvent("AutoIt.Error") ; Backup previous error handler
    Global $oMyError = ObjEvent("AutoIt.Error", "ComError") ; Set our error handler

    ; SOME CODE *************

    $oMyError = ObjEvent("AutoIt.Error", $oMyErrorOld) ; Restore old error handler
    $oMyError = 0 ; Clear object for later use (I just added this now to be tidy)
EndFunc   ;==>test

Func ComError()
    If IsObj($oMyError) Then
        SetError($oMyError.number)
    Else
        SetError(1)
    EndIf
    Return 0
EndFunc   ;==>ComError

or check out the mdiesels UDF _UserExt - Logging in and out.

Thanks for any/all help

John Morrison

Link to comment
Share on other sites

Yep, Thanks storme, I was just thinking of doing exactly this!

I think the part you added in (" = 0") isn't right though, as the function itself calls upon it here:

If IsObj($oMyError) Then
        SetError($oMyError.number)

The function objevent returns a handle to the obj, I think... :)

MDiesel

Link to comment
Share on other sites

  • Moderators

It sets an event handler in case an object fails for whatever reason.

You can only have one event handler registered at a time, so it would cause conflicts if you were including #includes that also have them.

A good way to practice or set yours up, would be to look at the IE.au3 #include that Dale has written. In it, he looks to see if the event handler is already registered, if it's not, registers it.

Look for #Region Internal functions in the IE.au3 #include, and primarily the __IEInternalErrorHandlerRegister() to see how he does it. Also the __IEInternalErrorHandlerDeRegister() on how to unregister it.

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

A good way to practice or set yours up, would be to look at the IE.au3 #include that Dale has written. In it, he looks to see if the event handler is already registered, if it's not, registers it.

kk, thats kinda similar to what I was trying to acheive. what I'm trying to get at is:

$oIEErrorHandler = ObjEvent("AutoIt.Error", $sIEUserErrorHandler)

What if their personal error handler uses a different variable, won't that muck it up? subsequently calling an object error in the object error handler....

Link to comment
Share on other sites

  • Moderators

kk, thats kinda similar to what I was trying to acheive. what I'm trying to get at is:

$oIEErrorHandler = ObjEvent("AutoIt.Error", $sIEUserErrorHandler)

What if their personal error handler uses a different variable, won't that muck it up? subsequently calling an object error in the object error handler....

:) ??? You're resetting it and then re-establishing it when you're done.

All $sIEUserErrorHandler does, is allow you as the user to set your own error handling function if you want rather than using IE.au3's default one.

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

Well I've done a little more testing...sigh

Here is the test program I came up with

Global $oMyError

Global $g_eventerror = 0 ; to be checked to know if com error occurs. Must be reset after handling.

$oMyError = ObjEvent("AutoIt.Error", "MyErrFunc") ; Install a custom error handler

; Performing a deliberate failure here (object does not exist)
$oIE = ObjCreate("InternetExplorer.Application")
$oIE.visible = 1
$oIE.bogus
If $g_eventerror Then MsgBox(0, "First Error", "the previous line got an error.")
$g_eventerror = 0

;Perform my test
test()

; Performing a deliberate failure here (object does not exist)
$oIE = ObjCreate("InternetExplorer.Application")
$oIE.visible = 1
$oIE.bogus
If $g_eventerror Then MsgBox(0, "SECOND ERROR", "the previous line got an error.")

Exit

Func test()
    Local $oMyErrorOld = ObjEvent("AutoIt.Error") ; Backup previous error handler
    Global $oMyError = ObjEvent("AutoIt.Error", "ComError") ; Set our error handler

    ; SOME CODE *************

    $oMyError = ObjEvent("AutoIt.Error", $oMyErrorOld) ; Restore old error handler
EndFunc   ;==>test

Func ComError()
    If IsObj($oMyError) Then
        SetError($oMyError.number)
    Else
        SetError(1)
    EndIf
    Return 0
EndFunc   ;==>ComError

; This is my custom error handler
Func MyErrFunc()
    $HexNumber = Hex($oMyError.number, 8)
    MsgBox(0, "", "We intercepted a COM Error !" & @CRLF & _
            "Number is: " & $HexNumber & @CRLF & _
            "Windescription is: " & $oMyError.windescription)

    $g_eventerror = 1 ; something to check for when this function returns
EndFunc   ;==>MyErrFuncoÝ÷ ÙhZ¶+l,ËajÛazâ)ÚJ뢸ZÙ^®+'ßÛkyéÚnWo+azƯz)àº{.­ë"¨Ëaz·,ÊìzÛb©j«¨¶×¦¦Ú¯*®¢×«®ájwez±Þ­è¬¶¨®("©¡×°êÞ¶®º+©Ýêâ²ëu«­¢+ÙÕ¹}UÍÉAÍÍݽÉ%Í ±¹¬ ÀÌØíÍUÍÉ9µôÅÕ½ÐìÅÕ½Ðì¤(1½°ÀÌØíÍUÍÉ1¥ÍÐôÅÕ½ÐìÅÕ½Ðì°ÀÌØíUÍÉ1¥ÍаÀÌØí½±½Õ¹ÑÌ°ÀÌØí¥±ÑÈ°ÀÌØí½©UÍÈ°ÀÌØí¥±ÑÉlÉtôlÅÕ½ÐíÕÍÈÅÕ½Ðít(1½°ÀÌØí½5åÉɽÉ=±ô=©Ù¹Ð ÅÕ½ÐíÕѽ%йÉɽÈÅÕ½Ðì¤(±½°ÀÌØí½5åÉɽÈô=©Ù¹Ð ÅÕ½ÐíÕѽ%йÉɽÈÅÕ½Ðì°ÅÕ½Ðí}}UÍÉ
½µÉɽÈÅÕ½Ðì¤(ÀÌØí½±½Õ¹ÑÌô=©Ð ÅÕ½Ðí]¥¹9Pè¼¼ÅÕ½ÐìµÀì
½µÁÕÑÉ9µ¤(ÀÌØí½±½Õ¹Ñ̹¥±ÑÈôÀÌØí¥±ÑÈ(½ÈÀÌØí½©UÍÈ%¸ÀÌØí½±½Õ¹ÑÌ(%ÀÌØíÍUÍÉ9µ¹ÀÌØí½©UÍȹ9µ±ÐìÐìÀÌØíÍUÍÉ9µQ¡¸(
½¹Ñ¥¹Õ1½½À(±Í(ÀÌØí½©UÍȹ
¡¹AÍÍÝ½É ÅÕ½ÐìÅÕ½Ðì°ÅÕ½ÐìÅÕ½Ðì¤(¹%((%ÉɽÈôÀ=ÈÉɽÈô´ÈÄÐÜÀÈÌÔØäQ¡¸ìÕÍÈ¥ÌÕÍ¥¹±¹¬ÁÍÍݽÉ(%ÀÌØíÍUÍÉ1¥ÍÐôÅÕ½ÐìÅÕ½ÐìQ¡¸(ÀÌØíÍUÍÉ1¥ÍеÀìôÀÌØí½©UÍȹ9µ(±Í(ÀÌØíÍUÍÉ1¥ÍеÀìôÅÕ½ÐíðÅÕ½ÐìµÀìÀÌØí½©UÍȹ9µ(¹%(¹%(MÑÉÉ½È À¤(9áÐ((ÀÌØí½±½Õ¹ÑÌôÅÕ½ÐìÅÕ½Ðì(ÀÌØí½©UÍÈôÅÕ½ÐìÅÕ½Ðì((%ÀÌØíÍUÍÉ9µ¹ÀÌØíÍUÍÉ1¥ÍÐôÀÌØíÍUÍÉ9µQ¡¸(±½°ÀÌØí½5åÉɽÈô=©Ù¹Ð ÅÕ½ÐíÕѽ%йÉɽÈÅÕ½Ðì°ÀÌØí½5åÉɽÉ=±¤(IÑÕɸQÉÕ(±Í%ÀÌØíÍUÍÉ9µQ¡¸(±½°ÀÌØí½5åÉɽÈô=©Ù¹Ð ÅÕ½ÐíÕѽ%йÉɽÈÅÕ½Ðì°ÀÌØí½5åÉɽÉ=±¤(IÑÕɸ±Í(±Í(ÀÌØíUÍÉ1¥ÍÐôMÑÉ¥¹MÁ±¥Ð ÀÌØíÍUÍÉ1¥ÍаÅÕ½ÐíðÅÕ½Ðì°È¤(±½°ÀÌØí½5åÉɽÈô=©Ù¹Ð ÅÕ½ÐíÕѽ%йÉɽÈÅÕ½Ðì°ÀÌØí½5åÉɽÉ=±¤(IÑÕɸÀÌØíUÍÉ1¥ÍÐ(¹%)¹Õ¹ìôôÐì}UÍÉAÍÍݽÉ%Í ±¹¬()Õ¹}}UÍÉ
½µÉÉ½È ¤(%%Í=¨ ÀÌØí½5åÉɽȤQ¡¸(MÑÉÉ½È ÀÌØí½5åÉɽȹ¹ÕµÈ¤(±Í(MÑÉÉ½È Ä¤(¹%(IÑÕɸÀ)¹Õ¹ìôôÐí}}UÍÉ
½µÉɽ

The error handler is used to capture failure of the line $objUser.ChangePassword ("", "").

If there is another way of handling this OR another way of checking for a "blank password" that would negate the need to user the error handler at all, PLEASE let us know.

Thanks for your help

John Morrison

Link to comment
Share on other sites

??

KK, some code. Its incredibly dodgy, and I cn't even get this to work!

<Snipped the code> johns actually works, and is a better representation

It only ever returns with an error of 1, and thats not right...

MDiesel

Hay don't be so hard on yourself your code isn't that much differnt to the original and you were just trying to avoid a problem I didn't even know existed till you pointed it out.

anyway here is the original code.

Func _WinPasswordIsBlank($sUserName = "")
    ;http://www.autoitscript.com/forum/index.php?showtopic=92240&view=findpost&p=680601
    ;author - ResNullius

    ;http://www.microsoft.com/technet/scriptcenter/resources/qanda/oct05/hey1006.mspx
    ;if called with no parameter, returns an array of all user accounts with no/blank password
    ;    otherwise, call with a username and it will return TRUE if password is blank/not set
    ;
    ;Note: will not return an account with a blank password where "User cannot change password" has been set
    ;                Also, no checking to see if a specified Account exists
    ;
    Global $oMyError = ObjEvent("AutoIt.Error", "ComError")
    Local $sUserList = "", $aUserList, $colAccounts, $aFilter, $objUser
    $colAccounts = ObjGet("WinNT://" & @ComputerName)
    Dim $aFilter[2] = ["user"]
    $colAccounts.Filter = $aFilter
    For $objUser In $colAccounts
        If $sUserName And $objUser.Name <> $sUserName Then
            ContinueLoop
        Else
            $objUser.ChangePassword("", "")
        EndIf

        If @error = 0 Or @error = -2147023569 Then; user is using a blank password
            If $sUserList = "" Then
                $sUserList &= $objUser.Name
            Else
                $sUserList &= "|" & $objUser.Name
            EndIf
        EndIf
        SetError(0)
    Next

    $colAccounts = ""
    $objUser = ""

    If $sUserName And $sUserList = $sUserName Then
        Return True
    ElseIf $sUserName Then
        Return False
    Else
        $aUserList = StringSplit($sUserList, "|", 2)
        Return $aUserList
    EndIf
EndFunc   ;==>_WinPasswordIsBlank

Func ComError()
    If IsObj($oMyError) Then
        SetError($oMyError.number)
    Else
        SetError(1)
    EndIf
    Return 0
EndFunc   ;==>ComError

Hope someone can find a better solution or a method to avoid using ObjEvent("AutoIt.Error",

Thanks for any help

John Morrison

Link to comment
Share on other sites

  • Moderators

I could have sworn that you could have de-referenced the object event handler. But re-looking at Dales code, I see he never found a way other than avoiding it all together if it was already referenced.

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

lod3n suggested a form on misdirection with ObjEvent that may be useful to you. You use Call from the function bound to AutoItError and evecute an arbitrary function based on a variable that you can control independantly:

$ComErrorHandlerFunction = "DeluxeComErrorHandler"
$GlobalErrorObject = ObjEvent("AutoIt.Error","ComErrFunc")
Func ComErrFunc()
    Return Call($ComErrorHandlerFunction,$GlobalErrorObject)
EndFunc

Func DeluxeComErrorHandler($errorEvent)
    If IsObj($errorEvent) Then
        
        ConsoleWrite("!--> DeluxeComErrorHandler: COM Error Encountered in " & @ScriptName & @CR)
        ConsoleWrite("----> Scriptline = " & $errorEvent.scriptline & @CR)
        ConsoleWrite("----> Number Hex = " & Hex($errorEvent.number, 8) & @CR)
        ConsoleWrite("----> Number = " & $errorEvent.number & @CR)
        ConsoleWrite("----> Win Description = " & StringStripWS($errorEvent.WinDescription, 2) & @CR)
        ConsoleWrite("----> Description = " & StringStripWS($errorEvent.description, 2) & @CR)
        ConsoleWrite("----> Source = " & $errorEvent.Source & @CR)
        ConsoleWrite("----> Help File = " & $errorEvent.HelpFile & @CR)
        ConsoleWrite("----> Help Context = " & $errorEvent.HelpContext & @CR)
        ConsoleWrite("----> Last Dll Error = " & $errorEvent.LastDllError & @crlf)
        
        $HexNumber = Hex($errorEvent.number, 8)
        SetError($HexNumber)
    Else
        SetError(1)
    EndIf
    $COMErrorProcessor = "customhandler2"
    Return 0
EndFunc

Func QuietComErrorHandler($errorEvent)
    ConsoleWrite("! QuietComErrorHandler: A COM error occured" & @CRLF)
    Return 0
EndFunc

Func FatalComErrorHandler($errorEvent)
    ConsoleWrite("! FatalComErrorHandler: A COM error occured" & @CRLF)
    Exit
EndFunc

$oDict = ObjCreate("Scripting.Dictionary")

$oDict.errorOut() ; trigger error using DeluxeComErrorHandler

$ComErrorHandlerFunction = "QuietComErrorHandler"
$oDict.errorOut() ; trigger error using QuietComErrorHandler

$ComErrorHandlerFunction = "FatalComErrorHandler"
$oDict.errorOut() ; trigger error using FatalComErrorHandler

Beep(100,100)
ConsoleWrite("FatalComErrorHandler should have stopped the script, so you shouldn't see this." & @CRLF)

Dale

Free Internet Tools: DebugBar, AutoIt IE Builder, HTTP UDF, MODIV2, IE Developer Toolbar, IEDocMon, Fiddler, HTML Validator, WGet, curl

MSDN docs: InternetExplorer Object, Document Object, Overviews and Tutorials, DHTML Objects, DHTML Events, WinHttpRequest, XmlHttpRequest, Cross-Frame Scripting, Office object model

Automate input type=file (Related)

Alternative to _IECreateEmbedded? better: _IECreatePseudoEmbedded  Better Better?

IE.au3 issues with Vista - Workarounds

SciTe Debug mode - it's magic: #AutoIt3Wrapper_run_debug_mode=Y

Doesn't work needs to be ripped out of the troubleshooting lexicon. It means that what you tried did not produce the results you expected. It begs the questions 1) what did you try?, 2) what did you expect? and 3) what happened instead?

Reproducer: a small (the smallest?) piece of stand-alone code that demonstrates your trouble

Link to comment
Share on other sites

  • Moderators

That works I guess, but isn't clean at all.

I kind of like the out of the box thinking personally.

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

kk, but ther is no method then to do it properly? In which case I'm going to go ahead and see if I can finalise that + get all the syntax right. As someone has said, It would be nice if you could associate error handling with particular variables. As there doesn't seem to be much in the way of a clean and proper method.

Thanks for all the help though, I am pobably going to do my own version of Dale's Register/UnRegister, as that seems a neat enough method.

Also, Is it possible to UnDim variables?? I know you can probably set them to "" or 0, but does actually remove them from the memory? How does all that stuff work..

MDiesel

Link to comment
Share on other sites

  • Moderators

Also, Is it possible to UnDim variables?? I know you can probably set them to "" or 0, but does actually remove them from the memory? How does all that stuff work..

MDiesel

Set it to 0 ... if you need a "nothing" variable for some object stuff: Dale again - http://www.autoitscript.com/forum/index.php?showtopic=64966

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

Variables are destroyed when they go out of scope. If they are global or are declared on the file level (not in a function) they will never be destroyed until the script ends.

Yep, thats the problem. But setting it to 0 is ok I suppose. That $Nothing thing from dale looks very useful too.

KK, my basic Idea (Back on the topic). Have I got the idea?

Func __UserRegisterError ()
   Global $oMyErrorOld = ObjEvent("AutoIt.Error")
   Global $oMyError = ObjEvent ("AutoIt.Error", "__UserComError")
EndFunc ; ==> __UserRegisterError

Func __UserRegisterError ()
   Global $oMyError = ObjEvent ("AutoIt.Error", $oMyErrorOld)
EndFunc ; ==> __UserRegisterError
Link to comment
Share on other sites

Yep, thats the problem. But setting it to 0 is OK I suppose. That $Nothing thing from dale looks very useful too.

KK, my basic Idea (Back on the topic). Have I got the idea?

< SNIP CODE >

Looks like AutoIT doesn't allow us to setup a new error handler if one is already setup. :)

I just ran my test program (old one had an error) and I keep get "Can't install a new Errorhandler when one is still active." when trying to blank out or reallocate the errorhandler.

Does anyone know how to "deallocate" an COM errorhandler?

Check out the code and make sure I haven't messed something up. I hope I have!!

Remember this is the situation where someone has "included a UDF that needs to allocate the errorhandler and the calling script has already allocated one.

OR

Any function that needs to use the errorhander to do it's work when the main script has already allocated one.

Global $oMyError

Global $g_eventerror = 0 ; to be checked to know if com error occurs. Must be reset after handling.

Local $oMyErrFunc = ObjEvent("AutoIt.Error", "MyErrFunc") ; Install a custom error handler


; Performing a deliberate failure here (object does not exist)
$oIE = ObjCreate("InternetExplorer.Application")
$oIE.visible = 1
$oIE.bogus
If $g_eventerror Then MsgBox(0, "First Error", "the previous line got an error.")
$oIE.quit                    ; Quit IE
$oIE=0                       ; Remove IE from memory (not really necessary)
$g_eventerror = 0

;Perform my test
test()
If $g_eventerror Then MsgBox(0, "First Error", "the previous function..... YOU shouldn't see this!!!")
$g_eventerror = 0

; Performing a deliberate failure here (object does not exist)
$oIE = ObjCreate("InternetExplorer.Application")
$oIE.visible = 1
$oIE.REALbogus
If $g_eventerror Then MsgBox(0, "SECOND ERROR", "the previous line got an error.")
$oIE.quit                    ; Quit IE
$oIE=0                       ; Remove IE from memory (not really necessary)

Exit

Func test()
    MsgBox(0, "test Function", "START")
    Local $oMyErrorOld = ObjEvent("AutoIt.Error") ; Backup previous error handler
    MsgBox(0, "test Function", "OLD saved - DONE")
    Global $oMyError = ObjEvent("AutoIt.Error", "") ; Set our error handler
    MsgBox(0, "test Function", "RESET Error handler - DONE")
    $oMyError = ObjEvent("AutoIt.Error", "ComError") ; Set our error handler
    MsgBox(0, "test Function", "SET NEW Error handler - DONE")

    ;ConsoleWrite("error handler = " & $oMyError)
    
    ; SOME CODE *************

    $oMyError = ObjEvent("AutoIt.Error", $oMyErrorOld) ; Restore old error handler
EndFunc   ;==>test

Func ComError()
    ConsoleWrite("HELLO from ComError" & @CR)
    $HexNumber = Hex($oMyErrFunc.number, 8)
    MsgBox(0, "", "ComError intercepted a COM Error !" & @CRLF & _
            "Number is: " & $HexNumber & @CRLF & _
            "Windescription is: " & $oMyErrFunc.windescription)

    ConsoleWrite("ComError intercepted a COM Error !" & @CRLF & _
            "Number is: " & $HexNumber & @CRLF & _
            "Windescription is: " & $oMyErrFunc.windescription & @CR)
EndFunc   ;==>ComError

; This is my custom error handler
Func MyErrFunc()
    ConsoleWrite("HELLO from MyErrFunc" & @CR)
    $HexNumber = Hex($oMyErrFunc.number, 8)
    MsgBox(0, "", "MyErrFunc intercepted a COM Error !" & @CRLF & _
            "Number is: " & $HexNumber & @CRLF & _
            "Windescription is: " & $oMyErrFunc.windescription)

    ConsoleWrite("MyErrFunc intercepted a COM Error !" & @CRLF & _
            "Number is: " & $HexNumber & @CRLF & _
            "Windescription is: " & $oMyErrFunc.windescription & @CR)

    $g_eventerror = 1 ; something to check for when this function returns
EndFunc   ;==>MyErrFunc

Good Luck

John Morrison

Link to comment
Share on other sites

You deregister an error handler by setting the instatiation valiable to null or 0.

I know of no other way than what I have done in IE.au3. When I am using it internal to IE.au3, I register an error handler and then deregister before I hand control back to the user. If there is already an error handler registered, there is nothing I can do unless I know the instantiation variable that holds the reference. If I know it, I degegister the user error handler, register mine, dregister mine and and re-register theirs before handing control back to the user. If I don't know their instantiation variable there is nothing I can do and COM error trapping cannot be done by IE.au3.

This is why I offer a _IEErrorHandlerRegister function in IE.au3. If they call this function with no parameters it will simply register the function I have in IE.au3 (which is usually sufficient if the goal is to make COM errors non-fatal)... if they pass a function name, I will register theirs. In either case, the important thing is that the instatiation variable is set to a predetermined Global variable so that the other routines in IE.au3 can find it and work through the complex deregister, register, deregister, register process described above.

In the current implementation I don't think there is any alternative (other than what I posted from lod3n above) -- I worked on this for a long time before settling on it as the best answer.

Dale

Edit: fixed typo and added clarity

Edited by DaleHohm

Free Internet Tools: DebugBar, AutoIt IE Builder, HTTP UDF, MODIV2, IE Developer Toolbar, IEDocMon, Fiddler, HTML Validator, WGet, curl

MSDN docs: InternetExplorer Object, Document Object, Overviews and Tutorials, DHTML Objects, DHTML Events, WinHttpRequest, XmlHttpRequest, Cross-Frame Scripting, Office object model

Automate input type=file (Related)

Alternative to _IECreateEmbedded? better: _IECreatePseudoEmbedded  Better Better?

IE.au3 issues with Vista - Workarounds

SciTe Debug mode - it's magic: #AutoIt3Wrapper_run_debug_mode=Y

Doesn't work needs to be ripped out of the troubleshooting lexicon. It means that what you tried did not produce the results you expected. It begs the questions 1) what did you try?, 2) what did you expect? and 3) what happened instead?

Reproducer: a small (the smallest?) piece of stand-alone code that demonstrates your trouble

Link to comment
Share on other sites

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...