Jump to content
Sign in to follow this  
martin

AutoMonIt - a way to monitor your own script

Recommended Posts

martin

This is a way to monitor your script.

It could help to debug a script but it is not claimed that this is a debugger.

No changes to your script are needed.

post-3602-1190052192_thumb.png

It is limited to being able to monitor up to 10 Global variables.

(Any 10, and you can keep changing them. Actually only 9 if your scrreeen resolution is 600 or less vertically.)

It will only work with a script which runs. If the script has bugs which stop it running then this program might not help, although it will monitor until it stops.

The variables can be changed while you're monitoring.

The rate of updating the variables can be changed.

The window width can be stretched to see long variable values. The height can be reduced to show just one.

To use it you need to have these udfs in your include folder-

dllcallback.au3 from here

nomadmemory.au3 from here.

There are 2 files needed and they are both shown below.

Put them both in the same folder.

The first script is MonIt.au3. It must be saved with that name and in the same folder as AutoMonIt.au3

The second script is AutoMonIt.au3 and this is the script to run.

When AutoMonIt runs you can choose a script , and then when that script runs you can enter variable names to monitor.

You can enter the name with or without the leading $, ie fred or $fred.

Variables can be arrays in which case you must enter something like Contacts[3][2] or $Contacts[3][2]

You can monitor macros like @ScriptDir, even though they might not be used in the monitored script. So for example @ScriptDir will give the path to the monitored script etc. (No use for @ScriptLineNumber though in case you were wondering.)

The script can be stopped and run again without closing AutoMonIt.

This means that if you use it to help develop a script, you can run the script, examine variables, stop it, edit the script, run it again. This could reduce the need to add debugging lines like consolewrite, or msgbox which are later removed again.

If you want to monitor local variables in functions then it requires a modification to your script and a different version of AutoMonIt.

But as it is you could make a temporary change to your script to have the local variables changed to global.

Save this but don't run it. (You can try but it won't work, but despite that it's essential!)

;MonIt.au3
;uses message numbers $WM_USER +2000,2001,2002
;V1.2 15th Sept tried to declare all variables (MustDeclareVars)
;V1.21 added free callback stub on close.
; changed message numbers
; delete temp au3 file on exit
#include <GUIConstants.au3>
#include <misc.au3>
#include <dllcallback.au3>

Global $MonItretval,$MonItpt,$MonIthStub_T,$MonItUpDatePeriod = 200,$MonItpnID1,$MonitStruct,$MonitLinked
Const $MonitTimer = 900;timer number reserved for monitoring
Global $newMonItVar='',$lastMonItVar = ''
Global $hAutoMonIt = WinGetHandle("AutoMonIt")
Global $MonItNames[10];the names of the variables to be monitored
Const $MonItMaxReturn = 200;must be set the same in AutoMonIt
;char[40][10] doesn't work with memory read
Local $dstruct = "int;int;char[100];int"
Local $dn
For $dn = 1 To 10
    $dstruct &= StringFormat(";char[%d]",$MonItMaxReturn)
Next
Global $MonItStruct = DllStructCreate($dstruct)
; type                      element offset  description
;~ int               1      0           request type
;~ int                          2       4           request parameter 1
;~ char[100]                    3       8           request parameter 2
;~ int               4      108         reply to request
;~ char[10][$MonItMaxReturn]    5 112   10 variable values, limited to $MonItMaxREturn chars

Global $TempMonItTitle = "MonIt Startup Window"
Global $MonItWind = GUICreate($TempMonItTitle,200,200);for handle and debug
Global $labmon1 = GUICtrlCreateLabel("-----",10,10,150,21)
Global $labmon2 = GUICtrlCreateLabel("-----",10,30,150,21)
Global $labmon3 = GUICtrlCreateLabel("-----",10,50,150,21)
Global $labmon4 = GUICtrlCreateLabel("-----",10,70,150,21)
Global $labmon5 = GUICtrlCreateLabel("-----",10,90,150,21)
Global $labmon6 = GUICtrlCreateLabel("-----",10,110,150,21)
Global $labmon7 = GUICtrlCreateLabel("-----",10,130,150,21)

GUISetState()

Const $MIRequest = 1, $MIReqParam1 = 2, $MIReqParam2 = 3, $MIReply = 4, $MIVals = 5
Global $MonItAddress = DllStructGetPtr($MonItStruct)
Global $MonItNewTime, $waitAns
GUICtrlSetData($labmon4,Hex($MonItAddress))

Global $MonitLinked = False;not linked to AutoMonIt
GUIRegisterMsg($WM_USER + 2001,"MonItSetLink")
Global $MonItHandle = WinGetHandle($TempMonItTitle);

;tell AutoMonIt who we are
_SendMessage(WinGetHandle("AutoMonIt"),$WM_USER + 2000,$MonItHandle)
$waitAns = TimerInit()
While Not $MonitLinked
    If TimerDiff($waitAns) > 2000 Then
        MsgBox(0,"ERROR","Failed to establish link to AutoMonIt!")
        Exit
    EndIf
WEnd

;set the timer up for updating monitored data
$MonItpt = DllStructCreate("int64")
DllStructSetData($MonItpt, 1, $MonitTimer);set the timer ref number
$MonItpnID1 = DllStructGetPtr($MonItpt,1);ptrs to the timer ref no struct
$MonIthStub_T = _DllCallBack ("MonItTransmit", "hwnd;int;ptr;int")
$MonItretval = DllCall("user32.dll", "int", "SetTimer", "hwnd", $MonItHandle, "ptr", $MonItpnID1, "int", $MonItUpDatePeriod, "ptr", $MonIthStub_T)
GUISetState(@SW_HIDE,$MonItWind)
;
;shouldn't matter if script to monitor uses event driven option because we only use the transmit fn from now on
#include '#x#x#x#xx#AutoMonIt script goes here#x#x#x#x#x#'

; Func MonitTransmit
; This is the callback function for the timer.
; Responds to requests from AutoMoIt and sets the values of requested variables in the
; $MonItStruct DllStruct.
; Reads and writes to the struct with DllStructGetData/SetData.
; AutoMonIt reads and writes to the struct with Memoryread/write
; VOID CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime);
;   hwnd    [in] Handle to the window associated with the timer.
;   uMsg    [in] Specifies the WM_TIMER message.
;   idEvent [in] Specifies the timer's identifier. (UINT_PTR)
;   dwTime [in] Specifies the number of mS elapsed since the system was started.

Func MonItTransmit($MThwnd, $MTuMsg, $MTidEvent, $MTdwTime);
    Local $request,$retval,$MonItNewTime,$MonItUpDatePeriod,$MonItTimerNumber
    Local $varnum,$varname,$varname2
    Local $MonItts = DllStructCreate("int", $MTidEvent)
    $MonItTimerNumber = DllStructGetData($MonItts, 1)
    If $MonItTimerNumber <> $MonItTimer Then
        GUICtrlSetData($labmon3,"wrong timer")
        Return
    EndIf
    
;the timer interrupt was the one we respond to so carry on
    
    If Not WinExists($hAutoMonIt) Then
        MsgBox(0,"AutoMonIt does not exist","Closing Monitored script.")
        MonItClose($MonItts)
    EndIf
    
    $request = DllStructGetData($MonItStruct,1)
    If $request <> 0 Then;we have a request from automonit
        GUICtrlSetData($labmon2,$request)
        
        Switch $request
            Case 10;set timer period
                $MonItNewTime = DllStructGetData($MonItStruct,$MIReqParam1)
                GUICtrlSetData($labmon3,$MonItNewTime)
                If $MonItNewTime <> $MonitTimer And $MonItNewTime > 99 And $MonItNewTime < 2001 Then
                    $retval = DllCall("user32.dll", "int", "KillTimer", "hwnd", $MonItHandle, "ptr", $MonItpnID1)
                    $MonItUpDatePeriod = $MonItNewTime
                    Local $MonItretval = DllCall("user32.dll", "int", "SetTimer", "hwnd", $MonItHandle, "ptr", $MonItpnID1, "int", $MonItUpDatePeriod, "ptr", $MonIthStub_T)
                    DllStructSetData($MonItStruct,$MIReply,100);100=ok
                EndIf
                
            Case 21;run mode
                Local $runParam = DllStructGetData($MonItStruct,$MIReqParam1)
                If $runParam = 10 Then
                    MonItClose($MonItts)
                EndIf
                
            Case 91;monitor new variable
                $varnum = DllStructGetData($MonItStruct,$MIReqParam1)
                $varname = StringReplace(DllStructGetData($MonItStruct,$MIReqParam2),' ,'')
                GUICtrlSetData($labmon3,$varnum)
                GUICtrlSetData($labmon4,"{:content:}quot; & $varname)
                

;monitor var number, variable name
                If $varname <> $MonItNames[$varnum-1] Then;variable has been changed
                    If $varname = '' Then DllStructSetData($MonItStruct,$MIVals,'',$varnum);clear the value
                    $MonItNames[$varnum-1] = $varname
                    If Not StringInStr($varname,'(') And $varname <> '' Then;expressions and functions not allowed
                        $varname2 = StringSplit($varname,'['); In Case it's an array
                        
                        If IsDeclared($varname2[1]) Then
                            DllStructSetData($MonItStruct,$MIReply,$varnum);1 to 10 = ok
                            GUICtrlSetData($labmon6,"= " & String(Execute( "{:content:}quot; & $MonItNames[$varnum - 1])))
                        Else
                            DllStructSetData($MonItStruct,$MIReply,-$varnum);-=failed
                            DllStructSetData($MonItStruct,$MIVals,'',$varnum);clear the value
                            GUICtrlSetData($labmon6,"cannot allocate value")
                        EndIf
                    Else
                        GUICtrlSetData($labmon6,"cannot parse functions")
                    EndIf
                Else
                    GUICtrlSetData($labmon6,"name " & $varnum & " not changed")
                EndIf
                
                
            Case Else
                DllStructSetData($MonItStruct,$MIReply,-9000);unknown request
                
        EndSwitch
    EndIf
    DllStructSetData($MonItStruct,$MIRequest,0);request dealt with successful or not

;doesn't actually transmit anything, just writes the values in the struct so AutoMonIt can read them
    For $MonMon = 1 To 10;for the 10 variables monitored
        If $MonItNames[$MonMon - 1] <> '' Then
            If StringLeft($MonItNames[$MonMon - 1],1) = '@' Then
                DllStructSetData($MonItStruct,$MIVals + $MonMon - 1,StringLeft(String(Execute($MonItNames[$MonMon - 1])),39))
            Else
                DllStructSetData($MonItStruct,$MIVals + $MonMon - 1,StringLeft(String(Execute("{:content:}quot; & $MonItNames[$MonMon - 1])),$MonItMaxReturn - 1))
            EndIf
        Else
            DllStructSetData($MonItStruct,$MIVals + $MonMon - 1,'')
        EndIf
    Next
;timing this function = .8 to 1.0 mS when 10 variables monitored on my old laptop
;doubling the lines which dealt with the timing, to see what effect they had, made no obvious difference.
    
EndFunc;==>transmit


Func MonItSetLink()
;we got a message from AutoMonIt so it has seen us
    If Not WinExists("AutoMonIt") Then
        $MonitLinked = False
        Return
    EndIf
    
;Tell AutoMonIt where the monitored data is stored
    _SendMessage(WinGetHandle("AutoMonIt"), $WM_USER + 2002, $MonItAddress, @AutoItPID, 0, "ptr", "ptr")
    GUICtrlSetData($labmon1,Hex(@AutoItPID))

    $MonitLinked = True
EndFunc;==>link

Func MonItClose($timerstruct)
;stop the timer
    DllCall("user32.dll", "int", "KillTimer", "hwnd", $MonItHandle, "ptr", $MonItpnID1)
    _DllCallBack_Free($MonIthStub_T);free callback stub
    $MonItStruct = 0;destroy struct
    $timerstruct = 0;destroy struct
    FileDelete("MonItTemp.au3")
    Exit
EndFunc

The script to run

;AutoMonIt.au3

;v1.01 10th Sept 2007
; working dir set correctly if script typed in rather than using browse
; Variables started up again if script being monitored is stopped then started again
;V1.02 15th Sept 2007
; improved resizing so Val input boxes expand with the window width
; added logging the first (topmost) val to notepad if the notepad title is
; set to 'AutoMonItADE' by saving to that name.
; CARE! every change to the val will be written to notepad, so if the value changes every 100ms
; you will end up with a big file.
;V1.03 Forgot to allow for longer variable value data to use in the wider display, so increased to 200 char max
;V1.04 allow for Beta or production scripts and read autoit3.exe paths from registry
;V1.05 Enter key will set var names so don't have to click Apply button
; fixed bug with entering script path rather than browsing.
; chnaged message numbers
; added MonItClose func
; Tidied timer combo and set Default To 200 mS
; Added Rob Saunders _GuiGetFocus fn - thanks Rob
;V1.06 Reduced height of window to 632 mainly by removed note at bottom and changing way error displayed
; achieved height of 600 for small screen res by reducing to 9 variables
;V1.07 Minor correction to missplaced line affecting resizing of inut for variablename.
; Cleared variable values when starting a script again
Const $AMVer = "V1.07"
#include <GUIConstants.au3>
#include <misc.au3>
#include <nomadmemory.au3>

Opt("GUIResizeMode",BitOR($GUI_DOCKLEFT,$GUI_DOCKTOP,$GUI_DOCKWIDTH,$GUI_DOCKHEIGHT))

Global $AutoMonItHandle, $AutoMonItMemOpen = 0, $AutoMonItMemAdd = 0,$AutoMonItNextREq, $AutoMonItNextREqParam1, $AutoMonItNextREqParam2, $AutoMonItrunning
Const $AutoMonItRequest = 1, $AutoMonItReqParam1 = 2, $AutoMonItReqParam2 = 3, $AutoMonItReply = 4, $AutoMonItVals = 5
Global $inputVar[10],$InputVarVal[10],$BtnApplyVar[10]
Global $AutoMonItValsRead[10],$AutoMonItVarStatus[10]
Global $status, $laststatus
Global $ReqCount, $RepCount
Const $WM_GETMINMAXINFO = 0x24;<----------remove line for AuoIt Beta V3.2.9.2 or later
Const $AutoMonItMaxReturn = 200;must be set the same in MonIt.au3
Const $AutoMonItValMemType = StringFormat("char[%d]",$AutoMonItMaxReturn)
Const $failtext = "Not Found. Not Global or not used yet."
Const $goodcol = 0xfffaa0, $badcol = 0xff4444
$winheight = 598;actually gives 632 on my PC, client is 598 I think
$Maxvar = 10
$reduce = 0
$AMSpacing = 48
If @DesktopHeight <= 601 Then
    $maxvar = 9
    $reduce = $AMSpacing
EndIf



Const $AMTitle = "AutoMonIt " & $AMVer,$AMLinked = $AMTitle & " - linked"

$AutoMonItForm = GUICreate($AMTitle, 275, 598 - $reduce, 511, 148, BitOR($WS_MINIMIZEBOX,$WS_SIZEBOX,$WS_THICKFRAME,$WS_SYSMENU,$WS_CAPTION,$WS_POPUP,$WS_POPUPWINDOW,$WS_GROUP,$WS_BORDER,$WS_CLIPSIBLINGS), BitOR($WS_EX_TOPMOST,$WS_EX_WINDOWEDGE))

$Group2 = GUICtrlCreateGroup("Script to monitor", 2, 0, 271, 64)
GUICtrlSetResizing(-1,BitOR($GUI_DOCKTOP,$GUI_DOCKHEIGHT))
$IPScriptPath = GUICtrlCreateInput("", 7, 16, 210, 21);edit1
GUICtrlSetResizing(-1,BitOR($GUI_DOCKTOP,$GUI_DOCKHEIGHT,$GUI_DOCKLEFT,$GUI_DOCKRIGHT))
$BtnBrowseScipt = GUICtrlCreateButton("&Browse", 222, 13, 45, 25, 0)
GUICtrlSetResizing(-1,BitOR($GUI_DOCKTOP,$GUI_DOCKHEIGHT,$GUI_DOCKRIGHT,$GUI_DOCKWIDTH))
$Radio1 = GUICtrlCreateRadio("Beta", 12, 42, 49, 17)
GUICtrlSetState(-1, $GUI_CHECKED)
$Radio2 = GUICtrlCreateRadio("Production", 92, 42, 74, 17)
$LabStatus = GUICtrlCreateLabel("Status", 183, 44, 85, 17)
GUICtrlSetColor(-1, 0x008000)
GUICtrlCreateGroup("", -99, -99, 1, 1)


$BtnStart = GUICtrlCreateButton("Start", 8, 66, 48, 24, 0)
$BtnStop = GUICtrlCreateButton("Stop", 222, 66, 47, 25, 0)
$Label2 = GUICtrlCreateLabel("Update every", 66, 71, 66, 17)
$Combo1 = GUICtrlCreateCombo("100 mS", 133, 68, 69, 25);edit2
GUICtrlSetData(-1, "200 mS|300 mS|400 mS|500 mS|750 mS|1000 mS|2000 mS","200 mS")

$Group1 = GUICtrlCreateGroup("Variables to monitor", 2, 95, 271, 500 - $reduce)
GUICtrlSetResizing(-1,BitOR($GUI_DOCKTOP,$GUI_DOCKHEIGHT))

;create all inputs for variable names in succession so can TAB from one to other
For $in = 0 To $maxvar - 1
    $inputVar[$in] = GUICtrlCreateInput("", 40, 117 + $AMSpacing * $in, 180, 21);Edit3,5,..21
        GUICtrlSetResizing(-1,BitOR($GUI_DOCKTOP,$GUI_DOCKLEFT,$GUI_DOCKHEIGHT,$GUI_DOCKRIGHT))
Next
;create input for variable values and Apply buttons
For $in = 0 To $maxvar - 1
    GUICtrlSetTip(-1,'Enter the variable name with or without the & @LF & 'Press Enter or click Apply to set the new variable','',0,1)
    $InputVarVal[$in] = GUICtrlCreateInput("", 40, 139 + $AMSpacing * $in, 222, 21, BitOR($ES_AUTOHSCROLL,$ES_READONLY))
    GUICtrlSetResizing(-1,BitOR($GUI_DOCKTOP,$GUI_DOCKLEFT,$GUI_DOCKHEIGHT,$GUI_DOCKRIGHT))
    GUICtrlCreateLabel("Name", 7, 120 + $AMSpacing * $in, 32, 17)
    GUICtrlCreateLabel("Val", 21, 142 + $AMSpacing* $in, 19, 17)
    
    $BtnApplyVar[$in] = GUICtrlCreateButton("Apply", 222, 115 + $AMSpacing * $in, 40, 24, 0)
    GUICtrlSetResizing(-1,BitOR($GUI_DOCKTOP,$GUI_DOCKHEIGHT,$GUI_DOCKRIGHT,$GUI_DOCKWIDTH))
Next

GUICtrlCreateGroup("", -99, -99, 1, 1)
;$VarName = GUICtrlCreateInput("VarName", 40, 635, 121, 21)

GUISetState(@SW_SHOW)

GUIRegisterMsg($WM_USER + 2000,"GetAppHandle")
GUIRegisterMsg($WM_USER + 2002,"GetDataAddr")
GUIRegisterMsg($WM_GETMINMAXINFO, "MY_WM_GETMINMAXINFO")

$AutoItProdexePath = RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\AutoIt v3\AutoIt","InstallDir");installDir for production
$AutoItBetaexePath = RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\AutoIt v3\AutoIt","betaInstallDir");installDir for production
$AutoItexePath = $AutoItBetaexePath;default to beta
While 1
    While 1
        
        $nMsg = GUIGetMsg()
        Switch $nMsg
            Case $GUI_EVENT_CLOSE
                Exit
            Case $BtnBrowseScipt
                $AutoMonItScript = FileOpenDialog("Select au3 script to monitor",@WorkingDir & "\", "AutoIt script (*.au3)",3)
                If @error <> 1 Then
                    GUICtrlSetData($IPScriptPath,$AutoMonItScript)
                EndIf
            Case $BtnStart
                $AutoMonItScript = GUICtrlRead($IPScriptPath)
                If BitAND(GUICtrlRead($radio1),$GUI_CHECKED) Then
                    $AutoItexePath = $AutoItBetaexePath
                Else
                    $AutoItexePath = $AutoItProdexePath
                EndIf
                
                ExitLoop
        EndSwitch
        
    WEnd

        For $in = 0 To 9
 GUICtrlSetData($InputVarVal[$in],'')   
    Next
    
        FileChangeDir(StringLeft($AutoMonItScript,StringInStr($AutoMonItScript,'\',0,-1) -1));in case scriptpath is typed in
    $RepCount = 0
    $ReqCount = 0
    
    $AutoMonItText = FileRead(@SCriptDir & "\MonIt.au3")
    $AutoMonItScript = GUICtrlRead($IPScriptPath)
    If FileExists("MonItTemp.au3") Then FileDelete("MonItTemp.au3")
    
    $AutoMonItText = StringReplace($AutoMonItText,"#include <dllcallback.au3>","#include " & "'" & $AutoItBetaexePath & "\Include\dllcallback.au3'")
    $AutoMonItText = StringReplace($AutoMonItText,"#include '#x#x#x#xx#AutoMonIt script goes here#x#x#x#x#x#'","#include " & "'" &$AutoMonItScript & "'")
    FileWrite("MonItTemp.au3",$AutoMonItText)
    
    Run( '"' & $AutoItexePath & '\AutoIt3.exe" MonItTemp.au3')
    WinWait("MonIt Startup Window","",5)
    $AutoMonItrunning = True
    $ADE = False
    
;in case we are starting the same script again and variables have already been entered, we need to
;start them to being monitored again
    If RestartExisting() <> -1 Then;stop but pressed
        GUICtrlSetState($BtnStart,$GUI_DISABLE)
        GUICtrlSetState($InputVar[0],$GUI_FOCUS)
        While $AutoMonItrunning
            $nMsg = AM_GUIGetMsg()
            Switch $nMsg
                Case $GUI_EVENT_CLOSE
                    Exit
                Case $BtnApplyVar[0] To $BtnApplyVar[$maxvar - 1];not good because this includes other controls, to be improved
                    Local $bn, $nvar
                    For $bn = 0 To $maxvar - 1
                        If $nMsg = $BtnApplyVar[$bn] Then
            ;set Apply btn to focus doesn't work=creates a new msg for the first button focused!
                            GUICtrlSetState($InputVar[$bn],$GUI_FOCUS);val?
                            $nvar = $bn
            ;hint will have served it's purpose by now so delete before it gets annoying
                            For $ntt = 0 To $maxvar - 1
                                GUICtrlSetTip($inputVar[$ntt],'')
                            Next
                            
                            ExitLoop
                        EndIf
                    Next
                    If GUICtrlRead($inputVar[$nvar]) = '' Then
                        GUICtrlSetBkColor($inputVarVal[$nvar],0xffffff)
                        GUICtrlSetData($inputVarVal[$nvar],'')
                    EndIf
                    
                    $AutoMonItNextREqParam1 = $nvar + 1
                    $AutoMonItNextREqParam2 = GUICtrlRead($inputVar[$nvar])
    ;set req last so message not sent with wrong params
                    $AutoMonItNextREq = 91;monitor new variable
                Case $Combo1
                    
                    $AutoMonItNextREqParam1 = Number(StringReplace(GUICtrlRead($Combo1),'mS',''))
                    $AutoMonItNextREqParam2 = ''
                    $AutoMonItNextREq = 10;set timer
                Case $BtnStop
                    $AutoMonItNextREqParam1 = 10;exit
                    $AutoMonItNextREq = 21;run mode

            EndSwitch
            
            If Not WinExists("MonIt Startup Window") Then $AutoMonItrunning = False
            $ADE = WinExists("AutoMonItade")
        WEnd
    EndIf

;$nMsg = AM_GUIGetMsg()
    WinSetTitle($AutoMonItForm,"",$AMTitle)
;ConsoleWrite("MonIt has stopped" & @CRLF)
    GUICtrlSetState($BtnStart,$GUI_ENABLE)
    _MemoryClose($AutoMonItMemOpen)
    $AutoMonItMemOpen = 0
WEnd

Func AM_GUIGetMsg()
;Hope someone will tell me correct way to do this
    If _IsPressed("0D") Then
        $ctrlEnter = _GuiGetFocus($AutoMonItForm)
        For $bn = 0 To $maxvar - 1
            If $ctrlEnter = $inputVar[$bn] Then
                ConsoleWrite($ctrlEnter & '=' & $BtnApplyVar[$bn] & ', ')
                While _IsPressed("0D")
                WEnd;wait for release of Enter key
                Return $BtnApplyVar[$bn]
            EndIf
        Next
    EndIf
    
    Return GUIGetMsg()
EndFunc

Func update()
;$AutoMonItStruct = DllStructCreate("int;char[100];int;char[40][10]") in MonIt
; type          element offset  description
;~ int   1      0           request type
;~ int              2       4           request parameter 1
;~ char[100]        3       8           request parameter 2
;~ int   4      108         reply to request
;~ char[40][10]     5 112   variable values

    If $AutoMonItMemOpen = 0 Then Return;we haven't got the address of the struct
    
    Local $update = _MemoryRead ($AutoMonItMemAdd, $AutoMonItMemOpen, "int");read request
    If $update = 0 Then;MonIt has dealt with last request
        
        Local $status = _MemoryRead (AddrCalc($AutoMonItMemAdd,108), $AutoMonItMemOpen, "int");read reply to request
        If $status <> 0 Then;if there is a reply to read
            $RepCount += 1
            If $status <> $laststatus Then
                GUICtrlSetData($LabStatus,"status = " & $status)
                $laststatus = $status
            EndIf
            
            
            Switch $status
                Case 1 To 10;means variable was set ok
                    $AutoMonItVarStatus[$status - 1] = 1;ok
                    GUICtrlSetBkColor($inputVarVal[$status - 1],$goodcol)
                    If GUICtrlRead($inputvar[$status - 1]) = '' Then
                        GUICtrlSetData($InputVarVal[- $status - 1],'')
                        GUICtrlSetBkColor($inputVarVal[-$status - 1],0xffffff)
                    EndIf
                    
    ;variable set ok
                Case -9000;request not understood
                Case -10 To -1;error setting variable
                    $AutoMonItVarStatus[-$status - 1] = 0;not ok
                    
                    If GUICtrlRead($inputvar[-$status - 1]) <> '' Then
                        GUICtrlSetData($InputVarVal[- $status - 1],$failtext)
                        GUICtrlSetBkColor($inputVarVal[-$status - 1],$badcol)
                    EndIf
                Case -7000;
    ;update timer not changed
            EndSwitch
            
            _MemoryWrite(AddrCalc($AutoMonItMemAdd,108), $AutoMonItMemOpen, 0,"int");response has been read
        Else
            $lastrequest = 1;ok
        EndIf
        
        
;send next request if any
        If $AutoMonItNextREq <> 0 And $AutoMonItNextREqParam1 <> 0 Then
            $ReqCount += 1
            _MemoryWrite($AutoMonItMemAdd, $AutoMonItMemOpen, $AutoMonItNextREq,"int")
            If _MemoryWrite(AddrCalc($AutoMonItMemAdd,4), $AutoMonItMemOpen, $AutoMonItNextREqParam1,"int") = 0 Then
                MsgBox(0,"memwrite error",@error)
            EndIf
            
            _MemoryWrite(AddrCalc($AutoMonItMemAdd,8), $AutoMonItMemOpen, $AutoMonItNextREqParam2,"char[99]")
            $AutoMonItNextREq = 0
        EndIf
        
    EndIf
    
;read the monitored variable values - I need to sort this mess
    For $mn = 0 To $maxvar - 1;for each of the shared variables
        $AutoMonItValsRead[$mn] = _MemoryRead (AddrCalc($AutoMonItMemAdd,112 + $AutoMonItMaxReturn * $mn), $AutoMonItMemOpen, $AutoMonItValMemType)
        If $AutoMonItValsRead[$mn] <> GUICtrlRead($InputVarVal[$mn]) Then;we need to update
            If $mn = 0 And $ADE Then ControlSend("AutoMonItade","","Edit1",$AutoMonItValsread[$mn] & @CR)
            If $AutoMonItValsRead[$mn] <> '' Then;might have changed to '' because no such variable
                If $AutoMonItVarStatus[$mn] Then GUICtrlSetData($InputVarVal[$mn],$AutoMonItValsread[$mn])
                If $AutoMonItVarStatus[$mn] = 0 Then;it was not ok but since we got new value must be ok now
                    $AutoMonItVarStatus[$mn] = 1;set staus to ok
                    GUICtrlSetBkColor($inputVarVal[$mn],$goodcol)
                EndIf
;shouldn't need this next line - something wring in MonIt logic or setting nulls in struct
                If GUICtrlRead($inputVar[$mn]) = '' Then GUICtrlSetData($InputVarVal[$mn],'')
                
            EndIf
        EndIf
    Next
    If $ReqCount > 1000 And $ReqCount = $RepCount Then
        $ReqCount = 0
        $RepCount = 0
    EndIf

EndFunc;==>update

Func RestartExisting()
    Sleep(2000);time to allow for app to start up
    For $bn = 0 To $maxvar - 1;now retrigger any set variable
        If GUICtrlRead($inputVar[$bn]) <> '' Then
            $PresentReq = $ReqCount
            
            $AutoMonItNextREqParam2 = GUICtrlRead($inputVar[$bn])
            $AutoMonItNextREqParam1 = $bn + 1
            $AutoMonItNextREq = 91;monitor new variable
;wait for request to be dealt with
            While $RepCount < $PresentReq + 1
                If GUIGetMsg() = $BtnStop Then
                    Return -1
                EndIf
                
            WEnd;bit dodgy could get stuck
        EndIf
    Next
    
EndFunc

Func GetAppHandle($hWndGUI, $MsgID, $WParam, $LParam)
    If $MsgID = $WM_USER + 2000 Then
        $AutoMonItHandle = $Wparam
        ConsoleWrite("got handle " & Hex($WParam) & @CRLF)
        _SendMessage($AutoMonItHandle,$WM_USER + 2001)
    EndIf
EndFunc

Func GetDataAddr($hWndGUI, $MsgID, $WParam, $LParam)
    If $MsgID = $WM_USER + 2002 Then
;wparam = mem address of MOnItStruct
;LParam = MonIt PID
        $AutoMonItMemAdd = $WParam
        $AutoMonItMemOpen = _MemoryOpen (Number($LParam))
        AdlibEnable("update", 100)
        WinSetTitle($AutoMonItForm,"",$AMLinked)
    EndIf
EndFunc;==>getaddr


Func AddrCalc($StarAddr, $Offset)
    Return '0x' & Hex(number($StarAddr) + $Offset, 8)
EndFunc


Func MY_WM_GETMINMAXINFO($hWnd, $Msg, $wParam, $lParam)
    $AutoMonItnmaxinfo = DllStructCreate("int;int;int;int;int;int;int;int;int;int",$lParam)
    DllStructSetData($AutoMonItnmaxinfo,7,283); min X
    DllStructSetData($AutoMonItnmaxinfo,8,200); min Y
    DllStructSetData($AutoMonItnmaxinfo,9,1200); max X
    DllStructSetData($AutoMonItnmaxinfo,10,633 - $reduce); max Y
    Return 0
EndFunc

;===============================================================================
; Description:      _GUIGetFocus - Retrieves the classname of a window.
; Syntax:           _GUIGetFocus ( $hGUI [, $vUser32Dll = 'user32.dll' ] )
; Parameter(s):     $hGUI - Handle of GUI to check for control focus.
;                   $vUser32Dll - Optional handle to user32.dll.
; Return Value(s):  Success: Returns the id of focussed control.
;                   Failure: Returns False, sets @error to 1, sets @extended to DllCall error.
; Author(s):        Rob Saunders (admin@therks.com)
;===============================================================================
Func _GUIGetFocus($hGUI, $vUser32Dll = 'user32.dll')
    Local $sFocus, $hCtrl, $aCtrlID, $sClassname, $hParent
    If Not IsHWnd($hGUI) Then
        Return SetError(1, 0, 0)
    EndIf
    
    $sFocus = ControlGetFocus($hGUI, '')
    $hCtrl = ControlGetHandle($hGUI, '', $sFocus)
    $sClassname = ___GCOP($hCtrl, $vUser32Dll, 1)
    If @error Then Return SetError(1, @error, 0)
    If $sClassname = 'COMBOBOX' Then
        $aCtrlID = DllCall($vUser32Dll, 'int', 'GetDlgCtrlID', 'hwnd', $hCtrl)
    ElseIf $sClassname = 'EDIT' Then
        $hParent = ___GCOP($hCtrl, $vUser32Dll)
        If @error Then Return SetError(2, @error, 0)
        $sClassname = ___GCOP($hParent, $vUser32Dll, 1)
        If @error Then Return SetError(3, @error, 0)
        If $sClassname = 'COMBOBOX' Then
            $aCtrlID = DllCall($vUser32Dll, 'int', 'GetDlgCtrlID', 'hwnd', $hParent)
        Else
            $aCtrlID = DllCall($vUser32Dll, 'int', 'GetDlgCtrlID', 'hwnd', $hCtrl)
        EndIf
    Else
        $aCtrlID = DllCall($vUser32Dll, 'int', 'GetDlgCtrlID', 'hwnd', $hCtrl)
    EndIf
    
    If @error Then Return SetError(4, @error, 0)
    Return $aCtrlID[0]
EndFunc

Func ___GCOP($hWnd, ByRef $vUser32Dll, $iSwitch = 0); GetClassOrParent
    Local $aReturn
    If $iSwitch = 0 Then
        $aReturn = DllCall($vUser32Dll, 'hwnd', 'GetParent', 'hwnd', $hWnd)
        If @error Then
            Return SetError(@error, 0, 0)
        Else
            Return $aReturn[0]
        EndIf
    Else
        $aReturn = DllCall($vUser32Dll, 'int', 'GetClassName', 'hwnd', $hWnd, 'str', '', 'int', 255)
        If @error Then
            Return SetError(@error, 0, 0)
        Else
            Return $aReturn[2]
        EndIf
    EndIf
EndFunc

Last Updates made

version 1.04 - now reads registry to find path for AutoIt3.exe and include files. Thanks to Firestorm.

- Option added to run Production version or Beta version of script.

- Disabled Run button when a script is running.

version 1.05 - Can use the Enter key to Apply the new variable name

Monit v1.21 deletes temp au3 file on exit

version 1.06 Cosmetics. Made window shorter and reduced monitored variable from 10 to 9 if screen res is 600 high.

Added a hint to the inputs for variable names. Hint is removed after first entry. Set colours for background.

Got rid of labels at bottom of window.

version 1.07 minor correction for resizing. Note need to comment out $WM_GETMINMAXINFO if using AutoIt V3.2.9.2 or later.

Cleared variable values when starting a script again.

Edited by martin

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites
Valuater

Neat concept... this could really turn into something martin

thanks for sharing.... please continue your effort

8)


NEWHeader1.png

Share this post


Link to post
Share on other sites
martin

Neat concept... this could really turn into something martin

thanks for sharing.... please continue your effort

8)

Thanks for the encouragement Valuater, I hope people can give me some ideas.

One thing that has stumped me is that I don't know how to get pointers to variables, apart from DllStructGetPtr, or even if this is practical in AutoIt.


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites
Pascal257

This is awesome!

I should have had this some weeks ago...

Never write vars to console anymore ^^

And it also works with arrays thats very useful.

Thanks for this

Greetings,

Pascal

Edited by Pascal257

Share this post


Link to post
Share on other sites
zatorg

I like the concept.. hell, every program needing to be debugged could "talk" to a debug/whatever handler like this :)

One thing that has stumped me is that I don't know how to get pointers to variables, apart from DllStructGetPtr, or even if this is practical in AutoIt.

I suppose one is not able to get a pointer to an inner AutoIt variable :/ Though this would be useful.. Mm

Share this post


Link to post
Share on other sites
martin

@Pascal257, Toady, zatorg

Thanks for the comments. (Just when I was thinking perhaps it wasn't such a great idea!)

For better debugging don't forget Stumpi's method and Klaatu's Debugit. Had I remembered to look at them before I wrote this I probably wouldn't have started!

However this method has some advantages and if debugging is a major interest then I will start stealing ideas.

A couple of minor changes made so I updated first post.

Edited by martin

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites
ade

Very useful program. Nice job!

I am new to AutoIT and have just started mucking about writing a few scripts and this has saved me alot of time, by not having to put in lots of messages boxes to work out where I went wrong.

I do have 1 question. Simple for most I am sure but for me, never having used GUIs, it isn´t. I did try to scan through the script and change some likely looking values but to no joy.

My question is: How do I change the size of the box for the variable return lines?

The problem I have is that one of my variables holds a URL of a website which is very long. This variable changes but I cannot see the changes as only the first 30-40 characters are displayed.

Can I just change a setting to make the box wider? Or is the problem that only the first 30-40 characters are read so therefore only they can be displayed?

When I resized the main monitor by dragging with the mouse only the background part widened not the lines that contain the variables.

Hope this makes sense. If not say so and I will try and explain it better.

Cheers!

Share this post


Link to post
Share on other sites
martin

Very useful program. Nice job!

I am new to AutoIT and have just started mucking about writing a few scripts and this has saved me alot of time, by not having to put in lots of messages boxes to work out where I went wrong.

I do have 1 question. Simple for most I am sure but for me, never having used GUIs, it isn´t. I did try to scan through the script and change some likely looking values but to no joy.

My question is: How do I change the size of the box for the variable return lines?

The problem I have is that one of my variables holds a URL of a website which is very long. This variable changes but I cannot see the changes as only the first 30-40 characters are displayed.

Can I just change a setting to make the box wider? Or is the problem that only the first 30-40 characters are read so therefore only they can be displayed?

When I resized the main monitor by dragging with the mouse only the background part widened not the lines that contain the variables.

Hope this makes sense. If not say so and I will try and explain it better.

Cheers!

Makes perfect sense.

The variable values are shown in read only edit boxes which can contain text longer than you can see all at once, but all the text should be there. To see the end of the text just click in the box and press End or move left and right with the arrow keys.

It's a bit silly that I let you make the window wider than is any use. I made the window resizable because I thought at full size it might get in the way sometimes and I was just a bit lazy about the way I did it.

I'l have a look at making the width of the text boxes grow with the window width.

Meanwhile, since you're new to AutoIt, maybe you would like to make the following mod to my script to give a rather unusual solution to your problem.

In the update function find the code shown here and add the extra line indicated.

For $mn = 0 To 9;for each of the shared variables
        $MonItValsRead[$mn] = _MemoryRead (AddrCalc($MonItMemAdd,112 + 40 * $mn), $MonItMemOpen, "char[40]")
        If $MonItValsRead[$mn] <> GUICtrlRead($InputVarVal[$mn]) Then
            If $mn = 0 And $ADE Then ControlSend("AutoMonItade","","Edit1",$MonItValsread[$mn] & @CR);<------------add this line
            GUICtrlSetData($InputVarVal[$mn],$MonItValsread[$mn])
            If $MonItValsRead[$mn] <> '' Then;might have changed to '' because no such variable
                If $MonItVarStatus[$mn] = 0 Then;it was not ok but since we got new value must be ok now
                    $MonItVarStatus[$mn] = 1;set staus to ok
                    GUICtrlSetBkColor($inputVar[$mn],0xffffff);set bkgrnd white
                EndIf
            EndIf
            
            
        EndIf
        
    Next

Then in the main while loop add one more line

While $MonItrunning
        $nMsg = GUIGetMsg()
        .
   .
   ..
   ..

        
        If Not WinExists("MonIt Startup Window") Then $MonItrunning = False
        $ADE = WinExists("AutoMonItade");<-------------------------add this line
    WEnd

Now, when you run the program and you want to see long lines, put the variable which is too long in the first (topmost) variable edit box.

Open notebook and save as AutoMonitADE.txt even though it is empty. You can then make the notebook as wide as you like, plus, when you have finished you have a record of all the urls.

EDIT: Correction to the suggested mod - $mn was $mm by mistake

Edited by martin

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites
martin

First post updated with improved resizing. Thanks to ade.


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites
ade

Thanks for the workaround!

Saving the URLs to a file will actually be better for the program i am making as it usually copies the links to an array and so every time the program runs it has to go to the website and get the link collection and put them back in an array. With this I could save a little bit of time as the links don´t change.

I will give the workaround a try now

Share this post


Link to post
Share on other sites
martin

This looks like VERY GOOD job martin!! :)

I haven't tested it yet but I will do :)

Thanks Zedna, I hope it's useful.

Updated again because I am forgetful.


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites
Skrip

>Running:(3.2.4.9):C:\AutoIt3\autoit3.exe "C:\AutoIt3\test.au3"

C:\AutoIt3\test.au3 (102) : ==> Unable to execute the external program.:

Run( '"' & @ProgramFilesDir &'\AutoIt3\Beta\AutoIt3.exe" MonItTemp.au3')

The system cannot find the path specified.

Might want to fix that..like my autoit is at C:\Autoit3\

So I'd have it detect where it is, by searching the registery.


[left][sub]We're trapped in the belly of this horrible machine.[/sub][sup]And the machine is bleeding to death...[/sup][sup][/sup][/left]

Share this post


Link to post
Share on other sites
martin

Might want to fix that..like my autoit is at C:\Autoit3\

So I'd have it detect where it is, by searching the registery.

Thanks Firestorm, now done.

This made me realise that I hadn't allowed for people wanting to run the Production version of AutoIt rather than the Beta so this is now allowed for.


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

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  

×