Ich möchte einem Bekannten, der bisher nur mit Batch gespielt hat, AutoIt näher bringen.
Er meinte ein Projekt, dass ihn interessieren würde, wäre der Download von Bildern vom eigenen Webspace.
Ich glaube zwar mittlerweile, dass ich ihm zu einem Skript ohne GUI hätte raten sollen, aber ich versprach ihm ein Beispielskript zu verfassen.
Nun bin ich begeistert von AutoIt, aber beileibe kein wirklicher Kenner! Daher möchte ich euch bitten, mein Erklär-Skript zu lesen, zu bewerten, und Verbesserungen erklärt zu posten. Ich möchte, dass er sich hier anmeldet, und gleich zu meinem Skript die Kommentare sehen kann. Damit er nicht zum Einen meinen schlechten Stil annimmt und zum anderen meine Fehler von Anfang an lernt.
Ich hänge das Skript in einer kommentierten und in einer unkommentierten Variante an, wie ich es ihm auch geben möchte.
Über eure Unterstützung würde ich mich echt freuen.
Kommentiert:
Spoiler anzeigen
#cs
Dies ist ein merhzeiliger Kommentar, den man durch #cs und #ce begrenzt.
Zu Anfang die Info für dich: Wenn du das Skript in SciTE geöffnet hast, kannst du die Befehle anklicken und dann F1 drücken.
Du landest dann direkt in der Hilfe in der Beschreibung des Befehls, wo auch immer Beispiele zu finden sind, die du direkt ausführen kannst.
;~ Einzelige Kommentare kannst du per Semikolon einleiten, oder drückst einfach Minus im Nummernfeld (wenn du SciTE verwendest).
#ce
#include <Array.au3>
#include <InetConstants.au3>
#include <GUIConstantsEx.au3> ; dies ist ein durch Semikolon eingeleiteter einzeiliger Kommentar
#include <StaticConstants.au3> ; Es handelt sich hier um eingebundene Sktripte, die mit der AutoIt-Installation geliefert wurden.
; Deren Funktionen du jetzt einfach in deinem Skript ansprechen kannst. Sie werden deinem Skript beim kompilieren einfach vorangestellt.
; Du kannst auch eigene Skripte inkludieren. Lege sie einfach in das Skriptverzeichnis und binde sie mit "" ein bspw. #include "meinSkript.au3"
;~ ### Deklarationen ###
Local $URLStart = "http://"
Local $Host = "192.168.123.5:80" ; IP Adresse oder Domain und Port - Port 80 muss man eigentlich nicht schreiben, da es der Standardport ist.
Local $Indexfile = "/tmp/Bilderindex.png" ; Die Datei ist hier nur als PNG benannt, weil unsere Recis (mein Testobjekt) keine txt streamt. Beim Download wird sie umbenannt.
Local $Bilderordner = "/tmp/Bilderordner" ; Der Ordner in dem die Bilder liegen.
Local $nLinks = "", $nLinks = "", $nDaten = "", $oDaten = "", $Anzahl = "", $KeinArray = "", $Error = "", $Durchlaeufe = ""
;~ Oben siehst du erst die Variablen mit Werten, die du anpassen musst. Danach kommen in einer Reihe die Variablen, die ich im Skript verwende.
;~ Das ist grundsätzlich nicht notwendig. Ich habe es mir aber angewöhnt, weil es notwendig wird, wenn die Variablen in mehreren Funktionen Verwendung finden.
;~ Die Variablen sind hier Local deklariert. Das muss man hier nicht angeben. Variablen die nicht anders deklariert sind, gelten immer lokal.
;~ Gerne wird bei den grundsätzlichen Variablen zu Anfang Global genommen. Das ist aber nicht notwendig.
;~ Du musst aber wissen: Wenn du eine Variable in einer Funktion deklarierst, hat sie nur darin Gültigkeit.
;~ Wenn du ihren Wert außerhalb der Funktion nutzen möchtest, musst du sie Global deklarieren.
;~ Ist aber meist nicht nötig. Du kannst die Variablen zu Anfang außerhalb deklarieren und ihr dann überall einen anderen Wert zuweisen.
;~ So könnte ich gleich einfach den Wert von $Host ändern, indem ich $Host = "192.0.0.1" schreibe. Dieser Wert gilt dann im weiteren Verlauf.
;~ ### Ende Deklarationen ###
;~ ### GUI (Programmoberfläche) ###
$Form1 = GUICreate("Bilder", 578, 296); Das ist die Programm-Oberfläche. Da keine Startposition angegeben ist, startet es immer zentriert im Desktop.
GUISetBkColor(0xEAEAEA, $Form1); die Hintergrundfarbe. Habe ich mit 'Autoit Window Info aus einem Browser Fenster gegrabbt. - Sehr praktisch das Ding!'
; auf der GUI befindliche Buttons, Labels, Menüs, Inputboxen usw. sind Controls. Die kommen jetzt.
$Suche = GUICtrlCreateButton("Suche starten", 180, 240, 217, 33) ; unser erster Button. Dieser ist von Beginn an sichtbar.
$Reaktion = GUICtrlCreateButton("", 180, 240, 217, 33) ; Diesen Button blende ich gleich aus und blende ihn erst wieder ein, wenn er relevant wird.
$Label1 = GUICtrlCreateLabel("", 34, 100, 508, 129, $SS_Center) ; Dieses Label füllen wir später mit Text. Mit $SS_Center wird der Text zentriert.
; Damit man diesen Stil (hier zentrierter Text) verwenden kann, muss man oben GUIConstantsEx.au3 einbinden. Das findet man, wenn man in der Hilfe auf Stile klickt.
; Über der Liste der Stile für einzelne Controls, steht welche Funktionen man einbinden muss.
$Label2 = GUICtrlCreateLabel("", 500, 43, 50, 50, $SS_Center) ; auch dieses Label füllen wir später. Hier werden die Bilder gezählt.
GUICtrlSetState($Reaktion, $GUI_HIDE) ; Hier blenden wir den den Reaktion Button aus. Reine Spielerei, um dir das zu zeigen.
GUISetState(@SW_SHOW) ; Hier machen wir das Fenster sichtbar.
;~ ### Ende GUI (Programmoberfläche) ###
;~ ### DIE WHILE-SCHLEIFE ###
;~ Jetzt kommt die While-Schleife. Das zentrale Element! Nachdem sie begonnen hat durchläuft das Skript endlos die Schleife.
;~ Ohne diese Schleife, würde das Fenster sofort verschwinden. Innerhalb der Schleife wird jetzt geprüft, was die GUI meldet.
;~ Wurde Button A gedrückt dann mache dies u.s.w.
;~ Alle unsere weiteren Schritte sind Funktionen, die etwa bei einem Button-Click ausgeführt werden. Wenn die Funktion durchlaufen ist,
;~ landen wir wieder in der Schleife.
While 1
$nMsg = GUIGetMsg() ; Hiermit holen wir uns die Status-Informationen der GUI
Switch $nMsg ; Innerhalb von Switch und EndSwitch sind die von uns definierten GUI-Controls, auf die wir reagieren
Case $GUI_EVENT_CLOSE ; Hier fangen wir ein allgemeines Status-Event ab. GUI wird geschlossen. Um diesen Befehl nutzen zu können, mussten wir StaticConstants.au3 einbinden.
FileDelete(@ScriptDir & "\Index_neu.txt") ; Beim Schließen räumen wir auch auf und löschen eine eventuell vorhandene neue Indexdatei
Exit ; Wir reagieren mit Exit. Das Programm wird beendet.
Case $Suche ; Hier reagieren wir auf den Suche-Button
GUICtrlSetData($Label1, "Suche gestartet...")
_Suche() ; Bei Klick auf den Button, führen wir die _Suche Funktion aus. Du findest sie unten ab Func _Suche()
Case $Reaktion ; Hier reagieren wir auf den zweiten Button.
_Laden() ; Bei Klick auf den Button, führen wir die _Laden Funktion aus. Du findest sie unten ab Func _Laden()
EndSwitch
WEnd
;~ ### Ende DIE WHILE-SCHLEIFE ###
Func _Suche()
$nLinks = "" ; Hier werden einige Variablen geleert, damit sie bei einem erneuten Klick auf den Button wieder leer sind.
$nDaten = ""
$oDaten = ""
$Anzahl = ""
$LoadIndex = InetGet($URLStart & $Host & $Indexfile, @ScriptDir & "\Index_neu.txt", 1, 1) ; Hier laden wir die Datei im Hintergrund (siehe Optionen in der Hilfe).
;~ Das Sript wartet nicht. Dafür erstelle ich gleich eine Schleife.
If Not @error Then ; Hier prüfen wir, ob der initialisiert wurde.
Do ; Hier haben wir eine Do-Until-Schleife. Das Skript wartet 250 Millisekunden, prüft ob der Downlod abgeschlossen ist und wenn nicht wartet es wieder 250 Millisekunden.
;~ Ansonsten wird die Schleife abgebrochen.
Sleep(250) ; Pause in Millisekunden!
Until InetGetInfo($LoadIndex, $INET_DOWNLOADCOMPLETE) ; Wir prüfen bis der Download komplett ist. Daher auch die Variable vor Inetget. Das ist sonst nicht notwendig.
$nDaten = FileReadToArray(@ScriptDir & "\Index_neu.txt") ; Hier wird die heruntergeladene Datei in ein Array gelesen. Dazu: http://www.bug-fix.info/array_tut.htm
;~ Am einfachsten kannst du dir den Unterschied zwischen einer Variablen und eine Array vorstellen, wenn du eine Variable als einfache Liste siehst und ein Array als
;~ Tabelle mit Zeilen und Spalten.
If FileExists(@ScriptDir & "\Index_alt.txt") Then $oDaten = FileReadToArray(@ScriptDir & "\Index_alt.txt") ; hier wird geprüft, ob schon eine alte Indexdatei
;~ vorhanden ist. Wenn ja, wird sie auch in ein Array gelesen.
If IsArray($nDaten) And IsArray($oDaten) Then ; Hier wird geprüft, ob beides ein Array ist. Wenn ja, dann...
For $i = 0 To UBound($nDaten) - 1 ; Unsere erste For Schleife! Sie läuft so lange, wie die Wiederholungen absolviert wurden, oder man mit Exitloop abbricht.
;~ Mit UBound($nDaten) ermitteln wir die Größe von $nDaten. Nehmen wir an, $nDaten hat 12 Zeilen (also deine 12 Bilder), dann bestimmen wir hier:
;~ $i hat erst den Wert 0. Mit jedem Durchlauf steigert sich der Wert um 1. Die Schleife läuft bis $i den Wert 12 erreicht hat.
;~ Hier ist noch zu beachten, dass Arrays Null basiert sind (Das erste Bild steht also in der Zeile 0).
;~ Das bedeutet, 12 Bilder bilden ein Array mit dem Wert 11.
;~ Ubound spuckt aber die Zeilenanzahl 12 aus. Deshalb müssen wir beim Durchlauf eines Arrays - 1 hinter die ermittelte Größe von Ubound setzen.
;~ Andernfalls stürzt das Skript in Zeile 12 ab. Da das Array nur 11 Zeilen hat. Das kannst du dir gut mit _ArrayDisplay anschauen.
;~ Ein Bsp. findest du unten.
_ArraySearch($oDaten, $nDaten[$i]) ; Hier durchsuchen wir das Array mit den alten Daten nach den Daten der Zeile $i aus dem neuen Array.
If @error Then ; Wenn ein Fehler auftritt , ist der Wert nicht in der alten Liste. Es handelt sich also um ein neues Bild.
$nLinks &= $nDaten[$i] & "|" ; Dieses neue Bild aus Zeile $i wird in die Linkliste aufgenommen. Wir füllen hier die Variable $nLinks.
$Anzahl = $Anzahl + 1 ; Hier wird mit jedem Treffer die Wert für Count erhöht. Wir wollen damit später arbeiten.
EndIf ; If Bedingung endet mit EndIf
Next ; For-Schleife endet mit Next
EndIf
If IsArray($nDaten) And $oDaten = "" Then ; Falls noch keine alte Indexdatei vorhanden war..
For $i = 0 To UBound($nDaten) - 1
$nLinks &= $nDaten[$i] & "|" ; Alle Einträge aus nDaten werden dann in die Variable $nLinks übernommen.
$Anzahl = UBound($nDaten) ; Die Anzahl ist dann auch die Anzahl der Einträge aus dem $nDaten-Array.
Next
EndIf
If $nLinks <> "" Then ; Wenn die Linkliste ungleich leer ist, dann..
GUICtrlSetState($Reaktion, $GUI_SHOW) ; Hier blenden wir den den Reaktion Button ein, weil es etwas zum Laden gibt.
GUICtrlSetData($Reaktion, "Laden") ; Wir setzen den Button-Text.
GUICtrlSetState($Suche, $GUI_HIDE) ; Hier blenden wir den den Suche Button aus.
GUICtrlSetData($Label1, $Anzahl & " neue Bilder gefunden.") ; Wir ändern den Text von Label1
Else ; Else ist erfüllt, wenn die Bedingungen in der If-Zeile nicht erfüllt sind!
GUICtrlSetData($Label1, "Keine neuen Bilder gefunden.") ; Da die Linkliste leer ist, haben wir keine neuen Bilder gefunden..
EndIf
Else
GUICtrlSetData($Label1, "Keine Verbindung vorhanden, oder keine Bilder auf dem Server.") ; da wir die Index-Datei nicht laden konnten,
FileDelete(@ScriptDir & "\Index_neu.txt")
EndIf
;~ ### Array und Variablen-Anschau ###
;~ --- Unten kannst du #cs und #ce auskommentieren. Dann kannst du dir die Inhalte der Linkliste und der $Anzahl anschauen. ---
#cs
;~ Wenn du #cs und #ce hier auskommentierst, dann kannst du dir die erhobenen Daten ansehen.
MsgBox(0,"Bilder-Anzahl", $Anzahl)
If IsArray($nLinks) Then
_ArrayDisplay($nLinks)
Else
If $nLinks = "" Then $nLinks = "Die Variable ist leer."
MsgBox(0,"Links", $nLinks)
EndIf
#ce
;~ ### Ende Array und Variablen-Anschau ###
EndFunc ;==>_Suche
Func _Laden() ; Hier beginnt die Funktion _Laden(). Sie endet mit EndFunc
$Error = "" ; Error wird geleert, falls der Nutzer die Funktion mehrfach ausführt.
GUICtrlSetData($Label1, "Bilder werden geladen")
DirCreate(@ScriptDir & "\Bilder") ; Hier erstellen wir das Verzeichnis Bilder im Skriptverzeichnis, damit gleich die Bilder dort gespeichert werden können.
For $i = 1 To $Anzahl ; Hier durchsuchen wir eine Variable und beginnen daher ab 1 und gehen auch bis $Anzahl
GUICtrlSetData($Label2, $i & "/" & $Anzahl) ; Hier ändern wir den Text des Label2, damit sichtbar mitgezählt wird. (Durchläusfe / Anzahl Bilder)
$LinkSplit = StringSplit($nLinks, "|") ; Hier splitten wir die Variable, die aktuell nichts weiter darstellt, als ein Text wie Bild1|Bild2|Bild3 usw..
InetGet($URLStart & $Host & $Bilderordner & "/" & $LinkSplit[$i], @ScriptDir & "\Bilder\" & $LinkSplit[$i], 1, 0) ; Hier werden die Bilder geladen.
;~ Die Optionen 1, 0 am Ende bedeuten, das Skript erzwingt das neue Laden vom Server und wartet bis der Download erfolgt ist.
If Not FileExists(@ScriptDir & "\Bilder\" & $LinkSplit[$i]) Then $Error &= $LinkSplit[$i] & @CRLF ; Wenn ein Bild nicht existiert, schreiben wir das in eine Fehler-Variable.
Sleep(200) ; Diese Pause haben wir nur, damit man bei kleinen Bildern überhaupt sieht, das hochgezählt wird. Das kannst du in der Praxis wohl entfernen.
Next
If $nLinks <> "" Then FileMove(@ScriptDir & "\Index_neu.txt", @ScriptDir & "\Index_alt.txt", 1) ; Hier überschreiben wir die alte Index-Datei mit der neuen.
GUICtrlSetData($Label2, "") ; Zähl-Anzeige wird wieder geleert.
GUICtrlSetData($Label1, "Bilder wurden geladen") ; Ergebnis wird präsentiert.
GUICtrlSetState($Reaktion, $GUI_HIDE) ; Hier blenden wir den den Reaktion Button wieder aus.
GUICtrlSetState($Suche, $GUI_SHOW) ; Hier blenden wir den den Suche Button wieder ein.
If $Error <> "" Then ; Falls ein Fehler aufgetreten ist, dann schreibe ein Logfile und gib eine Meldung in der GUI.
FileWrite(@ScriptDir & "\Fehlerlog.txt", @MDAY & "." & @MON & "." & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF & $Error & @CRLF)
GUICtrlSetData($Label1, "Es traten Fehler auf" & @CRLF & "Folgende Bilder wurden nicht geladen - finden sich auch im Log im Programmverzeichnis:" & @CRLF & $Error)
EndIf
EndFunc ;==>_Laden
Alles anzeigen
Unkommentiert:
Spoiler anzeigen
#include <Array.au3>#include <InetConstants.au3>#include <GUIConstantsEx.au3>#include <StaticConstants.au3>Local $URLStart = "http://"Local $Host = "192.168.123.5:80"Local $Indexfile = "/tmp/Bilderindex.png"Local $Bilderordner = "/tmp/Bilderordner"Local $nLinks = "", $nLinks = "", $nDaten = "", $oDaten = "", $Anzahl = "", $KeinArray = "", $Error = "", $Durchlaeufe = ""$Form1 = GUICreate("Bilder", 578, 296)GUISetBkColor(0xEAEAEA, $Form1)$Suche = GUICtrlCreateButton("Suche starten", 180, 240, 217, 33)$Reaktion = GUICtrlCreateButton("", 180, 240, 217, 33)$Label1 = GUICtrlCreateLabel("", 34, 100, 508, 129, $SS_Center)$Label2 = GUICtrlCreateLabel("", 500, 43, 50, 50, $SS_Center)GUICtrlSetState($Reaktion, $GUI_HIDE)GUISetState(@SW_SHOW)While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE FileDelete(@ScriptDir & "\Index_neu.txt") Exit Case $Suche GUICtrlSetData($Label1, "Suche gestartet...") _Suche() Case $Reaktion _Laden() EndSwitchWEndFunc _Suche() $nLinks = "" $nDaten = "" $oDaten = "" $Anzahl = "" $LoadIndex = InetGet($URLStart & $Host & $Indexfile, @ScriptDir & "\Index_neu.txt", 1, 1) If Not @error Then Do Sleep(250) Until InetGetInfo($LoadIndex, $INET_DOWNLOADCOMPLETE) $nDaten = FileReadToArray(@ScriptDir & "\Index_neu.txt") If FileExists(@ScriptDir & "\Index_alt.txt") Then $oDaten = FileReadToArray(@ScriptDir & "\Index_alt.txt") If IsArray($nDaten) And IsArray($oDaten) Then For $i = 0 To UBound($nDaten) - 1 _ArraySearch($oDaten, $nDaten[$i]) If @error Then $nLinks &= $nDaten[$i] & "|" $Anzahl = $Anzahl + 1 EndIf Next EndIf If IsArray($nDaten) And $oDaten = "" Then For $i = 0 To UBound($nDaten) - 1 $nLinks &= $nDaten[$i] & "|" $Anzahl = UBound($nDaten) Next EndIf If $nLinks <> "" Then GUICtrlSetState($Reaktion, $GUI_SHOW) GUICtrlSetData($Reaktion, "Laden") GUICtrlSetState($Suche, $GUI_HIDE) GUICtrlSetData($Label1, $Anzahl & " neue Bilder gefunden.") Else GUICtrlSetData($Label1, "Keine neuen Bilder gefunden.") EndIf Else GUICtrlSetData($Label1, "Keine Verbindung vorhanden, oder keine Bilder auf dem Server.") FileDelete(@ScriptDir & "\Index_neu.txt") EndIfEndFunc ;==>_SucheFunc _Laden() $Error = "" GUICtrlSetData($Label1, "Bilder werden geladen") DirCreate(@ScriptDir & "\Bilder") For $i = 1 To $Anzahl GUICtrlSetData($Label2, $i & "/" & $Anzahl) $LinkSplit = StringSplit($nLinks, "|") InetGet($URLStart & $Host & $Bilderordner & "/" & $LinkSplit[$i], @ScriptDir & "\Bilder\" & $LinkSplit[$i], 1, 0) If Not FileExists(@ScriptDir & "\Bilder\" & $LinkSplit[$i]) Then $Error &= $LinkSplit[$i] & @CRLF Sleep(200) Next If $nLinks <> "" Then FileMove(@ScriptDir & "\Index_neu.txt", @ScriptDir & "\Index_alt.txt", 1) GUICtrlSetData($Label2, "") GUICtrlSetData($Label1, "Bilder wurden geladen") GUICtrlSetState($Reaktion, $GUI_HIDE) GUICtrlSetState($Suche, $GUI_SHOW) If $Error <> "" Then FileWrite(@ScriptDir & "\Fehlerlog.txt", @MDAY & "." & @MON & "." & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF & $Error & @CRLF) GUICtrlSetData($Label1, "Es traten Fehler auf" & @CRLF & "Folgende Bilder wurden nicht geladen - finden sich auch im Log im Programmverzeichnis:" & @CRLF & $Error) EndIfEndFunc ;==>_Laden
[/autoit]