Hallo Community,
ich möchte ein kleines Skript mit euch teilen welches mir schon oft beim Debuggen von unübersichtlichen Programmcode geholfen hat. Auch lässt es sich wunderbar auf einen >4000 Zeiler anwenden, um dort einfacher abhängige Variablen und Funktionen auslesen zu können.
Wer kennt das nicht, da schaust dir ein altes Skript an oder Fremdsource und willst wissen wie eine einzelne Funktion aufgebaut ist. Aber durch den ganzen Code Wirr-Warr mußt du dir erstmal einen Überblick über den gesammten Source verschaffen, und das kostet eben Zeit...
Da kommt die ExcludeFunc() Funktion zur Hilfe, du musst diese Funktion einfach in dem Skript Includen wo sich auch die zu prüfende Funktion befindet - In diesem Beispiel nennen wir diese einfach _BigFunc().
Jetzt fügst du einfach in deinem Skript einen Befehl zu worin sich die Aufgerufene Funktion befindet: ExcludeFunc("_BigFunc").
Sobald du dein Skript startest, wird eine neue Datei in @ScriptDir mit dem Funktionsnamen erstellt @Scriptdir & "\_BigFunc.au3".
Dieses erstellte Skript enthällt die gewünschte Funktion mit allen Includes (C&P aus dem Main-Skript) und allen verwendten globalen Variablen (mit Werten) sowie aufgerufene Funktionen.
Oft kann dieser Source nicht ausgeführt werden - soll er auch gar nicht! Es ist zum Debuggen einzelner Funktionen gedacht und/oder um sich durch die Abhängikeitsprüfung eine bessere Übersicht verschaffen zu können. Wenn aufgerufene Funktionen oder Variablen aus dem Main-Skript fehlen dann weil sich diese nicht in dessen Datei befinden - Includierte Quellcodes werden nicht ausgewertet sondern einfach eingebunden.
In Zeile 241 und 242 befinden sich einfache Anwendungsbeispiele, müssen nur De-Kommentiert werden.
Spoiler anzeigen
#Region - Includes -----------------------------------------------------------------------------------------------------------------
#AutoIt3Wrapper_UseX64=n
#AutoIt3Wrapper_UseUPX=n
#RequireAdmin
#include-once
#include <Array.au3>
#include <String.au3>
#EndRegion -------------------------------------------------------------------------------------------------------------------------
[/autoit] [autoit][/autoit] [autoit]#cs - ReadMe -----------------------------------------------------------------------------------------------------------------------
[/autoit] [autoit][/autoit] [autoit]AutoIt Version: 3.3.12.0
Script: ExcludeFunc.au3
Progammversion: 0.12
Author: Techmix
Programm Funktion:
Ich verwende dieses Script um Funktionen aus z.B. unübersichtlichen Skripten incl.
aller Funktions- und Variablen- Abhängikeiten in ein einzelnes Script zu übertragen.
Damit lässt sich prima Debuggen und auch der Fokus auf eine Funktion lenken.
Update auf V0.12:
Tiefenanalyse auch auf verwendete Unterfunktionen ausgedehnt
Variablenerkennung verbessert
#ce --------------------------------------------------------------------------------------------------------------------------------
[/autoit] [autoit][/autoit] [autoit]Func _ExcludeFunc($sFuncName)
Local _
$sFile = @ScriptFullPath, _
$sFunc = "Func " & $sFuncName&"(" & _StringBetween(FileRead(@ScriptFullPath), "Func " & $sFuncName&"(", "EndFunc"&@CRLF)[0] & @CRLF&"EndFunc", _
$sSource, _
$aSourceCode, _
$sSourceCode, _
$aFunctions, $aTemp, $aArray, $sTemp, $sChr, $sGlobal, $iSkipFunc, _
$aIncludes[100], $aIncludedFuncs[100], $aInternFuncs[100], _
$aVariables[1000], $aGlobalVariables[1000], $iCount=0
; Includes auslesen
; Einfacherweise werden einfach alle #includes ausgelesen
$sSourceCode = FileRead($sFile)
$aSourceCode = StringSplit($sSourceCode, @CRLF, 3)
$aFunctions = StringSplit($sFunc, @CRLF, 3)
for $i = 0 to UBound($aSourceCode) -1
if StringLeft(StringLower($aSourceCode[$i]), = "#include" then
$aIncludes[$iCount] = $aSourceCode[$i]
$iCount += 1
EndIf
Next
ReDim $aIncludes[$iCount]
;~ _ArrayDisplay($aIncludes)
; Alle aufgerufenen Funktionen innerhalb der Hauptfunktion auslesen
; Wird benötigt um die genaue Abhängigkeit der Hauptfunktion zu ermitteln
$iCount=0
for $i = 1 to UBound($aFunctions) -1
if StringInStr($aFunctions[$i], "(") then
if StringInStr(StringLeft($aFunctions[$i], StringInStr($aFunctions[$i], "(")), ";") then ContinueLoop
$aTemp = StringRegExp($aFunctions[$i], '(?i)(?<=)[0-9a-zA-Z_]+[ ]*(?=\()', 3) ; Stolen from OrganizeIncludes
if IsArray($aTemp) = 0 then ContinueLoop
$aIncludedFuncs[$iCount] = $aTemp[0]
if $aIncludedFuncs[$iCount] = "" Then ContinueLoop
$aIncludedFuncs[$iCount] = StringStripWS($aIncludedFuncs[$iCount],
$iCount += 1
EndIf
Next
;~ ReDim $aIncludedFuncs[$iCount]
;~ _ArrayDisplay($aIncludedFuncs)
; Alle aufgerufenen Funktionen innerhalb aller Unterfunktionen auslesen
$i = 0
Do
$i += 1
if $i >= UBound($aIncludedFuncs) Then ExitLoop
if $aIncludedFuncs[$i] = "" then ContinueLoop
if StringInStr($sSourceCode, "Func " & $aIncludedFuncs[$i]&"(") = 0 then ContinueLoop
$sSource = StringSplit(_StringBetween($sSourceCode, "Func " & $aIncludedFuncs[$i]&"(", "EndFunc"&@CRLF)[0], @CRLF, 3) ; Interne Funktion mit @CRLF Splitten
for $j = 0 to UBound($sSource) -1
if StringInStr($sSource[$j], "(") then
if StringInStr(StringLeft($sSource[$j], StringInStr($sSource[$j], "(")), ";") then ContinueLoop
$aTemp = StringRegExp($sSource[$j], '(?i)(?<=)[0-9a-zA-Z_]+[ ]*(?=\()', 3) ; Stolen from OrganizeIncludes
if IsArray($aTemp) = 0 then ContinueLoop
$aIncludedFuncs[$iCount] = $aTemp[0]
if $aIncludedFuncs[$iCount] = "" Then ContinueLoop
$aIncludedFuncs[$iCount] = StringStripWS($aIncludedFuncs[$iCount],
$iCount += 1
EndIf
Next
Until $aIncludedFuncs[$i] = ""
ReDim $aIncludedFuncs[$iCount]
$aIncludedFuncs = _ArrayUnique($aIncludedFuncs)
_ArrayDelete($aIncludedFuncs, 0)
;~ _ArrayDisplay($aIncludedFuncs)
; Prüfen ob sich die gefundenen Funktionen in dem Main-Source befinden
$iCount=0
for $i = 0 to UBound($aIncludedFuncs) -1
if StringInStr($sSourceCode, "Func " & $aIncludedFuncs[$i]&"(") = 0 then ContinueLoop
$sSource = "Func " & $aIncludedFuncs[$i] & "(" & _StringBetween($sSourceCode, "Func " & $aIncludedFuncs[$i] & "(", "EndFunc"&@CRLF)[0] & "EndFunc"&@CRLF
$aInternFuncs[$iCount] &= $sSource
$iCount += 1
Next
ReDim $aInternFuncs[$iCount]
;~ _ArrayDisplay($aInternFuncs)
; Variablen sammeln
$sGlobal = "= ,;"&'"'&"'[])&+*/^-" ; Operatoren und so...
$iCount=0
for $x = 0 to 2
if $x = 0 then
$aArray = $aFunctions
Elseif $x = 1 then
$aArray = $aIncludedFuncs
Elseif $x = 2 then
$aArray = $aInternFuncs
EndIf
for $i = 1 to UBound($aArray) -1
for $x = 1 to StringLen($aArray[$i])
$sChr = StringMid($aArray[$i], $x, 1)
if StringMid($aArray[$i], $x-2, 3) = ", _" or StringMid($aArray[$i], $x-2, 3) = "& _" then ContinueLoop 2 ; Nächste Zeile
if $sChr = ";" then ContinueLoop 2 ; ...
if $sChr = "$" then ; Variablenstart
$sTemp = ""
for $y = $x to StringLen($aArray[$i])
$sChr = StringMid($aArray[$i], $y, 1)
if StringInStr($sGlobal, $sChr) then
$x = $y-1
ExitLoop
EndIf
$sTemp &= $sChr
Next
$sTemp = StringStripWS($sTemp, 2)
if _ArraySearch($aVariables, $sTemp) = -1 then
$aVariables[$iCount] = $sTemp ; Zufügen
$iCount += 1
EndIf
EndIf
Next
Next
Next
ReDim $aVariables[$iCount]
;~ _ArrayDisplay($aVariables)
; Gefundene Variablen im Main-Source suchen und incl. Werte zuweisen
; Alle gefundenen Variablen im Main-Source suchen und bei Erfolg Werte übernehmen
$iCount=0
$iSkipFunc=0
for $i = 0 to UBound($aSourceCode) -1
if StringLeft(StringLower($aSourceCode[$i]), 4) = "func" then $iSkipFunc = 1 ; Innerhalb von Funktionen keine Variablen suchen
if StringLeft(StringLower($aSourceCode[$i]), 7) = "endfunc" then $iSkipFunc = 0 ; ...
if $iSkipFunc = 0 then
$aSourceCode[$i] = StringReplace($aSourceCode[$i], Chr(9), "")
for $x = 1 to StringLen($aSourceCode[$i])
$sChr = StringMid($aSourceCode[$i], $x, 1)
if StringMid($aSourceCode[$i], $x-2, 3) = ", _" or StringMid($aSourceCode[$i], $x-2, 3) = "& _" then ContinueLoop 2 ; Nächste Zeile
if $sChr = ";" then ContinueLoop 2 ; ...
if $sChr = "$" then ; Variablenstart
$sTemp = ""
for $y = $x to StringLen($aSourceCode[$i])
$sChr = StringMid($aSourceCode[$i], $y, 1)
;~ if $sChr = "," or StringMid($aSourceCode[$i], $y, 1) & $sChr = " _" or $sChr = ";" Then ; evtl. Variablenende
if $sChr = "," or StringMid($aSourceCode[$i], $y-2, 3) = ", _" or StringMid($aSourceCode[$i], $y-2, 3) = "& _" or $sChr = ";" Then ; evtl. Variablenende
$x = $y-1
ExitLoop
EndIf
$sTemp &= $sChr ; Gefundenes erweitern
Next
$sTemp = StringStripWS($sTemp,
for $y = UBound($aVariables)-1 to 0 Step -1 ; Variablen-Array prüfen
if $aVariables[$y] = (StringInStr($sTemp, "=") ? StringSplit($sTemp, "=")[1] : $sTemp) then ; Wenn eine Zuweisung vorhanden ist "=" dann Splitten
if _ArraySearch($aGlobalVariables, $sTemp) = -1 then
$aGlobalVariables[$iCount] = $sTemp ; Variable Zufügen
_ArrayDelete($aVariables, $y)
$iCount += 1
ExitLoop
EndIf
EndIf
Next
EndIf
Next
EndIf
Next
if $iCount = 0 Then $iCount = 1
ReDim $aGlobalVariables[$iCount]
;~ _ArrayDisplay($aGlobalVariables)
; Alles dem Neuen-Source zufügen
; Erst Includes, globale Variabeln, Haupfunktion, Unter-Funktionen in einem SourceCode hinterlegen
$sSource = ""
for $i = 0 to UBound($aIncludes) -1
if $aIncludes[$i] <> "" then $sSource &= $aIncludes[$i] & @CRLF
Next
$aSourceCode = "; Includes" & @CRLF & $sSource & @CRLF
if $aGlobalVariables[0] <> "" then
$sSource = "Global _" & @CRLF
for $i = 0 to UBound($aGlobalVariables) -1
if $aGlobalVariables[$i] <> "" then $sSource &= Chr(9) & $aGlobalVariables[$i] & ", _" & @CRLF
Next
$aSourceCode &= @CRLF & "; Globale Variablen" & @CRLF & StringTrimRight($sSource, 5) & @CRLF & @CRLF
EndIf
$sSource = ""
for $i = 0 to UBound($aFunctions) -1
$sSource &= $aFunctions[$i] & @CRLF
Next
$aSourceCode &= @CRLF & "; Hauptfunktion" & @CRLF & $sSource & @CRLF
$sSource = ""
if UBound($aInternFuncs) >0 then
for $i = 0 to UBound($aInternFuncs) -1
$sSource &= $aInternFuncs[$i] & @CRLF
Next
$aSourceCode &= @CRLF & "; Unterfunktionen" & @CRLF & $sSource
EndIf
; Datei schreiben
FileDelete(@ScriptDir&"\"&$sFuncName&".au3")
FileWrite(@ScriptDir&"\"&$sFuncName&".au3", $aSourceCode)
EndFunc
[/autoit] [autoit][/autoit] [autoit];
; Testumgebung...
Global $sTest, _
$iTestSingle, _
$iTestDoubleA1, $iTestDoubleA2, _
$iTestDoubleB1 = 1,$iTestDoubleB2=2, _
$iTest = 1,$iTestSingle
;~ _ExcludeFunc("_ExcludeFunc") ; Abhängikeitsprüfung und Export von '_ExcludeFunc'
;~ _ExcludeFunc("_GetFunc") ; Abhängikeitsprüfung und Export von '_GetFunc'
Func _GetFunc($sFuncName)
Dim $Test ; Test
$Test = $iTestSingle
$Test = $iTestDoubleA1
$Test = $iTestDoubleA2
$Test = $iTestDoubleB1
$Test = $iTestDoubleB2
$Test = $iTest
$Test = $iTestSingle
Return "Func " & $sFuncName&"(" & _StringBetween(FileRead(@ScriptFullPath), "Func " & $sFuncName&"(", "EndFunc"&@CRLF)[0] & @CRLF&"EndFunc"
EndFunc
Viel Spaß beim Debuggen
Grüsse!
[Edit]
Update auf V0.12:
Verbesserte Tiefenanlyse, wird jetzt auch bei Unterfunktionen angewendet
Variablenerkennung optimiert, es werden jetzt mehr abhängige Variablen erkannt
Weniger Au3Check-Error
Danke für die bisherigen 20 Downloads!