ValueTracker - Variablenwerte beobachten

  • Hi alle zusammen!

    Heute ist mir die Idee gekommen, mal ein kleines Programm zu schreiben, das den Variablenwert in einem bestimmten Skript "beobachtet".

    Das Programm arbeitet bisher so:
    - zuerst wird das Skript, welches später überprüft werden soll, geladen
    - das Skript wird dupliziert und es wird Code "injectet", welcher den Variablenwert an der Stelle zum ValueTracker-Programm zurückschickt

    Das Ganze arbeitet mit der MessageHandler-Udf.

    Screen:
    [Blockierte Grafik: http://www8.pic-upload.de/10.03.11/f3ohzz7eow75.png]

    Mit diesem "getrackten" Skript:

    [autoit]


    $Variable = 0
    $Variable += 5

    [/autoit]

    Hinweis:
    Wem die MessageHandlerUDF fehlt, kommentiert einfach beim Skriptstart die #include "MessageHandler.au3 einmal aus und startet das Skript dann ohne.

  • Hallo Jautois,
    ich stelle mir deine Idee recht cool vor.
    Es könnte so manche Debugging Prozesse vereinfachen, wenn man nicht immer eine Variable an einem bestimmten Ort
    in die Console reinschreiben muss. Ich wünsche dir aufjedenfall viel Erfolg mit deinem Skript ;)
    MfG. PrideRage

    Meine Projekte:
    ClipBoard Manager (beendet)
    Gutes ClipBoard Verwaltungs Programm mit nützlichen Funktionen.

    HTML Creator (beendet)
    Nützliches Tool um schnell ein eigenes HTML Dokument zu erstellen.

  • Super, genau so etwas habe ich gesucht um ein Skript zu debuggen ohne überall ConsoleWrites hinzukopieren was vor allem bei der FF.au3 schlecht geht weil die sehr viel in die Console schreibt.

  • Das Skript noch in einem sehr frühren Anfangsstadium:

    Spoiler anzeigen
    [autoit]


    ;--------------------------
    ; Name: Value-Tracker
    ; By: Johannes
    ;
    ; Date: March. 3, 2011
    ;--------------------------

    [/autoit] [autoit][/autoit] [autoit]

    #include <ButtonConstants.au3>
    #include <ComboConstants.au3>
    #include <EditConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <ListViewConstants.au3>
    #include <StaticConstants.au3>
    #include <WindowsConstants.au3>
    #include <Array.au3>
    #include <MessageHandler.au3>
    #include <File.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Global $debug = False

    [/autoit] [autoit][/autoit] [autoit]

    Global $MessageHandlerPath = @ScriptDir & "\MessageHandler.au3"
    $Local_ReceiverID_Name = "S1ID"
    $Remote_ReceiverID_Name = "S2ID"
    $hwnd = _SetAsReceiver($Local_ReceiverID_Name)
    $myFunc = _SetReceiverFunction("_RemoteRec")

    [/autoit] [autoit][/autoit] [autoit]

    Global $ar_dvar[1][2]
    Global $dvar_index = 1, $scr_n, $scr_p

    [/autoit] [autoit][/autoit] [autoit]

    $hGui = GUICreate("ValueTracker - Jautois", 450, 610, 10, 124)
    $in_path = GUICtrlCreateInput("", 64, 8, 233, 21)
    GUICtrlCreateLabel("File", 26, 11, 34, 17)
    GUICtrlSetFont(-1, 8, 800, 0, "MS Sans Serif")
    $b_load = GUICtrlCreateButton("Load", 304, 6, 97, 25)
    $combo_vars = GUICtrlCreateCombo("", 64, 40, 233, 25, BitOR($CBS_DROPDOWNLIST, $CBS_AUTOHSCROLL, $CBS_SORT))
    GUICtrlSetColor(-1, 0x800000)
    $Label2 = GUICtrlCreateLabel("Variable", 10, 43, 50, 17)
    GUICtrlSetFont(-1, 8, 800, 0, "MS Sans Serif")
    $b_track = GUICtrlCreateButton("Track", 8, 88, 353, 25)
    $ico = GUICtrlCreateIcon("", -1, 340, 37, 25, 25)
    $b_stop = GUICtrlCreateButton("Stop", 368, 88, 73, 25)
    $lab_loaded = GUICtrlCreateLabel("0 - Records", 8, 120, 436, 17, $SS_CENTER)
    GUICtrlSetFont(-1, 8, 800, 0, "MS Sans Serif")
    $listview = GUICtrlCreateListView("Value|Line-Nr|Error", 8, 144, 433, 457, -1, BitOR($WS_EX_CLIENTEDGE, $LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT))
    GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 0, 200)
    GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 1, 128)
    GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 2, 100)
    GUISetState(@SW_SHOW, $hGui)

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
    Case $GUI_EVENT_CLOSE
    Exit
    Case $b_load
    $path = FileOpenDialog("Load file ...", @DesktopDir, "(*.au3)")
    If Not @error Then
    GUICtrlSetData($in_path, $path)
    _LoadFile($path)
    EndIf
    Case $b_track
    _Track(GUICtrlRead($combo_vars))
    Case $b_stop
    _SendData("Exit",$Remote_ReceiverID_Name)
    EndSwitch
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func _RemoteRec($recData)
    $ar_dvar[$dvar_index - 1][1] = $recData
    $ar_dvar[$dvar_index - 1][0] = GUICtrlCreateListViewItem(StringReplace($recData, "<#>", "|"), $listview)
    GUICtrlSetData($lab_loaded, $dvar_index & " - Records")
    $dvar_index += 1
    ReDim $ar_dvar[$dvar_index + 1][2]
    EndFunc ;==>_RemoteRec

    [/autoit] [autoit][/autoit] [autoit]

    Func _LoadFile($path)
    If $path = "" Then
    MsgBox(16, "Attention", "Path to a file needs to be returned!")
    Else
    $file = FileRead($path)
    $vars = _Del_Duplicates(StringRegExp($file, '\$[A-Za-z0-9_]+', 3))
    $data = ""
    For $i = 0 To UBound($vars) - 1
    $data &= "|" & $vars[$i]
    Next
    GUICtrlSetData($combo_vars, $data)
    $f_copy = FileCopy($path, @TempDir, 1)
    $scr = StringSplit($path, "\")
    $scr_n = $scr[UBound($scr) - 1]
    $scr_p = @TempDir & "\" & $scr_n
    EndIf
    EndFunc ;==>_LoadFile

    [/autoit] [autoit][/autoit] [autoit]

    Func _Track($selec_var)
    Local $f_ar

    [/autoit] [autoit][/autoit] [autoit]

    If $debug Then ConsoleWrite("+> Tracking variable: " & $selec_var & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    If Not _FileReadToArray($scr_p, $f_ar) Then
    MsgBox(4096, "Error", "Error while reading the file!")
    Exit
    EndIf
    _ArrayDelete($f_ar, 0)
    If Not @error Then
    GUICtrlSetData($lab_loaded, "Error during code injection!")
    GUICtrlSetColor($lab_loaded, 0x008000)
    $i = 0
    Do
    $is = StringInStr($f_ar[$i],'#include')
    If $is <> 0 Then $i += 1
    Until $is = 0
    $ln_c = 5
    _ArrayInsert($f_ar, $i+0, '#include "MessageHandler.au3"')
    _ArrayInsert($f_ar, $i+1, 'Global $Local_ReceiverID_Name = "S2ID"')
    _ArrayInsert($f_ar, $i+2, 'Global $Remote_ReceiverID_Name = "S1ID"')
    _ArrayInsert($f_ar, $i+3, 'Global $hwnd = _SetAsReceiver($Local_ReceiverID_Name)')
    _ArrayInsert($f_ar, $i+4, 'Global $myFunc = _SetReceiverFunction("_RemoteExit")')
    If $debug Then _ArrayDisplay($f_ar)
    If $debug Then ConsoleWrite(">> " & UBound($f_ar) & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    $j = $ln_c
    Do
    If $debug Then ConsoleWrite(@CRLF & "-> " & $j & " - " & $f_ar[$j] & @CRLF)
    If StringInStr($f_ar[$j], $selec_var, 1) Then
    If $debug Then ConsoleWrite(@CRLF & "@@Included!" & @CRLF)
    $j += 1
    _ArrayInsert($f_ar, $j, '_SendData(_CreatDataPackage(' & $selec_var & ',@ScriptLineNumber-1,@error),$Remote_ReceiverID_Name)')
    EndIf
    $j += 1
    Until UBound($f_ar) <= $j

    [/autoit] [autoit][/autoit] [autoit]

    _ArrayAdd($f_ar, @CRLF & 'Func _CreatDataPackage($var,$lnr,$error)')
    _ArrayAdd($f_ar, 'Return $var & "<#>" & $lnr-' & $ln_c & ' & "<#>" & $error')
    _ArrayAdd($f_ar, 'EndFunc' & @CRLF)
    _ArrayAdd($f_ar, 'Func _RemoteExit()')
    _ArrayAdd($f_ar, 'Exit')
    _ArrayAdd($f_ar, 'EndFunc')
    _FileWriteFromArray($scr_p, $f_ar)
    Run('"' & @AutoItExe & '" /AutoIt3ExecuteScript "' & $scr_p & '"')
    Else
    GUICtrlSetData($lab_loaded, "Error during code injection!")
    GUICtrlSetColor($lab_loaded, 0xFF0000)
    EndIf
    EndFunc ;==>_Track

    [/autoit] [autoit][/autoit] [autoit]

    Func _Del_Duplicates($ar_r)
    Local $ar_d = $ar_r
    Local $iCount = 0
    For $i = 0 To UBound($ar_r) - 1
    $iCount = 0
    For $j = 0 To UBound($ar_r) - 1
    If $j > UBound($ar_d) - 1 Then ExitLoop
    If $ar_d[$j] = $ar_r[$i] Then
    If $iCount > 0 Then
    _ArrayDelete($ar_d, $j)
    _ArrayDelete($ar_d, $i)
    EndIf
    $iCount += 1
    EndIf
    Next
    Next

    [/autoit] [autoit][/autoit] [autoit]

    Return $ar_d
    EndFunc ;==>_Del_Duplicates

    [/autoit]

    Ein simples Beispiel zum Testen:

    [autoit]


    ; Sample Value Tracker

    [/autoit][autoit][/autoit][autoit]

    $variable = 0
    Global $variable = 23, $int = 20
    $variable += 5

    [/autoit]

    Die Ausgabe ist dann folgende im Programm:
    [Blockierte Grafik: http://www8.pic-upload.de/05.03.11/ao48wncnknfv.png]

  • Bei mir funktioniert die MessageHandler.au3 nicht.

    [autoit]

    E:\AutoIt3\Include\MessageHandler.au3(19,34) : ERROR: Opt() called with illegal argument 1: "OnExitFunc"
    Opt("OnExitFunc", "CallBack_Exit")

    [/autoit]

    müsste doch eher so ausschauen:

    [autoit]

    OnAutoItExitRegister( "CallBack_Exit")

    [/autoit]

    ?

  • @Fabian: Ja habe vergessen, die abgeänderte MessageHandler.au3 hochzuladen, jedoch wird zu Beginn des Programmes nun gefragt, sofern die UDF nicht vorhanden ist, ob man sie eben downloaden möchte. Den Rest macht das Programm dann selbst.

    Mal ein kleines Update:

    - Es wird jetzt ebenso aufgezeichnet, ob die Variable innerhalb einer Funktion verändert wird, sprich der Name der Funktion wird im Listview angezeigt
    - das "@error"-handling ist eingebaut
    - Zeilennummern sind nun auch richtig

    Ich habe in einem Beispielskript einmal zum Testen durch Null geteilt und @error gesetzt. Wie man sehen kann, wird das direkt als Fehler farblich hervorgehoben.

    Screen:
    [Blockierte Grafik: http://www8.pic-upload.de/06.03.11/sawowjh9mc5m.png]

    Einmal editiert, zuletzt von Jautois (6. März 2011 um 07:07)

  • Die Idee gefällt mirwirklich sehr gut :thumbup:
    Jetzt bräuchte ich nur noch den neuen Code, um das ganze richtig in der Prxis zu testen.

    Lg, Fabian

  • Hi Jautois,
    erstmal vom Grundgedanken hier viel besser gemacht als der AutoIt Debugger. Aber: Ich würde mir etwas anderes wünschen: Das man wie bei _ArrayDisplay eine Listview hat mit allen Globalen Variablen und daneben die Werte. Da das nicht schwer ist, kann man das in 5 min fertig machen. ;)

  • Kannst du bitte den neuen Quellcode (nach dem Update von dir) hochladen, ich will den ValueTracker umbedingt ausprobieren :whistling:

    Danke im Voraus

  • Okay, habe mein bisheriges Skript einmal im #1Post angehängt. Ich habe in einer schon wieder etwas neueren Version einen Graphen eingebaut, der später dann übergebene Werte anzeigen kann, jedoch weiß ich nocht nicht ob ich das wirklich im Skript lasse. Das Flackern der Graphic-Elemente geht mir nämlich auf den Senkel ;)

    2 Mal editiert, zuletzt von Jautois (10. März 2011 um 03:50)