Debug mit Change2CUI

  • Hallo zusammen

    Um meine Programme zu debuggen und ggfs Fehler zu finden, nutze ich gerne die Möglichkeit gewisse (Rückgabe)Werte oder Fehler mittels

    [autoit]

    ConsoleWrite("")

    [/autoit]

    auszugeben.

    Da ich aber die Programme anschliessend als EXE kompiliere und ConsoleWrite nichts in die DOS-Box schreibt, setzte ich jeweils die folgenden Zeilen an den Anfang des Scriptes:

    [autoit]

    #AutoIt3Wrapper_Change2CUI=y
    WinSetState(@ScriptFullPath, "", @SW_HIDE)

    [/autoit]

    Wenn das EXE direkt ausgeführt wird, erscheint ganz kurz die schwarze Dos Box und verschwindet gleich wieder.
    Danach läuft das Programm normal durch. Wenn ich die EXE hingegen aus einer DOS Box starte, dann bekomme ich alle ConsoleWrite Werte zurück (Debuggen)

    Alles funktioniert einwandfrei, jedoch hätte ich am liebsten das kurze aufploppen dieser schwarzen DOS Box verhindert.
    Am einfachsten natürlich in dem man das Change2CUI weglässt. Aber dann kann man nicht mehr einfach kurz etwas debuggen...

    Habt Ihr eine Idee?
    Gruss Veronesi

    Einmal editiert, zuletzt von veronesi (8. Februar 2012 um 08:06)

    • Offizieller Beitrag

    Bastel Dir doch Deine eigene Console:

    Spoiler anzeigen
    [autoit]


    #include <EditConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>

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

    Opt('GUIOnEventMode', 1)

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

    Global $hConsoleGui, $idConsole, $fDebug = False

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

    If StringInStr(@AutoItExe, 'Debug') Then $fDebug = True ; wenn im Dateinamen der Exe ein Debug enthalten ist, den Debugmodus aktivieren

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

    If $fDebug Then _ConsoleOpen()

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

    ; Anfang Deines Programms
    $a = Random(1, 100, 1)
    _ConsoleWrite('Zeile 15, Wert von $a = ' & $a)
    $a = Random(1, 100, 1)
    _ConsoleWrite('Zeile 17, Wert von $a = ' & $a)
    $a = Random(1, 100, 1)
    _ConsoleWrite('Zeile 19, Wert von $a = ' & $a)
    ; Ende Deines Programms

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

    If $fDebug Then WinWaitClose($hConsoleGui)

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

    Func _ConsoleOpen()
    $hConsoleGui = GUICreate('Debug-Console', 640, 320)
    GUISetOnEvent($GUI_EVENT_CLOSE, '_ConsoleClose')
    $idConsole = GUICtrlCreateEdit('', 0, 0, 640, 320, BitOR($WS_VSCROLL, $ES_AUTOVSCROLL, $ES_READONLY))
    GUISetState(@SW_SHOW, $hConsoleGui)
    EndFunc

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

    Func _ConsoleClose()
    GUIDelete($hConsoleGui)
    EndFunc

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

    Func _ConsoleWrite($sMsg)
    If Not $fDebug Then Return
    $sMsg = StringFormat('%s:%s:%s.%s %s', @HOUR, @MIN, @SEC, @MSEC, $sMsg) & @CRLF
    GUICtrlSetData($idConsole, $sMsg, 1)
    EndFunc

    [/autoit]

    So kannst Du später nach belieben debuggen, indem Du in den Dateinamen der Exe ein "Debug" einfügst.

  • Hallo Oscar

    Vielen Dank.
    Ich habe mir nun in der Tat eine eigene Konsole gebastelt. Allerdings etwas anders:

    _ConsoleWrite UDF
    [autoit]

    #include-once
    #include <WinAPI.au3>
    Global $h_ConsoleWrite = -1

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

    ; _ConsoleWrite ===================================================================================
    ; Name ..........: _ConsoleWrite()
    ; Description ...: Write string to the console screen buffer.
    ; If you start your program from a DOS console, then you can see your debug value written by this function
    ; In normal operation (you don't start your program normally from a DOS console) you don't notice of any debug strings!
    ;
    ; Syntax ........: _ConsoleWrite($sText)
    ; Parameters ....: $sText String to write into the console screen buffer
    ;
    ; Return values .: Success: Return 1
    ; Failure: Return 0 and sets @error
    ; @error = 1 / @extended = 0 => DllCall GetStdHandle failure
    ; @error = 2 / @extended = 1 => _WinAPI_AttachConsole failure
    ; @error = 2 / @extended = 2 => _WinAPI_WriteConsole failure
    ; Author ........: Veronesi
    ; Links .........: http://msdn.microsoft.com/en-us/library/…1(v=vs.85).aspx
    ; =================================================================================================
    Func _ConsoleWrite($sText)
    If $h_ConsoleWrite = 0 Then Return 1 ;Program not in DOS console started! It's not neccessary to write something, because we don't see it!
    Local $Ret = True, $Ret2 = True
    If $h_ConsoleWrite = -1 Then ;Handle not yet initialized => Initialize the console handle, but only the first time
    Local Const $STD_OUTPUT_HANDLE = -11
    Local $aResult = DllCall("kernel32.dll", "handle", "GetStdHandle", "dword", $STD_OUTPUT_HANDLE)
    If @error Then Return SetError(1, 0, 0)
    $h_ConsoleWrite = $aResult[0]
    If $h_ConsoleWrite = 0 Then Return 1 ;Program not in DOS console started! ....
    $Ret = _WinAPI_AttachConsole(-1) ;Attaches the alling process to the current process
    EndIf
    $Ret2 = _WinAPI_WriteConsole($h_ConsoleWrite, $sText)
    If $Ret And $Ret2 Then Return 1 ;All went fine
    If $Ret2 Then Return SetError(2, 1, 0) ;_WinAPI_AttachConsole was NOT successful
    Return SetError(2, 2, 0) ;WinAPI_WriteConsole was NOT successful
    EndFunc ;==>_ConsoleWrite

    [/autoit]


    Damit kann ich mit minimalen Aufwand meine Scripts umbauen. Einfach alle ConsoleWrite Befehle in _ConsoleWrite ändern.
    Wird dann das EXE Programm "normal" von einem Windows Explorer gestartet, dann funktioniert es für den Benutzer einwandfrei und ohne Einschränkung. Wird es allerdings über eine DOS Konsole gestartet, dann läuft es auch normal, allerdings sieht man in der DOS Konsole zeitgleich die Debug-Ausgaben!
    Der Vorteil ist auch, dass man immer alle seine Debug Befehle im Programm drin lassen kann. Und man hat sie trotzdem zur Verfügung, wenn man möchte :)

    Nachfolgend ein kleines Beispiel.
    Einfach dies als EXE Kompillieren, und von einem Windows Explorer ausführen => Normales GUI, nichts aussergewöhnlich.
    Danach von einer DOS Konsole die EXE starten. Man sieht, dass das GUI durch läuft, aber zeitgleich in der Konsole die Ausgabe erfolgt!

    Beispiel
    [autoit]

    #include "_ConsoleWrite.au3"

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

    GUICreate("Test-GUI", 400, 100)
    Local $Label = GUICtrlCreateLabel("", 0, 25, 400, 50, 0x01)
    GUICtrlSetFont(-1, 26, 400, 0, "Arial")
    GUISetState()

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

    _ConsoleWrite(@CRLF & "********************************************************************" & @CRLF)
    _ConsoleWrite("UDF _ConsoleWrite from Veronesi" & @CRLF)
    _ConsoleWrite("********************************************************************" & @CRLF)
    For $i = 0 To 100
    GUICtrlSetData($Label, "Progress: " & $i & "%")
    _ConsoleWrite(@CR & "Progress: " & $i & "%")
    Sleep(20)
    Next
    GUICtrlSetData($Label, "Successful finished")
    $a = _ConsoleWrite(@CRLF & "Successful finished" & @CRLF)
    Sleep(2000)
    Exit

    [/autoit]

    Gruss Veronesi