1. Dashboard
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forenregeln
  4. Forum
    1. Unerledigte Themen
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. AutoIt.de - Das deutschsprachige Forum.
  2. Mitglieder
  3. Code-Jack

Beiträge von Code-Jack

  • Kopiertool

    • Code-Jack
    • 14. Dezember 2018 um 14:30

    Hallo Kayes,

    Ich schmeiße Dir einfach mal ein altes (und sicher verbesserungsfähiges) Script von mir vor die Füße, das damals unter Mithilfe mehrerer User dieses Forums entspanden ist.

    Vermutlich enthält es genügend Anregungen, anhand derer Du Dein Problem selbst gelöst bekommst.

    C
    ; Scriptname: PhotoRec-Butler
    ; Version: 1.01 vom 08.11.'16 (basierend auf Version 1.0 vom 26.07.'16)
    ; Autor: Stefan Denk (alias "Code-Jack", alias "Desi"), Fa. EDV-Dompteur
    ; Website: http://www.EDV-Dompteur.de
    ; Status: Freeware
    
    ; V E R W E N D U N G S Z W E C K :
    ; Dieses Script kommt zur Anwendung nach einer Datenrettung mit dem Programm "PhotoRec", aus dem Programmpaket "Testdisc",
    ; der ein Durchlauf des Scriptes "PhotoRec_Sorter" folgte.
    ; Im Anschluss an die Anwendung von PhotoRec_Sorter dürfte man einen Ordner namens "JPG" vorfinden, gefüllt mit nichts als massenhaft JPG-Dateien.
    ; In meinem eigenen Fall enthielt dieser Ordner über 465000 Dateien, was den Windows-Explorer völlig ausbremste. Es war kaum möglich,
    ; auch nur den Ordnerinhalt anzeigen zu lassen; es waren einfach gar zu viele Dateien darin vorhanden.
    ; Die Aufgabe des hier vorliegenden Scriptes ist es, die im JPG-Ordner vorhandenen Bilder, nach Aufnahmedatum sortiert, in automatisch angelegte
    ; Unterordner zu verschieben, so dass im Anschluss für jeden Tag, an dem ein Bild (bzw. mehrere) aufgenommen wurde(n), ein eigener Unterordner existiert.
    ;
    ; B E N U T Z U N G:
    ; Das Script soll sich NEBEN dem Ordner mit dem Namen "JPG" befinden, wenn es gestartet wird (also NICHT dort hinein kopieren!).
    ; Dann einfach das Script starten und abwarten. Im Anschluss findet man eine Ordnerstruktur nach folgendem Schema vor:
    ; ...\JPG\15-08-23
    ; ...\JPG\15-09-18
    ; ...\JPG\16-01-29
    ; etc.
    ; In jedem dieser automatisch angelegten Unterordner befinden sich nur genau jene Bilder, die an dem Tag aufgenommen wurden, der dem Ordnernamen entspricht.
    ;
    ; D A N K S A G U N G:
    ; Der Autor dankt folgenden Usern des großartigen Forums http://www.autoit.de für ihre Tipps, bzw. Code-Schnippsel:
    ; Simucal - für die Funktion _FileGetProperty, auf der dieses Script aufbaut.
    ; Oscar - für Codeschnippsel und präzise Hinweise.
    ; Xorianator - fürs Mitdenken.
    
    
    #include <FileConstants.au3>
    #include <MsgBoxConstants.au3>
    #include <WinAPIFiles.au3>
    
    Global $sQuellpfad = @ScriptDir & "\JPG\"
    Global $hSearch
    Global $sFileWithPath
    
    ; Das Handle der ersten Datei im Quellpfad ermitteln.
    $hSearch = FileFindFirstFile($sQuellpfad & "*.*")
    
    ; Überprüfen, ob obige Suche erfolgreich war.
    If $hSearch = -1 Then
      MsgBox($MB_SYSTEMMODAL, "", "Error: No files/directories matched the search pattern.")
      Return False
    EndIf
    
    ; Assign a Local variable the empty string which will contain the files names found.
    Global $sFileName = "", $iResult = 0
    
    While 1
      $sFileName = FileFindNextFile($hSearch)    ; Der Name der jeweils nächsten Datei.
      If @error Then ExitLoop                    ; Wenn keine weitere Datei vorhanden, dann Script beenden.
      ConsoleWrite($sFileName & @CRLF)           ; Dient nur der Kontrolle, ob das Script auch wirklich tätig ist und nicht etw "hängt"  :-)
    
      $sFileWithPath = $sQuellpfad & $sFileName  ; Der volle Pfad der Datei, samt deren Dateiname.
      $sAufnahmezeitpunkt = _FileGetProperty($sFileWithPath, "Bild aufgenommen am")  ;Das Datum, an dem das Bild tatsächlich aufgenommen wurde.
      ;ConsoleWrite($sAufnahmezeitpunkt & @CRLF) ; Dient nur zum Debuggen, sollte auskommentiert werden.
    
      $sJahr = StringMid($sAufnahmezeitpunkt, 7, 4)
      $sMonat = StringMid($sAufnahmezeitpunkt, 4, 2)
      $sTag = StringMid($sAufnahmezeitpunkt, 1, 2)
    
      $sZielpfad = $sQuellpfad & $sJahr & "-" & $sMonat & "-" & $sTag & "\"  ; Hierhin wird die Bilddatei gleich verschoben.
      ;ConsoleWrite($sZielpfad & @CRLF)          ; Dient nur zum Debuggen, sollte auskommentiert werden.
    
      ; Quelldatei in den neuen Ordner verschieben (Ordner wird automatisch erzeugt, falls noch nicht vorhanden).
      ;FileMove($sFileWithPath, $sZielpfad & $sFileName, $FC_OVERWRITE + $FC_CREATEPATH)
      FileMove($sFileWithPath, $sZielpfad & $sFileName, $FC_CREATEPATH)
    
    WEnd
    
    ; Close the search handle.
    FileClose($hSearch)
    
    
    ;===============================================================================
    ; Function Name.....: _FileGetProperty
    ; Description.......: Returns a property or all properties for a file.
    ; Version...........: 1.0.2
    ; Change Date.......: 05-16-2012
    ; AutoIt Version....: 3.2.12.1+
    ; Parameter(s)......: $S_PATH - String containing the file path to return the property from.
    ;                     $S_PROPERTY - [optional] String containing the name of the property to return. (default = "")
    ; Requirements(s)...: None
    ; Return Value(s)...: Success: Returns a string containing the property value.
    ;                       If $S_PROPERTY is empty, an two-dimensional array is returned:
    ;                         $av_array[0][0] = Number of properties.
    ;                         $av_array[1][0] = 1st property name.
    ;                         $as_array[1][1] = 1st property value.
    ;                         $av_array[n][0] = nth property name.
    ;                         $as_array[n][1] = nth property value.
    ;                     Failure: Returns 0 and sets @error to:
    ;                       1 = The folder $S_PATH does not exist.
    ;                       2 = The property $S_PROPERTY does not exist or the array could not be created.
    ;                       3 = Unable to create the "Shell.Application" object $objShell.
    ; Author(s).........: - Simucal <Simucal@gmail.com>
    ;                     - Modified by: Sean Hart <autoit@hartmail.ca>
    ;                     - Modified by: teh_hahn <sPiTsHiT@gmx.de>
    ;                     - Modified by: BrewManNH
    ; URL...............: http://www.autoitscript.com/forum/topic/...property/page__view__findpost_
    ; Note(s)...........: Modified the script that teh_hahn posted at the above link to include the properties that
    ;                     Vista and Win 7 include that Windows XP doesn't. Also removed the ReDims for the $av_ret array and
    ;                     replaced it with a single ReDim after it has found all the properties, this should speed things up.
    ;===============================================================================
    Func _FileGetProperty(Const $S_PATH, Const $S_PROPERTY = "")
        Local Const $objShell = ObjCreate("Shell.Application")
        If @error Then Return SetError(3, 0, 0)
        Local $iPropertyCount = 300 ; arbitrary number used, Windows 7 only returns 289 properties, Windows XP only returns 38 (future proofing)
        If StringLeft($S_PATH, 1) = '"' Then StringTrimLeft($S_PATH, 1) ; deletes any quotes around the path\filename, otherwise will cause errors
        If StringRight($S_PATH, 1) = '"' Then StringTrimRight($S_PATH, 1) ; deletes any quotes around the path\filename, otherwise will cause errors
        If Not FileExists($S_PATH) Then Return SetError(1, 0, 0)
        Local Const $S_FILE = StringTrimLeft($S_PATH, StringInStr($S_PATH, "\", 0, -1))
        Local Const $S_DIR = StringTrimRight($S_PATH, StringLen($S_FILE) + 1)
        Local Const $objFolder = $objShell.NameSpace($S_DIR)
        Local Const $objFolderItem = $objFolder.Parsename($S_FILE)
        If $S_PROPERTY Then
            For $I = 0 To $iPropertyCount
                If $objFolder.GetDetailsOf($objFolder.Items, $I) = $S_PROPERTY Then Return $objFolder.GetDetailsOf($objFolderItem, $I)
            Next
            Return SetError(2, 0, 0)
        EndIf
        Local $av_ret[300][2] = [[1]]
        For $I = 1 To $iPropertyCount + 1
            If $objFolder.GetDetailsOf($objFolder.Items, $I) Then
                $av_ret[$I][0] = $objFolder.GetDetailsOf($objFolder.Items, $I - 1)
                $av_ret[$I][1] = $objFolder.GetDetailsOf($objFolderItem, $I - 1)
                $av_ret[0][0] += 1
            EndIf
        Next
        ReDim $av_ret[$av_ret[0][0] + 1][2]
        If Not $av_ret[1][0] Then Return SetError(2, 0, 0)
        Return $av_ret
    EndFunc   ;==>_FileGetProperty
    Alles anzeigen
  • Internetseite auslesen und dann?

    • Code-Jack
    • 14. Dezember 2018 um 08:05

    Der Website-Betreiber wird sicherlich Freudensprünge machen, über einen User, der Listen mit Zugangsdaten automatisiert abarbeitet, bis er auf einen noch funktionierenden Account stößt, in den er sich dann einloggt und - wiederum automatisiert - Inhalte absaugt, an die er anders nicht heran käme.

    :thumbdown:

  • ListView füllen und ProgressBar

    • Code-Jack
    • 7. Dezember 2018 um 16:52
    Zitat von Bitnugger

    Du meinst wohl...

    a) _SQLite_Query() in einer While-Schleife mit _SQLite_FetchData() plus _GUICtrlListView_AddArray()

    Ja, naturalmente.

    Aber - öhh, sicherlich bin ich nur zu dumm - was genau soll Dein Quelltext aussagen?

  • Script mit Login versehen

    • Code-Jack
    • 7. Dezember 2018 um 16:23

    Ich schmeiße mal eine neue Idee in die Runde.

    Prinzip: Die Daten sind gar nicht da, wenn der rechtmäßige Nutzer nicht da ist.

    Und das kombinieren wir mit schon genannten Methoden:

    Step 1:

    Das Script, welches das Passwort entgegen nimmt, kann von der bösen Person Ede Knastmann gerne im Quelltext eingesehen werden. Es ist im Prinzip nur ein Launcher, welcher das PW an ein kleines TrueCrypt-Archiv sendet.

    Sofern TrueCrypt mit dem PW zufrieden ist, bindet es ein neues Laufwerk ins System ein, unter immer dem selben Laufwerksbuchstaben. Z. B. Laufwerk K.

    Step 2:

    Auf dem streng gecrypteten Laufwerk liegt das eigentliche Anwendungsprogramm, welches nun vom Launcher gestartet wird.

    - Aber halt! Ede Knastmann könnte den Rechner ja geschickt verseucht haben, so dass der Inhalt des gecrypteten Containers im Hintergrund heimlich kopiert wird!

    Darum nun Step 3 ...

    Step 3:

    Das ist jetzt die große neue Idee:

    Das Anwendungsprogramm im Container ist nicht lauffähig, ohne hinzugeladene Daten. Aber die liegen nicht im Container und nicht auf der Platte.

    Sondern die liegen auf einem ESP32 WLAN-Modul. So ein Ding passt mitsamt Akku in eine Streichholzschachtel. Programmiert werden kann das Teil mit der Arduino-IDE.

    Der ESP32 stellt einen Webserver dar und bietet in der kleinsten Version immerhin 4MB Speicher.

    Darauf kann man eine wiederum verschlüsselte Datei ablegen, die das Programm im Container ins Ram lädt und dort entschlüsselt. Erst mit diesen Daten wird es vollständig lauffähig.

    (Kritikpunkt weiter unten)

    Wenn der rechtmäßige Benutzer die Arbeit beendet, schließt er das Programm im Container.

    Der parallel noch immer laufende Launcher bemerkt das und schließt zudem den TrueCrypt-Container.

    Der Benutzer entfernt sich und/oder schaltet seinen ESP32 in der Hosentasche aus.

    Ede Knastmann mag den Quelltextdes Launchers einsehen, doch das nützt ihm nichts.

    Ede mag zudem auch das Passwort für den Container per Keylogger erbeutet haben, doch es nützt ihm wiederum nichts, ohne den Daten aus dem ESP32.

    Ede hat zwar heimlich im Hintergrund den kompletten Inhalt des geöffneten Containers kopiert. Doch dummerweise läuft das darin befindliche Programm partout nicht, ohne den Daten vom ESP32 ...

    Ede ist hartnäckig - neulich hat er sogar die WLAN-Verbindung mitgenifft. Doch die erfolgte ja verschlüsselt.

    Also schon ziemlich sicher!

    Dennoch gibt es keine 100%ige Sicherheit.

    Zu irgend einem Zeitpunkt liegen die Daten ja lauffähig im Ram.

    Wenn Ede tatsächlich so krass drauf sein sollte, dass er den RAM-Inhalt ausliest und analysiert, dann ...

    - Auch dagegen mag es Schutz geben, aber langsam wird's utopisch.

    Zumindest könnte man aber nach getaner Arbeit noch den Speicher clearen. Kleine Routine, die das RAM kurzzeitig mit Müll vollpumpt, bis hart an den Anschlag.

    Allerdings kann einem dabei noch die Windows-Auslagerungsdatei wieder in die Suppe spucken ...


    Ich hatte mal eine Praktikantin, die ich sehr hart im Verdacht habe, dass sie mir eine Schadsoftware installiert hatte, die im Hintergrund mindestens Hardcopys erstellte. Womöglich zudem noch gepaart mit einem Keylogger.

    Aber ich glaube eher nicht, dass Ihre Malware den oben von mir beschriebenen Weg irgendwie geknackt hätte.

    Wenn man also nicht gerade die NSA am Hals hat und draußen vor dem Haus ständig Fahrzeuge mit getönten Scheiben parken, dann scheint mir das Prinzip einen ausreichenden Schutz zu bieten.

    'Nen ESP32 kriegt man in 100 Varianten für unter 10,- EUR und die Programmierung ist halt wie bei 'nem ollen Arduino.

    Gegenüber einem USB-Stick hat man da den Vorteil, dass auf dem Ding komplexe selfmade Software laufen kann, die Daten nur beliebig widerwillig heraus rückt (und das natürlich vorzugsweise verschlüsselt).

    Einen simplen USB-Stick könnte man zudem im Rechner eingesteckt vergessen. Doch der ESP32 befindet sich permanent in der eigenen Hosentasche. Entfernt man sich aus der Reichweite des Rechners, dann sind die darauf gespeicherten Daten halt ebenfalls definitiv außer Reichweite.

    Kann man alles wohl noch weiter verfeinern, mir ging es nur darum, die neue Anregung in die Runde zu werfen

    .

  • ListView füllen und ProgressBar

    • Code-Jack
    • 7. Dezember 2018 um 07:10

    Ich schmeiße mal meine jüngsten Erkenntnisse in die Runde.

    Diese sind leider nicht als der Weisheit letzter Schluss anzusehen, könnten die erfahreneren User aber dazu veranlassen, eigene Untersuchungen anzustellen, um womöglich unerwartetes Optimierungspotenzial zu erschließen.

    Es geht um die Frage: Auf welche Weise bekommt man eine ListView schneller gefüllt?

    a) _SQLite_Query(), plus einer While-Schleife mit _SQLite_FetchData()

    b) _SQLite_GetTable2d() plus _GUICtrlListView_AddArray()

    Die erfahrenen User waren ja der Meinung, Variante b) wäre schneller.

    Nun, nach meinen Tests ist die Sache so klar nicht ...

    Tatsächlich gewinnt bei mir Variante a), sofern die komplette Datenbank in die ListView fließen soll.

    Der Zeitunterschied fällt nicht gigantisch hoch aus, aber er beträgt bei mir (1400 Datensätze zu 32 Feldern) immerhin:

    a) 3047 ms

    b) 3614 ms

    Aber damit nicht genug, denn man bekommt die Variante a) noch rund doppelt schneller, indem man die übliche While-Schleife durch eine For-Next-Schleife ersetzt (mit ausreichend hohem Endwert), in der sich folgende If-Konstruktion befindet:

    if _SQLite_FetchData($hQuery, $aTaxi, False, False) = $SQLITE_OK Then

    Dann reduziert sich die Zeit für das Füllen der ListView sogar auf:

    1535 ms!

    Das ist also deutlich mehr als doppelt so schnell, wie Variante b).

    Dummerweise sieht die Sache aber anders aus, wenn nicht die komplette Datenbank eingelesen werden soll, sondern wenn das Query so gestrickt ist, dass es z. B. 1000 der 1400 Datensätze findet.

    In diesen Fällen gewinnt bei mir immer die Variante b).

    Ich kann mir gut vorstellen, dass wenn die geschätzten Power-User der Sache tiefer auf den Grund gehen, ein bislang unerwarteter Geschwindigkeitsschub für betroffene Anwendungen machbar ist.

  • Den Namen der aktiven (oder aufrufenden) Function ermitteln

    • Code-Jack
    • 27. November 2018 um 03:00

    (Ich schreibe es mal in ein neues Posting, damit es nicht unter geht)

    Vorweg explizit noch einmal ganz dicken Dank an Musashi! Die Vollversion vom SciTE unterstützt den Entwickler wirklich signifikant besser beim coden, als die "Lite".

    Nun noch einmal zu der Betriebssystem-Thematik, nachdem autoiter es sogar in der Shoutbox anschnitt:

    Ich habe mehrere (unterschiedlich gute) Gründe, warum ich XP einsetze - speziell zum Coden.

    Den vielleicht gewichtigsten Grund nenne ich noch einmal (obwohl neulich schon anderweitig im Forum geschehen):

    Ich entwickle Geräte für gewerblichen Einsatz.

    Steuerungen für Schaustellerbetriebe; Testgeräte für Werkstätten; Spielautomaten; einmal auch eine Zentralsteuerung für ein Waschcenter.

    Wo immer es geht, setze ich die robusteste, simpelste Hardware ein.

    Atmel AVR und so.

    Im Waschcenter kam darüber hinaus ein fest verbautes Android-Tablet zu Einsatz. Eine einerseits schicke Lösung, andererseits nicht robust genug.

    Schon seit längerer Zeit habe ich die Idee, bei künftigen Steuerungen, die ein gutes "Mehr" an Rechenpower benötigen, als ein 8-Bit AVR (Arduino) je leisten könnte, ein minimalistisches Embedded PC-Board zu verbauen, auf dem ein XP laufen soll.

    Geldautomaten laufen ja auch oft noch mit XP. Was wollte man da auch mit Win10?

    Ganz oft benötige ich eine direkt verbaute, serielle Schnittstelle, die modernere Mainboards gar nicht mehr haben. USB-Adapter sind da nur ein Notnagel, aber keine hinreichend zuverlässige Lösung.

    Ich brauche ungefähr etwas wie den Raspberry Pi (mit RS232), nur läuft drauf (meines Wissens) kein Windows und diese Dinger sind mir auch deutlich zu sensibel. Die sind nicht tauglich, für wirklich harten Einsatz.

    Gegenwärtig entwickle ich ein Testgerät, wo (vermutlich) erstmals tatsächlich so ein Embedded PC-Platinchen verbaut werden soll.

    Das Gerät benötigt eine Datenbank-Anbindung.

    Plan A: Embedded PC rein, plus Display - alles gut!

    Plan B: Die Datenbank läuft auf separatem PC und kommuniziert per WLAN mit meinem Testgerät, in dem dann nur noch ein ESP32 (wer es nicht kennt: ein WLAN-Modul mit Mikrocontroller) zum Einsatz kommt.

    Ich favorisiere den Plan A.

    Schon aus dem Grund, dass ich das Prinzip dann für andere Projekte recyceln könnte.

    Einer meiner Kunden betreibt eine Art Geisterbahn. Da stecken die Gondeln voller Technik. Wegen der ständigen Erschütterungen ruckelt mit der Zeit alles kaputt, trotz mechanischer Pufferung. Zudem ist es dort (Außeneinsatz!) mal heiß, mal frostig kalt, mal feucht - da kann man kein ausgewachsenes PC-Mainboard einbauen.

    Besser wäre ein möglichst minimalistisches, betont robustes, embedded Platinchen.

    Ich möchte nicht noch einmal mit Arduino zu tun haben und ich will auch kein Linux-Board verbauen.

    Der Traum ist halt, ein total vertrautes System zu verbauen - eine Hardware, auf der ein XP läuft.

    Wenn ich mal für 'nen Serviceeinsatz zum Kunden muss, dann brauche ich dort nur 'ne drahtlos-Tastatur und Maus anzuschließen (den Monitor kriegt man per WLAN ebenfalls weg) und ich kann direkt auf der Zielhardware den Code modifizieren!

    Aber - besser noch - ich muss vielleicht erst gar nicht hin, denn vieles ginge auch aus der Ferne! Update per E-Mail ans Handy des Kunden; der beamt es dann per WLAN drauf.

    Diese Ideen sind noch noch nicht voll ausgereift und nur zum Teil erprobt, aber das ist der grobe Plan.

    Es macht IMHO keinen Sinn, den Code für die Ziel-Hardware auf einer Win10-Kiste zu schreiben und dann bangend darauf zu hoffen, dass das Ergebnis ohne Überraschungen auch beim Kunden läuft!

    Gibt es Probleme, dann bedeutet das für den Kunden nämlich in der Regel Verdienstausfall und das wird er nicht lieben!

    Ich möchte daher partout auf einer möglichst weitgehend identischen Hardware proggen - einem XP-Rechner.

    Da habe ich auch meine direkt verbaute, serielle Schnittstelle, muss mich nicht mit den kuriosen Treiberproblemen der FT232-Chips herum quälen (die können echt garstig sein!) und so weiter.


    Es ist ja schön, wie viele Vorteile Win8, Win10 für den Programmierer und Anwender Daheim haben mögen - mein Szenario ist ein anderes.

    Man kann da natürlich viel diskutieren: "Nimm doch dies, nimm doch das ..." - bei allem, was mir in solchen Diskussionen erfahrungsgemäß vorgeschlagen wird, könnte ich sofort kontern, warum es nicht in Betracht kommt.

    Jeder denkbare Lösungsansatz ist immer ein Kompromiss. Doch in Bezug auf die Zuverlässigkeit bin ich am wenigsten zu Kompromissen bereit.

    Lieber nehme ich es in Kauf, nicht mit der aktuellsten Editor-Version coden zu können, wenn ich dafür am Ende die robusteste Zielhardware, mit dem zuverlässigsten Betriebssystem einsetzen kann, bei der weitest möglich sicher gestellt ist, dass mein Zuhause geschriebener Code 1 zu 1 darauf läuft.

    Und das bedeutet, meiner Meinung nach, dass ich den Code nicht etwa unter Win10 geschrieben und dann zuletzt unter XP bloß kurz getestet habe ("jooo,scheint zu laufen!"). Sondern das bedeutet viel eher, dass ich die komplette Entwicklung unter XP durchgezogen habe und dabei im Laufe der Zeit mit quasi jedem möglichen Problem real konfrontiert wurde.

    - So jedenfalls meine Philosophie.

    Soweit mein Haupt-Argument für XP. Ich habe noch weitere, wenn auch weniger starke. In der Summe sind sie doch wieder sehr stark.

    Aber persönlich will ich in der Tat mittelfristig mal auf Win7 wechseln, wenn auch mit Bauchschmerzen.

  • Den Namen der aktiven (oder aufrufenden) Function ermitteln

    • Code-Jack
    • 26. November 2018 um 13:52

    Zwar noch etwas früh, für eine Veröffentlichung, aber ich habe mal ein Archiv gepackt und auf Zippy hochgeladen (14MB):

    https://www99.zippyshare.com/v/kp8Cj0Vk/file.html

    Das ist soweit alles drin.

    Wenn Du die Datenbank löschst, oder umbenennst, dann wird bei Programmstart eine neue erzeugt. Dann kannst Du auch den Excel-Import sinnvoll testen.

    Die Excel-Tabelle habe ich "kastriert" und sensible Daten daraus entfernt.

    Der per Menü aufrufbare Datei-Download ist noch experimentell und lädt momentan nur eine einzelne Bilddatei ins Scriptverzeichnis herunter. Die Funktion dient später dazu, dass mehrere User ihre Datensätze untereinander tauschen können.

    Die Funktion "Datenbank-Import" habe ich deaktiviert und 'ne MessageBox in den Menüpunkt gepackt. Diese Funktion ist eh nur eine "Altlast" und funktioniert im Moment auch gar nicht (mehr). Sie war mal hoch speziell, die kann außer mir eh kein Mensch gebrauchen.

    Meine normalerweise sehr schöne Code-Formatierung (einschließlich der Kommentare) hat gerade gelitten, durch jüngste, sehr umfangreiche Replace-Aktionen.

    Aber genieße mal die Ausgabe in der Console, wenn Du im Programm herum klickst! :)

  • Den Namen der aktiven (oder aufrufenden) Function ermitteln

    • Code-Jack
    • 26. November 2018 um 11:08

    DANKE!

    Zunächst probierte ich aus Deinem Link die beiden neueren, portablen SciTE-Versionen.

    Diese lassen sich - anders als die ganz aktuelle Vollversion - zwar immerhin starten, kommen aber irgendwie mit meiner Festplattenstruktur nicht klar.

    Der Pfad meines Scripts:

    D:\Mainboardverwaltung\MainboardverwaltungV079.au3

    konnte angeblich nicht geparst werden.

    Also ging ich noch eine Version weiter zurück.

    Die (portable) Version 3.5.4 vom Mar 7 2015 14:59:39 läuft!

    Das wäre diese hier:

    v15.503.1200.0-SciTE4AutoIt3.zip

    In meinen bislang 2025 Codezeilen nörgelte diese Version nach Druck auf "F5" über gefühlt eine Million angebliche Syntaxfehler. Und in (mindestens) zwei Fällen war die Nörgelei sogar berechtigt!

    Nachdem ich das, was ich protestfrei einsehen konnte, behoben hatte, lief mein Programm!

    - Ungewohnterweise jedoch nicht per "F5" gestartet, sondern per Ctrl+F5. Den dazu korrespondierenden Menüpunkt gab es in der Lite-Version gar nicht. Mir im Moment noch unklar, wie das einzuordnen ist und wieso "F5" so viel an meinem schönen Code zu bemängeln hat.

    - Oh, gerade aufgetretene Neuigkeit, jetzt geht es plötzlich auch per F5 ...


    Zitat von Musashi

    Gibt es einen besonderen Grund, warum Du noch so an XP hängst ?

    Solche Probleme müssten doch auch in anderen Bereichen zunehmen.

    Ja, es gibt Gründe dafür. Mehrere.

    Ist aber ziemlich müßig, das zu erklären.

    Und ja, seit erstmals vor knapp zwei Jahren, stoße ich inzwischen zunehmend auf Probleme.

    Der Leidensdruck ist aber noch nicht hoch genug, mich zum sofortigen Handeln zu bewegen. Es ist aber inzwischen anvisiert, mittelfristig mal auf Win7 umzusteigen.

    Eine noch höhere Version kommt mir aber nicht in die Tüte.

  • Den Namen der aktiven (oder aufrufenden) Function ermitteln

    • Code-Jack
    • 25. November 2018 um 22:38
    Zitat von Bitnugger

    eine Hilfe könnte sein, wenn du bei aktiviertem Auto-Indent darauf achtest, dass du keine offenen "Verschachtelungen" hast... z.B. ein If ohne das zugehörige EndIf.

    Das passiert beim Schreiben von neuem Code kurzzeitg natürlich ständig.

    Und da würde ich mir wünschen, dass am Ende einer (bereits korrekt positionierten) If-Zeile der Druck auf "Enter" die nachfolgende Zeile um eine Position nach rechts einrückt.

    (Aber keinesfalls wünsche ich mir, dass die If-Zeile dabei aus ihrer bereits korrekten Position nach links rückt!)

    Perfekt wäre die Auto-Einrückung dann, wenn zudem noch der Befehl zum Schließen von If, oder einer Schleife (also EndIf, Next ...) automatisch anhand des weiter oben stehenden, öffnenden Befehls ausgerichtet werden würde.

    Das mit Deinen Abkürzungen, die eine Code-Vervollständigung bewirken, ist natürlich auch ein komfortabler Weg.

    Damit umgehst Du die "Zickigkeit" des Editors und kommst viel seltener damit in Berührung.

    Wobei das in der Lite-Version wohl nicht geht (habe jetzt nicht danach gegoogelt, finde jedenfalls auf die Schnelle keine Möglichkeit dazu).

    Es ist schick, dass man bei SciTE (zumindest in der Vollversion) so viele mächtige Dinge konfigurieren kann.

    Schade nur, dass er "ab Werk" IMHO recht schräg konfiguriert daher kommt.

    Aber ich will nicht nörgeln, es ist schon großartig, was man hier als Freeware erhält!

    Und wenn ich dann eines Tages auf Win7 umgestiegen bin, so dass auch die Vollversion bei mir läuft, dann nehme ich mir mal die Zeit, mich durch die vielen Konfigurationsmöglichkeitern zu hangeln.

    Im Moment steht bei mir das pure Coden im Vordergrund; mein Programm muss dringend fertig werden und ich komme gar nicht so schnell voran, wie mir ständig gute Ideen kommen.

  • Den Namen der aktiven (oder aufrufenden) Function ermitteln

    • Code-Jack
    • 25. November 2018 um 20:49

    Große Klasse, Musashi!

    Da hast Du Dir ja richtig Arbeit gemacht, um es garantiert idiotensicher zu erklären!

    Die Lösung funktioniert. DANKE DANKE DANKE!

    Was mich wundert, ist wieso Ihr alle damit lebt, wie SciTE sich verhält?

    Ich stoße mich ja dauernd daran:

    1. Am Ende einer horizontal bestens positionierten Zeile drücke ich Enter. Dabei rückt DIESE Zeile ein Stück nach links! :(
    2. Der Cursor steht ganz links und ich drücke Enter, um eine Leerzeile einzufügen. Wieder verrückt die (bestens ausgerichtete) Zeile, in der der Cursor steht (stand).
    3. ... und weitere Späße dieser Art.

    Und besonders ulkig: Es passiert nicht immer, nur fast immer.

    Ich verbrachte bisher fast mehr Zeit damit, diese kruden Auto-Einrückungen wieder von Hand zu korrigieren, als mit dem eigentlichen Eintippern meines Codes. Da mache ich doch lieber gleich alles von Hand!

    Ich programmierte bisher:

    1. Auf dem ATARI, in GFA-Basic (lang ist's her!).
    2. auf dem Psion Serie 3 und später dem Psion Serie 5, jeweils in OPL.
    3. Auf dem PC etwas in Delphi.
    4. Später auf dem PC jede Menge in VB.Net.
    5. Zwischendurch auch etwas in Arduino C.
    6. Reichlich in BASCOM, dem Basic-Dialekt für Atmel AVR-Controller.

    ... ganz frisch bin ich also nicht dabei. Aber noch niemals habe ich einen Codeeditor erlebt, der so ein sonderbares Eigenleben austobt.

    Alle mir sonst bekannten Codeeditoren haben sich für mein Empfinden weitgehend vernünftig verhalten und den Code ziemlich gut eingerückt, so dass höchstens "EndIf", oder Schleifenenden, wie z. B. "Next" von Hand wieder passend hingerückt werden mussten.

    Die Logik vom SciTE erschließt sich mir nicht.

    Vielleicht verhält sich die Vollversion anders?

  • Den Namen der aktiven (oder aufrufenden) Function ermitteln

    • Code-Jack
    • 25. November 2018 um 04:58

    Also das mit der Zeitmessung habe ich aufgegriffen und inzwischen integriert. Vielen Dank für diesen Input!

    Aber irgendwelche Routinen automatisch an meinem Code herummanipulieren zu lassen, geht für mich gar nicht!

    Mich nervt schon extrem diese Autoformatierung in SciTE! Die macht mir weit mehr Arbeit, als dass sie mir irgendeinen Nutzen bringt.

    Ich möchte meinen Code Byte für Byte eigenhändig eintippern und daran nicht die Spur "korrigiert" haben, da bin ich total konservativ.

    Und ich würde mich SEHR über den entscheidenden Tipp freuen, wie ich der Lite-Version von SciTE diese lästige Auto-Einrückung komplett abgewöhnen kann!

  • Den Namen der aktiven (oder aufrufenden) Function ermitteln

    • Code-Jack
    • 25. November 2018 um 01:57

    Sorry, aber ... neee.

    Keine einzige der in diesem Thread vorgestellten Lösungen gefällt mir.

    Da bleibe ich lieber bei meinem bisherigen Weg. Der ist zwar leicht unelegant, aber was soll man machen? AutoIt bietet halt nicht die nötige Funktion, um es besser machen zu können.

    Vielleicht kommt ja mal ein passendes AutoIt-Update ... (die Hoffnung stirbt zuletzt).

    Trotzdem habe ich aus allen Antworten etwas mitgenommen und bedanke mich bei Allen, die zu helfen versucht haben!

    Zum Abschluss hier noch ein direkt lauffähiges Beispiel, nach meinem Prinzip:

    Code
     Global $iLogprint = 2        ;# (0 = Keine Ausgaben in der Console. 1 = Nur Functions rein/raus. 2 = Ausführliche Ausgaben.
    Global $iLogEbene = 0        ;# Diese Variable legt die Einrückung der Textausgaben in der Konsole fest. Wird im Prgrammablauf dynamisch verändert.
    
    output("Dieser Text steht auf der ersten Ebene.")
    output("Auch dieser Text steht auf der ersten Ebene, unmittelbar vor Eintritt in die erste, aufgerufene Function.")
    _Beispiel1()
    _Beispiel2()
    _Beispiel1()
    _Beispiel1()
    _Beispiel2()
    output("Dieser Text steht wieder auf der ersten Ebene, nach Verlassen der aufgerufenen Functions.")
    
    
    ; #############################################################################
    Func _Beispiel1()
      output("_Beispiel1", 1)    ;# Nach jedem Func-Eintritt muss so eine Zeile stehen. Übergabeparameter 1 ==> Einrückung nachfolgender Ausgaben um eine Position nach rechts.
    
      ; Hier Code
      ; Hier Code
      output("Ich bin um eine Position nach rechts eingerückt. Toll was?")    ;# Bei normalen Ausgaben kann der zweite Parameter entfallen!
      output("Ich tue noch etwas in _Beispiel1.")                             ;# Man beachte den höheren Komfort, gegenüber ConsoleWrite("Laberlaber" & @CRLF)
      output("Es gibt ja soo viel zu tun, in  _Beispiel11 ...")               ;# Alle drei Zeilen sind um eine Position nach rechts eingerückt.
      ; Hier Code
      ; Hier Code
    
      output("_Beispiel1", -1)   ;# Vor jedem EndFunc muss so eine Zeile stehen. Übergabeparameter -1 ==> Linksrückung nachfolgender Ausgaben um eine Position.
    EndFunc  ;==> Beispiel 1
    ; #############################################################################
    Func _Beispiel2()
      output("_Beispiel2", 1)
    
      ; Hier Code
      ; Hier Code
      output("Ich tue gerade was in _Beispiel2. Aber jetzt geht es eine Ebene tiefer!")
      _Unterfunktion()               ;# Ruft die Unterfunktion auf
      output("Ich tue wieder was in _Beispiel2.")
      ; Hier Code
      ; Hier Code
    
      output("_Beispiel2", -1)
    EndFunc  ;==> Beispiel 2
    ; #############################################################################
    Func _Unterfunktion()
      output("_Unterfunktion", 1)
    
      ; Hier Code
      ; Hier Code
      output("Ich tue gerade was in _Unterfunktion. Diese Textausgabe ist um noch eine weitere Ebene noch rechts gerückt, gegenüber der aufrufenden Function.")
      output("Gleich geht es noch eine Ebene tiefer!")
      _DeepDeepFunction()            ;# Ruft die Unter-Unterfunktion auf
      output("Wir sind wieder eine Ebene weiter links und befinden uns gerade in _Unterfunktion")
      ; Hier Code
      ; Hier Code
    
      output("_Unterfunktion", -1)
    EndFunc  ;==> Unterfunktion
    ; #############################################################################
    Func _DeepDeepFunction()
      output("_DeepDeepFunction", 1)
    
      ; Hier Code
      ; Hier Code
      output("Ich tue gerade was in der tiefen, tiefen Function und stehe noch weiter rechts.")
      output("Es ist ja sooo tief hier!")
      ; Hier Code
      ; Hier Code
    
      output("_DeepDeepFunktion", -1)
    EndFunc  ;==> _DeepDeepFunktion
    ; #############################################################################
    Func output($sMessage, $iParam = 0)
       ;# Dient als besserer Ersatz für Consolewrite(), zwecks strukturierter Ausgabe des Programmablaufs.
       ;# Erfordernis: Global $iLogEbene (Optional. 1 = Einrückung nachfolgender outputs um eine Position nach rechts. -1 = Einrückung um eine Position nach links.)
       ;# ............ Global $iLogprint (0 = Keine Ausgabe. 1 = Nur Functions rein/raus. 2 = Ausführliche Ausgaben.
       ;# Übergabeparamteter "$sMessage": Der in der Console auszugebende Text.
       ;# Übergabeparameter "$iParam" (optional): Information über die Einrückung. 1 = Eine Position weiter rechts einrücken. -1 = Nach links rücken. 0 = Einrückung nicht verändern.
    
      If $iLogprint = 0 then
         Return
      EndIf
    
      If $iLogprint = 1 And $iParam = 0 Then
         Return
      EndIf
    
      Local $sEA
      Local $sLeerzeile
      Local $sTrailer
    
      If $iParam = 1 Then
        $sEA &= "#EINTRITT# "
      EndIf
    
      If $iParam = -1 Then
        $sEA &= "#AUSTRITT# "
        $iLogEbene -= 1
      EndIf
    
      For $i = 0 to $iLogEbene - 1
        $sTrailer &= ".   "
      Next
    
      ConsoleWrite($sTrailer & $sEA & $sMessage & @CRLF)
    
      If $iParam = 1 Then
         $iLogEbene += 1
      EndIf
    
      If $iParam = -1 Then
         ConsoleWrite($sTrailer & @CRLF)
      EndIf
    
      ; Ideen für spätere Erweiterungen:
      ; - Zeitdifferenz mit ausgeben, beim Austritt aus einer Function.
      ; - Zusätzlicher Übergabeparameter, der die Console-Ausgaben auf eine bestimmte Function beschränkt.
    EndFunc  ;==> output()
    ; #############################################################################
    Alles anzeigen

    Gegenüber meinen vorherigen Schnippseln habe ich die Ausgabe simplifiziert, ohne die vielen ...

    ;---------------\

    Blah

    Blahblah

    ;---------------/

    Solche Klammer-Konstrukte verwende ich im Quellcodes sonst recht häufig, als Ergänzung zu #Region. Aber ich habe inzwischen mit der formatierten Konselen-Ausgabe viel experimentiert und diese komische Einklammerung zumindest dort für verzichtbar befunden.

    Mein Datenbank-Programm schmeißt sogar regelrecht meterlange Logs aus und für mein Empfinden sind die glasklar zu lesen.

    Diese Art, Meldungen auszugeben, hilft mir sehr dabei, mein Programm aufgeräumt zu halten und zudem eine konsistente Benennung der Functions zu realisieren.

    Wenn man die Globale Variable $iLogprint auf 1 setzt, dann beschränkt sich die Ausgabe auf die reinen Ein-/Austritte der Functions. So erhält man ruckzuck einen kompakten Überblick über die Struktur der ganzen Aufrufe.

    Weil man die Ausgabe auch auf einen Schlag komplett ausschalten kann (per $iLogprint = 0), können die ganzen Ausgabebefehle einfach im Code stehen bleiben.

    Bei ConsoleWrite() hingegegen, würde man diese Zeilen wohl auskommentieren, wenn sie nicht mehr benötigt werden. Erstens um Zeit zusparen, zweitens um überflüssige Ausgaben zu unterdrücken.

    Aber bei meinem strukturierten output() ist das Auskommentieren IHMO nicht nötig, denn da gibt es keine zu späterem Zeitpunkt "überflüssigen", bloß verwirrenden Ausgaben, da alles in eine klare Struktur eingebettet ist.

    Und wie gesagt: Man kann die Ausgabe der Meldungen global abschalten (oder auch einschränken).

    Später baue ich noch etwas mehr Luxus ein. Zeitmessung und so. Aber im Moment bin ich zufrieden.

    Thema erledigt.

  • Den Namen der aktiven (oder aufrufenden) Function ermitteln

    • Code-Jack
    • 23. November 2018 um 22:25
    Zitat von Tuxedo

    Ich habs jetzt nur überflogen, aber

    Das merkt man, Tuxedo! :Face:

    Genau das, was ich bislang praktisch genau so mache und nun durch eine bessere Alternative ersetzt haben möchte, schlägst Du mir vor.


    Bittnuggers Vorschlag ist eine kompliziertere Variante, die hier einen kleinen Vorteil und da einen kleinen Nachteil mit sich bringt.

    Noch einmal:

    Der folgende Code bildet das Grundgerüst, wie jede Function meines Programm aufgebaut ist:

    C
    Func _User_Eingabefelder_leeren()
      output("_User_Eingabefelder_leeren", 1)
    
      ; Hier Code
      ; Hier Code
      ; Hier Code
    
      output("_User_Eingabefelder_leeren", -1)
    EndFunc ;==> _User_Eingabefelder_leeren()

    - Das ist simpel (sogar regelrecht primitiv) und funzt bestens.

    Was mich daran aber stört:

    Ich habe im obigen Code VIER MAL den Namen der Function stehen! Pure Redundanz!

    Ohne den auskommentierten Bereich hinter EndFunc steht der Name noch immer drei Mal im Code.

    Und es ist fehlerträchtig, weil ich für jede meiner ca. 40 Functions die jeweils zwei Zeilen mit "output()" von Hand anpassen muss.

    Es wäre viel schicker, wenn all die vielen Output-Zeilen jeweils identisch sein könnten, quer durch das ganze Programm.

    Was dazu geschehen müsste: Irgendein Zauber-Befehl müsste den Namen der Funktion, aus der heraus er aufgerufen wurde, ganz von allein ermitteln.

    Das würde gehen, wenn beim Erzeugen einer Function sozusagen ein Handle zurückgegeben werden würde, über das man an deren Namen heran käme.

    Mir ist aber kein solcher Weg bekannt.

  • Den Namen der aktiven (oder aufrufenden) Function ermitteln

    • Code-Jack
    • 23. November 2018 um 21:16

    Musashi hat's erkannt:

    Die "Komplettversion" von SciTE läuft auf meiner Kiste nicht, darum arbeite ich bloß mit derabgespeckten Version, die zusammen mit AutoIt installiert wird.

    Ja, ich muss wohl langsam mal auf Win7 umsteigen ... :-/

    Trotzdem wäre es mein Wunsch, dass mein Programm auch unter Win XP läuft.

    Die Frage aus dem Startposting bleibt also bestehen, unabhängig von den massig erweiterten Features des SciTE-Editors.

  • Den Namen der aktiven (oder aufrufenden) Function ermitteln

    • Code-Jack
    • 23. November 2018 um 18:31

    Moment, nix Hotkey.

    Mein Programm tut dies, tut das, tut jenes ... und das soll mitgeloggt werden.

    Jedes Mal, wenn eine Function betreten/verlassen wird, soll die Info über dieses Ereignis in die Logdatei einfließen.

    Unabhängig davon, ob der User das angestupst hat, oder nicht.

    Die Frage ist also : Wie kann eine Function ihren eigenen Namen ermitteln?

    Die alternative Frage : Wie kann eine aufgerufene Function den Namen der sie aufrufenden "Über-Function" ermitteln?

    Gegenwärtig sieht der Inhalt meiner Console so aus (gut!):

    Code
    >"D:\Programme\AutoIt3\SciTE-AutoIt3Installer\..\autoit3.exe" /ErrorStdOut "H:\Notebook-Reparatur\Mainboardverwaltung\Mainboardverwaltung V0.75b.au3"    
    GDIPlus starten
    # _ReadIniFile #Eintritt---\
    # _ReadIniFile #Austritt---/
    # _SQLite_Start #Eintritt---\
       # _SQLite_CountRows #Eintritt---\
       .   Übergabeparameter $_sTable = Mainboardverwaltung
       .   Übergabeparameter $sSuchbefehl: 
       .   $sSQLiteBefehl = SELECT count(*) FROM Mainboardverwaltung;
       .   Rückgabewert: 1451
       # _SQLite_CountRows #Austritt---/
    # _SQLite_Start #Austritt---/
    # _ListViewFill #Eintritt---\
       Übergabeparameter: SELECT * FROM Mainboardverwaltung ORDER BY F2, F3, F4, F6, F5;
       _ListViewFill korrigiert den String zu folgendem SQLiteBefehl: SELECT * FROM Mainboardverwaltung ORDER BY F2, F3, F4, F6, F5;
       Farben im Listview setzen...
    # _ListViewFill #Austritt---/
    Hauptschleife betreten
    User-Aktion: 'LiestView sortieren'
    
    ------------------------------------------------------------------------------\
    ###_User_Suche #Eintritt
       # _Suche #Eintritt---\
       .   $iFeldnummer=2
       .   $sSQLiteBefehl = SELECT * From Mainboardverwaltung WHERE F2 LIKE 'As%';
       .   # _ListViewFill #Eintritt---\
       .   .   Übergabeparameter: SELECT * From Mainboardverwaltung WHERE F2 LIKE 'As%';
       .   .   _ListViewFill korrigiert den String zu folgendem SQLiteBefehl: SELECT * From Mainboardverwaltung WHERE F2 LIKE 'As%';
       .   .   Farben im Listview setzen...
       .   # _ListViewFill #Austritt---/
       # _Suche #Austritt---/
    ###_User_Suche #Austritt
    ------------------------------------------------------------------------------/
    
    ------------------------------------------------------------------------------\
    ###_User_Suche #Eintritt
       # _Suche #Eintritt---\
       .   $iFeldnummer=2
       .   $sSQLiteBefehl = SELECT * From Mainboardverwaltung WHERE F2 LIKE 'Ac%';
       .   # _ListViewFill #Eintritt---\
       .   .   Übergabeparameter: SELECT * From Mainboardverwaltung WHERE F2 LIKE 'Ac%';
       .   .   _ListViewFill korrigiert den String zu folgendem SQLiteBefehl: SELECT * From Mainboardverwaltung WHERE F2 LIKE 'Ac%';
       .   .   Farben im Listview setzen...
       .   # _ListViewFill #Austritt---/
       # _Suche #Austritt---/
    ###_User_Suche #Austritt
    ------------------------------------------------------------------------------/
    
    ------------------------------------------------------------------------------\
    ###_User_Datensatz_bearbeiten #Eintritt
       # _ListViewEntryToDatentaxi #Eintritt---\
       .   $iInputIndex = 2
       .   # _Eingabefelder_leeren #Eintritt---\
       .   # _Eingabefelder_leeren #Austritt---/
       .   Selektierter Eintrag: {76F6CFA0-1B48-4AE5-8BA2-F872A0BC924B}
       # _ListViewEntryToDatentaxi #Austritt---/
       Bearbeitet wird folgender Datensatz: {76F6CFA0-1B48-4AE5-8BA2-F872A0BC924B}
       # _SQL2Datentaxi #Eintritt---\
       .   Übergabeparameter: {76F6CFA0-1B48-4AE5-8BA2-F872A0BC924B}
       .   SQLite-Befehl für Query: SELECT * FROM Mainboardverwaltung WHERE `ID`='{76F6CFA0-1B48-4AE5-8BA2-F872A0BC924B}';
       .   $aDatentaxi[0] = {76F6CFA0-1B48-4AE5-8BA2-F872A0BC924B}
       # _SQL2Datentaxi #Austritt---/
       # _Datentaxi2Editboxes #Eintritt---\
       .   $i = 33
       # _Datentaxi2Editboxes #Austritt---/
    ###_User_Datensatz_bearbeiten #Austritt
    ------------------------------------------------------------------------------/
    
    ------------------------------------------------------------------------------\
    ###_User_DsUpdate #Eintritt
       # _GatherDatasFromInputs #Eintritt---\
       .   $aDatentaxi[0] = {76F6CFA0-1B48-4AE5-8BA2-F872A0BC924B}
       # _GatherDatasFromInputs #Austritt---/
       # _SQLite_DS_Update #Eintritt---\
       .   $aDatentaxi[0] = {76F6CFA0-1B48-4AE5-8BA2-F872A0BC924B}
       .   SQLiete-Befehl: UPDATE Mainboardverwaltung SET F1 = '#00002',F2 = 'Acer Zwei äöüßÄÖÜ',F3 = 'Aspire 1200',F4 = 'Compal LA-1281',F5 = '1.0',F6 = 'CY23',F7 = 'SST39VF040 (3V)',F8 = 'U7',F9 = 'SST',F10 = 'N/A',F11 = 'N/A',F12 = 'N/A',F13 = 'PC87570-176',F14 = 'National Semiconductor',F15 = 'U21',F16 = '23,67,108,161',F17 = 'Nein',F18 = '',F19 = '',F20 = 'N/A',F21 = 'N/A',F22 = 'N/A',F23 = '',F24 = '',F25 = '',F26 = 'http://www.s-manuals.com/pdf/motherboard/compal/compal_la-1281_r1.0_schematics.pdf',F27 = '',F28 = 'Nein',F29 = '',F30 = '',F31 = '',F32 = ''WHERE ID = '{76F6CFA0-1B48-4AE5-8BA2-F872A0BC924B}';
       # _SQLite_DS_Update #Austritt---/
       # _SQL2Datentaxi #Eintritt---\
       .   Übergabeparameter: {76F6CFA0-1B48-4AE5-8BA2-F872A0BC924B}
       .   SQLite-Befehl für Query: SELECT * FROM Mainboardverwaltung WHERE `ID`='{76F6CFA0-1B48-4AE5-8BA2-F872A0BC924B}';
       .   $aDatentaxi[0] = {76F6CFA0-1B48-4AE5-8BA2-F872A0BC924B}
       # _SQL2Datentaxi #Austritt---/
       # _ListViewEntryUpdate #Eintritt---\
       .   Inputindex in ListViewEntryUpdate = 2
       # _ListViewEntryUpdate #Austritt---/
       $iInputIndex in DSUpdate= 2
    ###_User_DsUpdate #Austritt
    ------------------------------------------------------------------------------/
    
    ------------------------------------------------------------------------------\
    ###_User_Datensatz_bearbeiten #Eintritt
       # _ListViewEntryToDatentaxi #Eintritt---\
       .   $iInputIndex = 1
       .   # _Eingabefelder_leeren #Eintritt---\
       .   # _Eingabefelder_leeren #Austritt---/
       .   Selektierter Eintrag: {9A7D2422-863D-4509-B8AA-2D3188E0068E}
       # _ListViewEntryToDatentaxi #Austritt---/
       Bearbeitet wird folgender Datensatz: {9A7D2422-863D-4509-B8AA-2D3188E0068E}
       # _SQL2Datentaxi #Eintritt---\
       .   Übergabeparameter: {9A7D2422-863D-4509-B8AA-2D3188E0068E}
       .   SQLite-Befehl für Query: SELECT * FROM Mainboardverwaltung WHERE `ID`='{9A7D2422-863D-4509-B8AA-2D3188E0068E}';
       .   $aDatentaxi[0] = {9A7D2422-863D-4509-B8AA-2D3188E0068E}
       # _SQL2Datentaxi #Austritt---/
       # _Datentaxi2Editboxes #Eintritt---\
       .   $i = 33
       # _Datentaxi2Editboxes #Austritt---/
    ###_User_Datensatz_bearbeiten #Austritt
    ------------------------------------------------------------------------------/
    
    ------------------------------------------------------------------------------\
    ###_User_Datensatz_Delete #Eintritt
       # _SQLiteDeleteDS #Eintritt---\
       .   Übergabeparameter: {9A7D2422-863D-4509-B8AA-2D3188E0068E}
       .   SQLite-Befehl für Exec: DELETE From Mainboardverwaltung WHERE ID = '{9A7D2422-863D-4509-B8AA-2D3188E0068E}';
       # _SQLiteDeleteDS #Austritt---/
       # _SQLite_CountRows #Eintritt---\
       .   Übergabeparameter $_sTable = Mainboardverwaltung
       .   Übergabeparameter $sSuchbefehl: 
       .   $sSQLiteBefehl = SELECT count(*) FROM Mainboardverwaltung;
       .   Rückgabewert: 1450
       # _SQLite_CountRows #Austritt---/
    ###_User_Datensatz_Delete #Austritt
    ------------------------------------------------------------------------------/
    
    ------------------------------------------------------------------------------\
    ###_User_Exit #Eintritt
       # _Exit #Eintritt---\
       # _Exit #Austritt---/
    >Exit code: 0    Time: 256.4
    Alles anzeigen

    Das gefällt mir schon prima,aber am Anfang und Ende einer jeden Function (mit Ausnahme der extrem häufig aufgerufenen), habe ich jeweils eine "Output-Zeile" stehen, die mir meinen Ersatz für ConsoleWrite() aufruft:

    Code
    Func _User_Eingabefelder_leeren()           ;# Alle Functions, die vom User himself (und nur vom User!) aufgerufen werden, beginnen im Namen mit "_USER_"
      output("_User_Eingabefelder_leeren", 1)
      _Eingabefelder_leeren()                   ;# Ruft die eigentliche Function auf (die auch programmintern zum Einsatz kommt). 
      output("_User_Eingabefelder_leeren", -1)
    EndFunc  ;==> _User_Eingabefelder_leeren()

    Obige Function ist natürlich betont minimalistisch. Aber sie verdeutlich das Prinzip.

    Jeweils direkt hinter "Func " kommt eine Zeile mit output().

    (Der zweite Parameter sorgt übrigens für die Einrückung aller folgenden Outputs um eine Position nach rechts.)

    Und vor jedem "EndFunc" kommt wieder so eine Outputzeile.

    (Der zweite Parameter "-1" macht die vorherige Einrückung wieder rückgängig.)

    Will ich zwischendurch eine Debugmeldung ausgeben, dann schreibe ich statt:

    ConsoleWrite("Laberlaber" & @CRLF)

    einfach nur:

    output("Laberlaber")

    (Hier kann ich den zweiten Parameter weg lassen, die Zeile wird automatisch korrekt eingerückt.)

    Ich erhalte also, mit weniger Schreibarbeit als bei ConsoleWrite(), einen schick formatierten Log in der Konsole (oder bei Bedarf auch in einer Datei).

    Aber ich muss halt, innerhalb einer jeder einzelnen Function, in zweien dieser Output-Zeilen den Namen der Function per Hand eintippern.

    Wäre schöner, wenn diese Zwei Zeilen jeweils ungefähr so aussehen könnten:

    output(@FunctionName, 1)

    output(@FunctionName, -1)

  • Den Namen der aktiven (oder aufrufenden) Function ermitteln

    • Code-Jack
    • 23. November 2018 um 17:25

    Trotz RTFM und Google nix gefunden:

    Ich möchte, für eine formatierte Debug-Ausgabe, den Namen der gerade aktiven Function ermitteln.

    Wie könnte das gehen?

    Alternativ:

    Ist es innerhalb einer Function möglich, zu ermitteln, von welcher "höheren Function" sie aufgerufen wurde?

    Was das soll?

    - Ich habe in meinem Programmcode die mir stets lästigen Debug-Ausgaben per ConsoleWrite() durch eine eigene Lösung ersetzt, die erstens simpler einzuitippen ist (z. B. kein " & @CRLF" mehr erforderlich) und die darüber hinaus den Programmablauf automatisch schick strukturiert dokumentiert.

    Es wäre auch kein Problem, die Ausgabe in eine Logdatei umzuleiten, statt in die Console.

    Das klappt soweit alles prima, nur muss ich beim Betreten/Verlassen einer jeden Func deren Namen an meine Log-Routine übergeben, was ich bisher "zu Fuß" erledige.

    Es wäre bequemer und zudem für die Suche im Quelltext vorteilhafter, wenn ich dort jedes Mal eine stets identische Codezeile reinpacken könnte, die den Namen selbst ermittelt.

  • ListView füllen und ProgressBar

    • Code-Jack
    • 21. November 2018 um 21:11

    Was mein reales Programm betrifft:

    Ich glaube sogar, dass es möglich sein müsste, noch zwei weitere Sekunden zu sparen.

    Grund: Ich hatte ja bereits in Posting Nr. 16 festgestellt, dass es zwei Sekunden länger dauert, die Datenbank per _SQLite_GetTable2d in ein 2D-Array einzulesen, gegenüber einem _SQLite_Query(), gefolgt von einer Schleife mit zeilenweisem Einlesen per _SQLite_FetchData() - was erprobterweise quasi in Nullzeit geschieht.

    Beim Versuch, das umzusetzen, habe ich heute leider richtig Schrott fabriziert. Aber wenn ich mich da erfolgreich durchgebissen habe, dann sollten zwischen F5 in SciTE und dem voll geladenen Programm, mit prall gefüllter und gefärbter ListView, nur noch schlanke drei Sekunden vergehen!

    Da ich die gleiche Routine auch für meine Suchfunktion verwende, würde der Vorteil also nicht nur den Programmstart betreffen, sonden auch den ständigen Gebrauch des Programms.

    Wenn das erledigt ist, dann ersetze ich außerdem noch das krötig lahme Sortieren über den Spaltenheader durch selfmade SQL-Sortierung, samt neuem Füllen der Listview. Dann ist alles kopmplett durch und durch richtig husch.

  • Den Background einzelner ListView Elemente ändern

    • Code-Jack
    • 21. November 2018 um 16:29

    DasIch,

    wir hatten das Thema gerade ausgiebig im Thread:

    ListView füllen und ProgressBar

    Der geschätzte Bitnugger hat dort im Posting Nr. 9 dieses Juwel verlinkt:

    https://www.autoitscript.com/forum/topic/18…ws-udf-version/

    Scrolle dort mal ein gutes Stück herunter und bestaune die Beispiele!

    Schier grenzenlose Freiheit, oder? Und schnell!

    Bitnugger hat in Posting Nr. 18 auch ein direkt lauffähiges Script gepostet (nur ein Pfad bei "Include" muss eventuell angepasst werden).

  • ListView füllen und ProgressBar

    • Code-Jack
    • 21. November 2018 um 00:53

    Bitnugger, Du bist der König unter den Königen!

    Ich dachte, der Warp-Antrieb wäre noch gar nicht erfunden, doch ich irrte!

    Dieses ListViewColorsFonts.au3 läuft ganz definitiv mit Warp!

    Übrigens weiß ich nicht, wieso Du so schlechte Werte in der Konsole hast?

    Auf meinem alten Bürorechner mit OnBoard-Grafik (also wahrlich kein Rechenmosnter) bekomme ich mit Deinem Script folgende Ausgabe:

    Code
    ! Array $aLV[1600][32] erzeugen...         benoetigte Zeit: 0 Sekunden
    ! Breite/Ausrichtung der Items anpassen... benoetigte Zeit: 0 Sekunden
    ! Array im Listview anzeigen...            benoetigte Zeit: 1 Sekunden
    ! Farben im Listview setzen...             benoetigte Zeit: 1 Sekunden

    In hoffnungsvoller Erregung habe ich den Code dann mal in mein Programm eingefrickelt.

    - Ein Traum!!!

    Keine 5 Sekunden nach dem Drücken von F5 im Editor, steht die gesamte GUI da, mit gefüllter und gefärbter ListView!

    Davon verheize ich knapp eine Sekunde anderweitig und rund zwei Sekunden mit dem Füllen des 2D-Arrays aus der SQLite-Datenbank.

    Das eigentliche Füllen und Färben der ListView geschieht dann mit einem Extrakt aus Deinem Code, der seinen Job in nur rund zwei Sekunden erledigt.

    GROßARTIG!!! :thumbup: 

    (Schade, es gibt hier keinen Kotau-Smiley)

  • ListView füllen und ProgressBar

    • Code-Jack
    • 20. November 2018 um 19:07

    Ich habe es jetzt also mal real ausprobiert.

    Und das Ergebnis ist übel!

    Dieser Code (basierend auf den Vorschlägen von autobert), ist krötig lahm:

    C
      Local $aResult[$iTreffer][$iFeldNrMax + 1], $iRows, $iColumns, $iRval                            ;# Ein Array kreieren, in das die Datensätze eingelesen werden.
      ConsoleWrite("Eins" & @CRLF)
      $iRval = _SQLite_GetTable2d(-1, $sSQLiteBefehl, $aResult, $iRows, $iColumns)                     ;# Die SQLite-Datensätze ins Array einlesen.
      ConsoleWrite("Zwei" & @CRLF)
      if $iRval = $SQLITE_OK Then                                                                      ;# Wenn das geklappt hat ...
        For $i = 1 To $iRows                                                                           ;# ... in einer Schleife pro Datenzeile (außer Null) ...
          GUICtrlCreateListViewItem(_ArrayToString($aResult, '|', $i, $i), $idListView)                ;# ... je einen ListView-Eintrag kreieren ...
          GUICtrlSetBkColor(-1, 0xF0E68C) ;# (0xF9F9F9) helles Grau (0xB9D1EA) helles blau (0xF0E68C)  ;# ... und dort farblich hübsch herrichten ...
        Next
      Else
        MsgBox($MB_OK, "Fehler:", "Die SQLite-Datenbank konnte nicht ins Array kopiert werden.")       ;# Falls es aber nicht geklappt haben sollte, User informieren.
      EndIf
      ConsoleWrite("Drei" & @CRLF)
    Alles anzeigen

    Obiger Code ist doppelt so langsam wie mein ursprünglicher Code.

    Hier ist er noch einmal:

    C
      Local $i = 0
      Local $iProzentwert = 0
      Local $iLast = 0
      ConsoleWrite("Eins" & @CRLF)
      _SQLite_Query(-1, $sSQLiteBefehl, $hQuery)                                                        ;# Die SQLite-Suchfunktion parametrieren ...
      ConsoleWrite("Zwei" & @CRLF)
      While _SQLite_FetchData($hQuery, $aDatentaxi, False, False) = $SQLITE_OK                          ;# ... anschließend fröhlich Suchtreffer ansammeln ...
        GUICtrlCreateListViewItem(_ArrayToString($aDatentaxi, '|', 1, 21), $idListView)                 ;# ... und diese sogleich in die ListView schreiben ...
        GUICtrlSetBkColor(-1, 0xF0E68C) ;# (0xF9F9F9) helles Grau (0xB9D1EA) helles blau (0xF0E68C)     ;# ... und dort hübsch herrichten ...
        ;--- Berechnungen für die Fortschrittsanzeige ---\
        $i += 1
        $iProzentwert = Round(100 * $i / $iTreffer)
        if $i <> $iLast then
          $iLast = $i
          GUICtrlSetData($idProgressbar1, $iProzentwert)                                                  ;# ... außerdem die Fortschrittsanzeige aktualisieren ...
        EndIf
        ;--- Berechnungen für die Fortschrittsanzeige ---/
      WEnd                                                                                              ;# ... bis nichts mehr gefunden wird.
      ConsoleWrite("Drei" & @CRLF)
    Alles anzeigen

    Trotz der Fortschrittsanzeige, läuft mein alter Code also doppelt so schnell.

    Drei Meldungen gebe ich jeweils in der Console aus, um zu sehen, wo die Zeit verschwendet wird.

    Entgegen autoberts erstem Satz in Posting 7, ist mein ursprüngliches _SQLite_Query und _SQLite_FetchData bedeutend schneller, als _SQLite_GetTable2d.

    In meinem alten Code kommen die Meldungen "Eins" und "Zwei" unmittelbar nacheinander.

    Nicht so bei autoberts _SQLite_GetTable2d. Da dauert es so ca. 3 Sekunden.

    Der wahre Zeitfresser sitzt aber bei beiden Codes zwischen den Konsolemeldungen "Zwei" und "Drei". Also in der Schleife.

    Der Code nach autoberts Vorschlag verheizt hier klägliche 25 Sekunden.

    Mein alter Code dagegen nur 12 Sekunden, trotz der Zusatz-Aufgabe mit der Progressbar.

    In beiden Fällen setze ich _ArrayToString ein. Der Unterschied ist aber, dass dieser Befehl bei meinem alten Code nur ein 1D-Array zu einem String zusammen datschen muss, wohingegen im auf autoberts Vorschlag basierten Code die Felder jeweils aus dem 2D-Array zusammengeklaubt werden müssen.

    Das ist aber nicht der Zeitfresser (was mich wundert). Ich habe dann nämlich mal eine Kombination beider Codes versucht:

    Zuerst fülle ich mein 1D-Array "Datentaxi" (mit nur einer Zeile), um dann im Code gemäß autoberts Vorschlag nur noch dieses 1D-Array behandeln zu müssen, bei jedem Schleifendurchlauf.

    Ist für Testzwecke ja egal, dass es stets die selbe Zeile ist.

    Und das Ergebnis ist so lahm, wie beim 2D-Array, was mich nun total wundert!

    Hier im Detail:

    C
      _SQLite_Query(-1, $sSQLiteBefehl, $hQuery)                                                        ;# Die SQLite-Suchfunktion parametrieren ...
      _SQLite_FetchData($hQuery, $aDatentaxi, False, False); = $SQLITE_OK                          ;# ... anschließend fröhlich Suchtreffer ansammeln ...
    
      Local $aResult[$iTreffer][$iFeldNrMax + 1], $iRows, $iColumns, $iRval                            ;# Ein Array kreieren, in das die Datensätze eingelesen werden.
      ConsoleWrite("Eins" & @CRLF)
      $iRval = _SQLite_GetTable2d(-1, $sSQLiteBefehl, $aResult, $iRows, $iColumns)                     ;# Die SQLite-Datensätze ins Array einlesen.
      ConsoleWrite("Zwei" & @CRLF)
      if $iRval = $SQLITE_OK Then                                                                      ;# Wenn das geklappt hat ...
        For $i = 1 To $iRows                                                                           ;# ... in einer Schleife pro Datenzeile (außer Null) ...
          ;GUICtrlCreateListViewItem(_ArrayToString($aResult, '|', $i, $i), $idListView)                ;# ... je einen ListView-Eintrag kreieren ...
          GUICtrlCreateListViewItem(_ArrayToString($aDatentaxi, '|', 1, 21), $idListView)              ;# ... und diese sogleich in die ListView schreiben ...
          GUICtrlSetBkColor(-1, 0xF0E68C) ;# (0xF9F9F9) helles Grau (0xB9D1EA) helles blau (0xF0E68C)  ;# ... und dort farblich hübsch herrichten ...
        Next
      Else
        MsgBox($MB_OK, "Fehler:", "Die SQLite-Datenbank konnte nicht ins Array kopiert werden.")       ;# Falls es aber nicht geklappt haben sollte, User informieren.
      EndIf
      ConsoleWrite("Drei" & @CRLF)
    Alles anzeigen

    Zwischen den Konsole-Meldungen Zwei und Drei liegen rund 30 Sekunden (nie exakt gemessen, einfach nach Gefühl gezählt).

    Mir unerklärlich, was im letzten Code der Zeitfresser ist, gegenüber meinem alten Code?


    Was wirklich flott ging, das war der Weg, das komplette 2D-Array direkt in die ListView zu schieben. Nur haperte es da an der alternierenden Einfärbung der Zeilen.

    Jetzt bleibt mir noch zu hoffen, dass Bitnuggers "alternative Möglichkeit" (am Ende von Posting Nr. 9) was reißt.

    Sehr optimistisch bin ich jetzt aber nicht mehr.

Spenden

Jeder Euro hilft uns, Euch zu helfen.

Download

AutoIt Tutorial
AutoIt Buch
Onlinehilfe
AutoIt Entwickler
  1. Datenschutzerklärung
  2. Impressum
  3. Shoutbox-Archiv
Community-Software: WoltLab Suite™