Sign in to follow this  
Followers 0
myids

AutoIt COM object being closed unexpectedly

10 posts in this topic

How do I handle gracefully a situation where an AutoIt COM object being closed unexpectedly thru the object's GUI.

I am using Excel at the moment.

TIA

myids

Share this post


Link to post
Share on other sites



From the help file

$oMyError = ObjEvent("AutoIt.Error","MyErrFunc")

Func MyErrFunc()

  Msgbox(0,"AutoItCOM Test","We intercepted a COM Error !"      & @CRLF  & @CRLF & _
             "err.description is: "    & @TAB & $oMyError.description    & @CRLF & _
             "err.windescription:"     & @TAB & $oMyError.windescription & @CRLF & _
             "err.number is: "         & @TAB & hex($oMyError.number,8)  & @CRLF & _
             "err.lastdllerror is: "   & @TAB & $oMyError.lastdllerror   & @CRLF & _
             "err.scriptline is: "     & @TAB & $oMyError.scriptline     & @CRLF & _
             "err.source is: "         & @TAB & $oMyError.source         & @CRLF & _
             "err.helpfile is: "       & @TAB & $oMyError.helpfile       & @CRLF & _
             "err.helpcontext is: "    & @TAB & $oMyError.helpcontext _
            )
Endfunc

Share this post


Link to post
Share on other sites

Thanks very much for the reply.

This COM/Object stuff baffles me most of the time. I have more questions.

This isn't as importmant for me to know, but It looks like the custom error handler is executed in @error?

I am having some trouble implementing. Here's some of the code:

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_icon=..\..\..\..\..\..\Program Files (x86)\AutoIt3\Icons\ids_nl.ico
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <GUIConstants.au3>
#include <GuiListView.au3>
#include <Excel.au3>
#include <Array.au3>
#Include <Constants.au3>

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Define vars and capture values of PwrPCB object
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Global $Selected = 0
$powerPCBApp = ObjGet("", "PowerPCB.Application")
$powerPCBDoc = $powerPCBApp.ActiveDocument
$mcount = $powerPCBDoc.GetObjects(1).Count
$netcount = $powerPCBApp.Activedocument.Nets.Count
Dim $ListNets[$netcount]
Dim $cell_netlength, $cell_net, $mynet
Dim $NetProperties[2][$netcount]

Global $pcbname = $powerPCBApp.Activedocument.Name
Global $pcbpath = $powerPCBApp.Activedocument.Path
Global $pcbfullname = $powerPCBApp.Activedocument.FullName
Global $pcbssname = StringLeft($pcbname, StringLen($pcbname) - 4) & ".xls"
Global $ssisopen = ""
Global $ssfile = ""
Global $oExcel = ""
Global $oExcelIdent = ""
Global $g_eventerror = 0    ; to be checked to know if com error occurs. Must be reset after handling.
$oMyError = ""
$err = ""

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Setup the tray Icon
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Opt("TrayMenuMode",1)   ; Default tray menu items (Script Paused/Exit) will not be shown.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Menu For tray Icon
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
$OpenSSItem  = TrayCreateItem("Open SpreadSheet")
TrayCreateItem("")
$RunItem  = TrayCreateItem("Run Length Check")
TrayCreateItem("")
$SaveSSItem  = TrayCreateItem("Save SpreadSheet")
TrayCreateItem("")
$CloseSSItem  = TrayCreateItem("Close Spreadsheet")
TrayCreateItem("")
$aboutitem  = TrayCreateItem("About")
TrayCreateItem("")
$exititem   = TrayCreateItem("Exit")
TraySetState()
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Menu For tray Icon
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Loop though events/Menu options in tray icon
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
While 1
    $msg = TrayGetMsg()

            $oMyError = ObjEvent("AutoIt.Error","MyErrFunc")    ; Initialize a COM error handler
            If $g_eventerror then
                $g_eventerror = 0
                Msgbox (0,"AutoItCOM test","Test passed: We got an error number: " & @error)
                Exit
            Else
                Msgbox (0,"AutoItCOM test","Test failed!")



    Select
        Case $msg = 0
            ContinueLoop
        Case $msg = $RunItem
            TrayItemSetState($RunItem, $TRAY_CHECKED)
            GetNetLengths()


        Case $msg = $CloseSSItem
            TrayItemSetState($CloseSSItem, $TRAY_CHECKED)
            CloseSS()
        Case $msg = $SaveSSItem
            TrayItemSetState($SaveSSItem, $TRAY_CHECKED)
            SaveSS()
        Case $msg = $OpenSSItem
            TrayItemSetState($OpenSSItem, $TRAY_CHECKED)
            OpenSS()
        Case $msg = $aboutitem
            TrayItemSetState($aboutitem, $TRAY_CHECKED)
            Msgbox(64, "about:", "Interactive Design Solutions")
        Case $msg = $exititem
            ExitLoop
    EndSelect

    Endif ; branch of COM error testing

WEnd
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Loop though events/Menu options in tray icon
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Func MenuForTrayIcon()
;EndFunc

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Function: GetNetLengths
; retrieves all nets in pcb db in 2d array
; reads spreadsheet net columns and retrieves each nets routed lengths
; writes the routed length to the spreadsheet
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Func GetNetLengths()



    ;GUICreate($powerPCBApp.Activedocument.Name, 400, 200)
    ;GUISetIcon(@SystemDir & "\mspaint.exe", 0)
    ;GUISetState()
    $Index = 0
    For $nextNet In $powerPCBApp.Activedocument.Nets
        $NetProperties[0][$Index] = $nextNet.Name
        $NetProperties[1][$Index] = $nextNet.Length
        $cindex = $Index + 1
        ;GuiCtrlCreateListViewItem($nextNet.Name, $listView)
        ;_GUICtrlListView_AddItem ($ListView, $nextNet.Name)
        ;_ExcelWriteCell($oExcel, $nextNet.Name, $cindex, 1)
        ;_ExcelWriteCell($oExcel, RoutedNetLength ($nextNet.Name), $cindex, 2)
        $Index = $Index + 1
    Next
    ;_ArrayDisplay($NetProperties, "Net Properties", -1, 1)

    ;If $oExcel.ActiveSheet.Name Then
    ;   $Index = 0
    ;   For $i = 1 To 200 ;Loop
    ;       $cindex = $Index + 1
    ;       _ExcelWriteCell($oExcel, "0", $cindex, 2)
    ;       $Index = $Index + 1
    ;   Next
    ;EndIf

    $oMyError = ObjEvent("AutoIt.Error","MyErrFunc")
    If $g_eventerror then
    $g_eventerror = 0
        Msgbox (0,"AutoItCOM test","Test passed: We got an error number: " & @error)
    Else
        Msgbox (0,"AutoItCOM test","Test failed!")
    Endif


    If IsObj($oExcel) Then
        $Index = 0
        For $i = 1 To 200 ;Loop
            $cindex = $Index + 1
            $sCellValue = _ExcelReadCell($oExcel, $i, 1)
            $cell_net = StringStripWS($sCellValue, 3)
            If $cell_net = "Netname" Then
                $cell_net = ""
            EndIf
            ;ConsoleWrite( $cell_net & @CRLF)
            ;MsgBox(0, "", "cell_net is: " & @CRLF & $cell_net, 2)
            If StringLen($cell_net) Then
                $nlgth = FindNetinArray($cell_net)
                _ExcelWriteCell($oExcel, $nlgth, $i, 2)
            EndIf
            $Index = $Index + 1
        Next
    Else
        $oExcel = ""
        MsgBox(0, "SpreadSheet Was Not Open", "SpreadSheet Was Not Open" & @CRLF & "Open Spreadsheet, to Run a Length Check")
        ;OpenSS()
    EndIf
EndFunc

That should be all the relevant code. This version will always result in the "Test Failed" branch. Kind of obvious I guess. But I've tried embedded in getlength() and in the $RunItem CASE.

I don't understand enough for the mechanics of this. I could probably try for hours and days and finally get the code working, but I still don't know that I'll understand.

I can post the complete script if needed -- It doesn't seem to be relevent. NOTE: chances you can't run the whole script because of the other object being called?

hmmmm....does the other object I have open interfere? I don't think so because I can run the example from help file successfully.

Thanks very much for any tips on how to code this.

myids

Share this post


Link to post
Share on other sites

You don't put the error event in a loop. You set that up before you start creating objects I think.

Share this post


Link to post
Share on other sites

That was a big help. Thanks.

I am not sure where I need to reset $g_eventerror to 0, if that is the correct thing to do, after a COM error is intercepted.

I am using:

If NOT $g_eventerror Then

to run code if no $g_eventerror.

TIA,

myids

Share this post


Link to post
Share on other sites

This is another symptom if the Excel object was closed.

C:\Program Files (x86)\AutoIt3\Include\Excel.au3 (694) : ==> Missing right bracket ')' in expression.:

Return $oExcel.Activesheet.Cells($sRangeOrRow, $iColumn).Value

Return ^ ERROR

I think this is due to it being a second object, but not sure. Do I possibly need to setup a different flag or two?

Or

Is there a way to differentiate between objects for error handling?

TIA

myids

Share this post


Link to post
Share on other sites

I'm sorry but I don't know a lot about COM. I was just trying what I knew.

I don't know anything about the Excel objects either. :D

Share this post


Link to post
Share on other sites

Richard,

Thanks very much. You know more than I do. You helped me through to a better scenario and something that is workable.

Maybe someone else can chime in with more insight.

myids

Share this post


Link to post
Share on other sites

Well, I have a resolution although not so elegant and I'm not sure I understand it -- but, the code is behaving like I want it to so far. Luckily, this script isn't huge.

If NOT $g_eventerror then
   ;call/use the object/function here since there is no COM/Object error
Else
   ;reset/re-initialize the flag 
   $g_eventerror = 0
EndIf

Summary:

After getting the error handler working for a non-existent object, where previously the script would crash, multiple calls to multiple objects still crashed the script despite the error handler. My current solution is to use the above If/Else for EVERY single object usage and re-initialize the error handler flag so the next potential object error could be captured and messaged. I probably could have had the program EXIT once the COM error was intercepted, but, that isn't the behavior I was after. So, even though my solution is a bit of a hassle, it's the only thing that makes to me because The documentation advise on the error handler is that a reset is needed after every intercepted error.

Thanks for the help I received on this. If anyone has more thoughts and ideas for elegance, I'd love to read it.

myids

Share this post


Link to post
Share on other sites

Error handling is never "clean". What you've got now looks to be the best from what I can see.

Share this post


Link to post
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
Sign in to follow this  
Followers 0