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. AspirinJunkie

Beiträge von AspirinJunkie

  • Schleifenabbruch nur über HotKey möglich

    • AspirinJunkie
    • 15. Mai 2025 um 08:02

    Ja das ist wirklich etwas tricky in diesem Fall.
    Klären wir erstmal das Warum:
    Wenn man einen Button drückt, dann löst dieser ein bestimmtes Event aus und dieses kommt in eine Art Warteschlange.
    Wenn man dann GuiGetMsg() aufruft, liest es diese Warteschlange aus und gibt das Event zurück und mit diesem kann man dann entsprechend darauf reagieren.

    Bei dir passiert nun folgendes: Du drückst den Start-Menü-Button, das Event $gm_Menu_run wird abgefeuert und in deiner Message-Loop wird nun GUIGetMsg() aufgerufen.
    Dieses findet nun das Event $gm_Menu_run und gibt es zurück. Darauf reagierst du in deinem Code damit, dass die Funktion _startRoutine() aufgerufen wird.

    Nun befinden wir uns in der Funktion _startRoutine().
    Und da wir uns in einer Endlosschleife befinden, kommen wir da erstmal nicht heraus.
    Wenn man nun den Stopp-Button drückt, dann wird das Event $gB_Button1 gefeuert.
    Das Problem: Niemand schaut nun nach ob Events in der Warteschlange stehen, denn GuiGetMsg() wird nicht mehr aufgerufen.
    Das würde erst passieren wenn die Funktion _startRoutine() beendet wird, denn dann befinden wir uns wieder in der Message-Loop.

    HotkeySet macht das hingegen anders. Es setzt nicht das Event in die Schlange sondern reagiert direkt darauf.
    Daher funktioniert das und die GUI-Events nicht.

    Es gibt (das sind zumindest die Variante, welche mir einfallen) da nun 2 Möglichkeiten:

    1. GuiGetMsg() muss auch in der _startRoutine()-Funktion kontinuierlich abgefragt werden.
    2. Auf den GuiOnEvent()-Modus wechseln. Das klingt erstmal einleuchtender, hat aber auch einen Haken - dazu später mehr.

    Variante 1 - GuiGetMsg() in der _startRoutine():

    Das GuiGetMsg() muss in die Schleife von startRoutine() mit hinein. Da die Events aber nur eine bestimmte Lebenszeit in der Schlange haben, kann es passieren, dass wenn sie erst nach dem 1s-Sleep aufgerufen wird, dass das Event dann schon wieder weg ist.
    Daher muss GuiGetMsg() auch während dieser Sekunde permanent abgefragt werden.

    Ich habe das mal folgendermaßen umgesetzt:

    AutoIt
    #include <GUIConstants.au3>
    
    HotKeySet('{F10}','_startRoutine')
    HotKeySet('{F11}','_stopRoutine')
    
    Global Const $GUI = GUICreate('Test',300,150, -1, -1, $WS_SYSMENU,$WS_EX_TOPMOST)
    Global $gm_Menu = GUICtrlCreateMenu("Steuerung")
    Global $gm_Menu_run =  GUICtrlCreateMenuItem("Programm starten",$gm_Menu)
    Global $gm_Menu_stop =  GUICtrlCreateMenuItem("Programm stoppen",$gm_Menu)
    GUICtrlCreateMenuItem("", $gm_Menu, 3)
    Global $gm_Menu_exit =  GUICtrlCreateMenuItem("Beenden",$gm_Menu)
    Global $gB_Button1 = GUICtrlCreateButton ("Stopp", 10, 50,60,30)
    Global $gL_Label1 = GUICtrlCreateLabel("Zeit",10,10,100,20,1,5)
    Global $stop = false
    GUISetState(@SW_SHOW, $GUI)
    While 1
    	Switch GUIGetMsg()
    		Case -3,$GUI_EVENT_CLOSE,$gm_Menu_exit
    			GUIDelete()
    			Exit
    		Case $gm_Menu_run
    			_startRoutine()
    		Case $gm_Menu_stop,$gB_Button1
    			_stopRoutine()
    	EndSwitch
    WEnd
    
    
    Func _startRoutine()
    	$stop = False
    	Local $iMsg, $iT
    
    	Do
    		For $i = 0 to 60
    			GUICtrlSetData($gL_Label1,$i)
    
    			; Sleep durch Msg-Loop-Schleife ersetzt
    			$iT = TimerInit()
    			While TimerDiff($iT) < 1000
    				$iMsg = GUIGetMsg()
    				If $iMsg = $gB_Button1 Or $iMsg = $gm_Menu_stop Or $stop then ExitLoop 3
    			WEnd
    		Next
    	Until False
    EndFunc
    
    Func _stopRoutine()
    	$stop = true
    EndFunc
    Alles anzeigen

    Variante 2 - OnEvent-Modus:

    Die Idee dahinter ist, dass der OnEvent-Modus Funktionen ähnlich wie Hotkeyset aufruft und daher ohne explizite Event-Abfragen funktioniert.
    Das heißt man verknüpft die Events einfach mit den Funktionen und fertig.

    Problem: Auch der OnEvent-Modus arbeitet mit einer Art Warteschlange. Und er arbeitet erst das nächste Event ab, wenn die Funktion, welche durch das vorherige Event aufgerufen wurde beendet wurde.
    Das heißt wir stehen eigentlich wieder vor dem selben Problem.
    Eine Idee hierzu wäre es, den Aufruf von _startRoutine() möglichst kurz zu halten.
    Ich habe das umgesetzt indem diese einfach nur ein AdlibRegister initiiert und dann sich wieder beendet.
    Auf diese Art können dann die weiteren Events bearbeitet werden.
    Der Code ist dann evtl. etwas übersichtlicher:

    AutoIt
    #include <GUIConstants.au3>
    
    ; schalte auf OnEvent-Modus um
    Opt("GUIOnEventMode", 1)
    
    ; -------- GUI-Aufbau -----------------------
    Global Const $GUI = GUICreate('Test',300,150, -1, -1, $WS_SYSMENU,$WS_EX_TOPMOST)
    Global $gm_Menu = GUICtrlCreateMenu("Steuerung")
    Global $gm_Menu_run =  GUICtrlCreateMenuItem("Programm starten",$gm_Menu)
    Global $gm_Menu_stop =  GUICtrlCreateMenuItem("Programm stoppen",$gm_Menu)
    GUICtrlCreateMenuItem("", $gm_Menu, 3)
    Global $gm_Menu_exit =  GUICtrlCreateMenuItem("Beenden",$gm_Menu)
    Global $gB_Button1 = GUICtrlCreateButton ("Stopp", 10, 50,60,30)
    Global $gL_Label1 = GUICtrlCreateLabel("Zeit",10,10,100,20,1,5)
    Global $iCount
    
    ; -------- Event-Behandlung -----------------------
    ; Verknüpfe das Ereignis $GUI_EVENT_CLOSE mit der Funktion _beendeProgramm
    GUISetOnEvent($GUI_EVENT_CLOSE, "_beendeProgramm")
    ; Verknüpfe die Klick-Events der Controls mit entsprechenden Funktionen
    GUICtrlSetOnEvent($gm_Menu_run, "_startRoutine")
    GUICtrlSetOnEvent($gm_Menu_stop, "_stopRoutine")
    GUICtrlSetOnEvent($gB_Button1, "_stopRoutine")
    
    ; -------- Hotkeys -------------------------------- 
    ; (evtl. Alternative: GUISetAccelerators)
    HotKeySet('{F10}','_startRoutine')
    HotKeySet('{F11}','_stopRoutine')
    
    ; GUI sichtbar machen
    GUISetState(@SW_SHOW, $GUI)
    
    ; Endlossschleife (damit sich Programm nicht beendet)
    ; Der Programmablauf wird nun über Hotkeys und Events beeinflusst
    While Sleep(100)
    WEnd
    
    ; startet den Aufruf von _countUp aller 1s
    Func _startRoutine()
    	$iCount = 0
    	AdlibRegister("_countUp", 1000)
    EndFunc
    
    ; stoppt den periodischen Aufruf von _countUp
    Func _stopRoutine()
    	AdlibUnRegister("_countUp")
    EndFunc
    
    ; Funktion, welche hochzählt und die Zahl anzeigt
    Func _countUp()
    	$iCount = $iCount > 60 ? 0 : $iCount + 1
    	GUICtrlSetData($gL_Label1, $iCount)
    EndFunc
    
    ; Funktion welche das Programm beendet
    Func _beendeProgramm()
    	Exit
    EndFunc
    Alles anzeigen
  • AutoIt-Hackathon #3 "alte Zeiten"

    • AspirinJunkie
    • 11. Mai 2025 um 21:06

    Na dann meine Lösung - tatsächlich durchaus eine Herausforderung für mich gewesen:

    AutoIt
    Func _IntegerToRoman($dInt)
    	Local $aRoman[][2] = [["M", 1000],["CM", 900],["D", 500],["CD", 400],["C", 100],["XC", 90],["L", 50],["XL", 40],["X", 10],["IX", 9],["V", 5],["IV", 4],["I", 1]]
    	Local $sReturn = ""
    	For $i = 0 To UBound($aRoman) - 1 
    		If $dInt <= 0 Then ExitLoop
    		While $dInt >= $aRoman[$i][1]
    			$sReturn &= $aRoman[$i][0]
    			$dInt -= $aRoman[$i][1]
    		WEnd
    	Next
    	Return $sReturn
    EndFunc   ;==>_IntegerToRoman
    
    Func _RomanToInteger($sRoman)
    	Local $dInt = 0, $dCurr, $dVorher, $aRoman[][2] = [["M", 1000],["D", 500],["C", 100],["L", 50],["X", 10],["V", 5],["I", 1]], $mRoman[]
    	For $i = 0 To UBound($aRoman) - 1
    		$mRoman[$aRoman[$i][0]] = $aRoman[$i][1]
    	Next
    	For $cChar in StringSplit($sRoman, '', 3)
    		$dCurr = $mRoman[$cChar]
    		$dInt += $dCurr > $dVorher ? $dCurr - 2 * $dVorher : $dCurr
    		$dVorher = $dCurr
    	Next
    	Return $dInt
    EndFunc   ;==>_RomanToInteger
    
    ; Bonus-Aufgabe für Ambitionierte ;-)
    Func _DateToRoman($sDate) ;Input date in the format "YYYY/MM/DD[ HH:MM:SS]", Output in same date-format with roman sign
    	Return Execute('"' & StringRegExpReplace($sDate, "(\d+)", '" & _IntegerToRoman($1) & "') & '"')
    EndFunc   ;==>_DateToRoman
    Alles anzeigen
  • Datenbank : Teil 1 erstellen einer DB

    • AspirinJunkie
    • 28. April 2025 um 07:34

    2038 findet nur der Überlauf statt wenn 32 Bit-Integer zur Speicherung verwendet werden.
    SQLite entscheidet aufgrund des Bereiches eines Wertes selbstständig ob es diesen als 32 Bit oder 64 Bit Integer abspeichert.
    Im Fall von Unix-Timestamps > 2147483647 (2038-01-19 03:14:07) wechselt SQLite also automatisch auf 64 Bit und daher gibt es da kein Problem.

    Die Funktion unixepoch() ist in SQLite folgendermaßen definiert:

    Code
    static void unixepochFunc(
      sqlite3_context *context,
      int argc,
      sqlite3_value **argv
    ){
      DateTime x;
      if( isDate(context, argc, argv, &x)==0 ){
        computeJD(&x);
        if( x.useSubsec ){
          sqlite3_result_double(context, (x.iJD - 21086676*(i64)10000000)/1000.0);
        }else{
          sqlite3_result_int64(context, x.iJD/1000 - 21086676*(i64)10000);
        }
      }
    }
    Alles anzeigen

    Hier sieht man schön, dass der Returnwert der Funktion ein 64 Bit Integer ist. Ein Überlaufproblem wird also nicht auftreten.

    Auch die strftime-Funktion ist davon nicht betroffen wie man leicht selbst testen kann:

    SQL
    SELECT
      CAST(strftime('%s', '2038-01-19 03:14:07', 'utc') AS INTEGER) AS vorher,
      CAST(strftime('%s', '2038-01-19 03:14:08', 'utc') AS INTEGER) AS nachher,
      CAST(strftime('%s', '2099-01-01 03:14:07', 'utc') AS INTEGER) AS zukunft;
  • AutoIt-Hackathon #2 CypherEnigma

    • AspirinJunkie
    • 22. April 2025 um 22:15

    Juchhe!

    Aus meiner Sicht war es schwer für die Aufgabe grundlegende Ansätze zum Optimieren zu finden.
    Grob war eigentlich das Grundgerüst ziemlich fest und nur an ein paar Feinheiten konnte man schrauben.
    Sieht man auch schön daran wie sehr alle beeinander waren zeitlich.
    Mein Skript wird wohl nur deshalb paar Prozente vorn gelegen haben weil ich den Sonderfall mit $nExtra=0 extra behandelt habe (wie Eukalyptus).
    Würde man die Skripte nur mit Beispielen testen wo $nExtra<>0 ist, dann könnte sich die Reihenfolge schnell ändern.

    Ich hatte zig Varianten durchexerziert, welche alle nach logischen dafürhalten schneller sein müssten. Die Modulooperationen komplett durch +- und If ersetzt, komplette Lookup-Tables für alle Fälle erstellt usw. Am Ende war dennoch diese - nunja "profane" Lösung die schnellste. Das zeigt einmal mehr, dass man in AutoIt anders optimieren muss. Eher das Hauptaugenmerk auf die Entlastung des Interpreters legen anstatt Operationen nach teuer und günstig einzuteilen und darauf hin zu optimieren.

    Wäre sicherlich mal interessant in einer der nächsten Discord-Gespräche wenn jeder seine Lösung mal erklärt und vor allem: wie diese entstanden ist.

    Zitat von UEZ

    Sehr clever Look-up Table [...] zu benutzen!

    Hast du doch genauso verwendet ;)

    Ich danke wieder einmal(!) Schnuffel für die tolle Ausarbeitung und Durchführung des Hackathons.
    Dies ist für die Belebung des Forenlebens nicht hoch genug zu bewerten!
    Ich denke es ist Zeit, dass wir uns in irgendeiner Weise mal revanchieren.

  • MsgBox ohne Beep möglich

    • AspirinJunkie
    • 16. April 2025 um 11:01

    Msgbox macht im Grunde nichts weiter als die Windows-API-Funktion "MessageBoxW" aufzurufen.
    Diese ist so eingestellt, dass bei bestimmten gesetzten Parametern ein Beep ertönt.
    Hab es nicht genau getestet aber bei $MB_ICONERROR, $MB_ICONWARNING oder $MB_ICONINFORMATION zumindest ist das wohl der Fall.
    Zumindest wenn Benachrichtigungstöne in den Soundeinstellungen von Windows eingestellt sind.

    Mir fallen als Abhilfe daher spontan folgende Möglichkeiten ein:

    1. Verzichte auf die Parameter, bei welchen der Ton erklingt.
    2. Entferne in den Soundeinstellungen von Windows den Benachrichtigungston.
    3. Schreibe eine eigene Msgbox-Funktion, welche nicht piept.
  • Ist ein 'char' ein 'char' oder vieleicht doch nicht? bzw. kann er es werden?

    • AspirinJunkie
    • 15. April 2025 um 17:46

    Erste Frage: Was hat das Thema im Bereich " Übersetzung der Hilfe-Datei ins Deutsche - Fragen/Anregungen" zu suchen?

    Zitat von bankesbusters

    1. ist es möglich aus einem String "Chr(74)" mit wenig aufwand ein Chr(74) zu machen?

    Ja - mit Execute(). Diese Funktion führt AutoIt-Code aus, der als String übergeben wird und gibt dessen Ergebnis zurück.

    Zitat von bankesbusters

    2. ist es möglich aus Zahlen in einem Array Chr() zu machen?

    1. Du hast eigentlich keine Zahlen in deinem Array sondern Strings. Das klappt in dem Fall zwar, aber die Anführungszeichen solltest du dennoch entfernen wenn du StringFromASCIIArray() so nutzen möchtest wie es vorgesehen ist.

    2. Du versuchst ein 2D-Array an StringFromASCIIArray() zu übergeben. Dieses erwartet jedoch ein 1D-Array als Input.

    Wenn du also mehrere Wörter in einem Array als ASCII-Codes abgespeichert halten möchtest und diese alle in einen String konvertieren möchtest, dann musst du entsprechend deiner Datenstruktur handeln.
    Wenn du wie in deinem Beispiel die Wörter als 2D-Array vorliegen hast (was ich persönlich als ziemlich bescheiden ansehe, da sich die Anzahl der Spalten dann nach dem längsten Wort für alle richtet), dann musst du in einer For-To-Schleife die Zeilen (also die Wörter) durchgehen und in einer zweiten For-To-Schleife darin die einzelnen Buchstaben durchgehen, mit Chr() dekodieren und buchstabenweise das Wort wieder zusammensetzen

    Wenn du stattdesen ein Array-In-Array vorliegen hast - also ein 1D-Array dessen Elemente wiederrum 1D-Arrays sind, dann gehst du in einer For-To-Schleife die Zeilen des äußeren Arrays durch und kannst für die einzelnen SubArrays wieder StringFromASCIIArray() verwenden.

    Zitat von bankesbusters

    aber aleine dafür gibt es irgendwie keine sinnvollen AutoIT-Befehle

    Es kann nicht für jeden bizarren Spezialfall vorgefertigte Funktionen geben.
    Wenn es wirklich notwendig ist (wofür ich hier bislang nicht den Anwendungsfall sehe), dann kannst du dir eine eigene Funktion für bessere Wiederverwendbarkeit schreiben.

  • Einzelne Daten (Mengenproblem) in einem String durch array austauschen?

    • AspirinJunkie
    • 14. April 2025 um 15:44

    Bei dir steht in deinem Array im ersten Element (Index [0][0]) die Anzahl der Zeilen des Arrays.
    Das heißt: Irgendjemand muss sich darum kümmern, dass dort die korrekte Anzahl steht - in deinem Fall du selbst.
    Die Anzahl der Zeilen des Arrays ist aber eine immante Eigenschaft des Arrays, welche man ganz einfach mit der Funktion Ubound() abfragen kann.
    Sprich: Das kann man sich alles sparen.

    Da die Variante mit Ubound() also die sicherere ist, habe ich dies entsprechend umgestellt.
    Das hat auch den Nebeneffekt, dass die Daten in deinem Array nun beim Index 0 beginnen anstatt wie vorher bei 1.
    Und da Ubound die Anzahl der Zeilen zurückgibt und die Indizes aber bei 0 beginnen, ist der letzte Index im Array = Anzahl Zeilen - 1

  • Einzelne Daten (Mengenproblem) in einem String durch array austauschen?

    • AspirinJunkie
    • 14. April 2025 um 14:41

    Falsch abgebogen bist du nicht.
    Das Skript macht das was es soll und das ist genauso wie von dir bereits festgestellt: Die bereits prozessierten Zeichen werden von den danach kommenden Anweisungen wieder mit erfasst.

    Um damit umzugehen gibt es ein paar Ansätze.
    Einer wäre es, bereits prozessierte Daten zu escapen indem man z.B. einen Präfix voranstellt oder soetwas in der Art.
    Dann sagt man dem Ersetzungsgbefehl, dass die Zeichen, welche den Präfix haben nicht prozessiert werden sollen.
    Ganz am Ende dann wird das Escapezeichen dann entfernt und das Ergebnis sollte dein gewünschtes sein.

    Da wir uns hier im Forum "Programmieranfragen" befinden wäre das ganze auch gleich folgendermaßen umgesetzt (dann sieht man auch gleich, dass in deinem Solltext noch ein kleiner Fehler steckt):

    AutoIt
    Global $sSatz = "hallo dies ist ein toller & guter text!"
    Global $cEscape = "#" ; Ein Zeichen als Präfix für die Zeichen die bereits prozessiert wurden
    
    Global $aErsatz[][] = [["a","m"],["b","n"],["c","o"],["d","p"],["e","q"],["f","r"],["g","s"],["h","t"], _
    ["i","u"],["j","v"],["k","w"],["l","x"],["m","y"],["n","z"],["o","a"],["p","b"],["q","c"],["r","d"],["s","e"], _
    ["t","f"],["u","g"],["v","h"],["w","i"],["x","j"],["y","k"],["z","l"],["!","1"],["&","2"],[" ","_"]] ; die Veraenderungen
    
    ; Alle Ersetzungspaare einzeln durchgehen
    For $i = 0 To UBound($aErsatz) - 1
    
    	; Nur die Buchstaben im Satz austauschen, welche nicht das Präfix davor stehen haben
    	$sSatz = StringRegExpReplace($sSatz, StringFormat("(?<!\Q%s\E)\Q%s\E", $cEscape, $aErsatz[$i][0]), $cEscape & $aErsatz[$i][1])
    
    	; aktuellen Satz ausgeben
        ConsoleWrite($sSatz & @CRLF)
    
    	; warten (warum auch immer...)
        sleep(100)
    Next
    
    ; Satz final um die Escape-Zeichen bereinigen
    $sSatz = StringRegExpReplace($sSatz, '\Q' & $cEscape & '\E', '')
    
    MsgBox(0,"","Muss sein:" & @CRLF & "tmxxa_piqe_uef_quz_faxxqd_2_sgfqd_fqjf1" & @CRLF & @CRLF & "Ist aber:" & @CRLF & $sSatz)
    Alles anzeigen
  • daten aus einer ini datei in ein array[x][x] nach vorgaben umwandeln? möglich? wie?

    • AspirinJunkie
    • 13. April 2025 um 14:58

    Die naheliegendste Abfolge ist die folgende:

    1. Daten der Ini-Sektion roh einlesen (mit IniReadSection())
    2. Anzahl der eingelesenen Datensätze bestimmen (mit Ubound oder direkt im Element [0][0] von IniReadSection)
    3. Zielarray mit der gewünschten Größe deklarieren (die Anzahl aus Schritt 2 verwenden)
    4. Die Elemente vom Returnarray von IniReadSection einzeln durchgehen (mit For-To-Schleife)
    5. In der Schleife den Datenwert des aktuellen Elementes an den "|"-Zeichen trennen (mit StringSplit)
    6. In der Schleife die getrennten Werte einzeln ins Zielarray schreiben

    Fertig

    Bei dir ist daher schon einmal das Problem, dass du nie das Zielarray deklarierst.
    Auch aufpassen muss man ob die Arrays jeweils 1-basiert oder 0-basiert sind (bei IniReadSection sind die dämlicherweise 1-basiert).

    Spoiler anzeigen
    AutoIt
    #include <Array.au3>
    
    Global $sIniFile = @ScriptDir & "\Test.ini"
    
    ; Daten der Ini-Sektion in 2D-Array einlesen (Datenfelder noch ungetrennt)
    Global $aIniDataRaw = IniReadSection($sIniFile, "Data")
    If @error Then MsgBox(0, 16, "Fehler", "Fehler " & @error & " beim Einlesen der Ini-Sektion")
    
    ; Anzahl der eingelesenen Elemente ermitteln
    Global $iN = $aIniDataRaw[0][0]
    
    ; Zielarray dimensionieren
    Global $aData[$iN][3]
    
    ; Daten einzeln in Zielarray übertragen
    Global $aSplit
    For $i = 1 To $iN
    	
    	; Datenwert an den | trennen
    	$aSplit = StringSplit($aIniDataRaw[$i][1], "|", 3)
    	If UBound($aSplit) < 3 Then Exit MsgBox(0,"Fehler", "Fehler " & @error & " beim Trennen der Daten.")
    
    	; in Zielarray übertragen
    	$aData[$i - 1][0] = $aSplit[0]
    	$aData[$i - 1][1] = $aSplit[1]
    	$aData[$i - 1][2] = $aSplit[2]
    Next
    
    ; Zielarray ausgeben
    _ArrayDisplay($aData, "Ergebnis", "", 64, "|", "Name|Monat|Raum")
    Alles anzeigen
  • AutoIt Hackathon #1 Mitarbeiter-ID abgeschlossen

    • AspirinJunkie
    • 30. März 2025 um 21:19
    AutoIt
    Global $LineStart = @ScriptLineNumber
    Func _CreateID($aUserdata)
    	Local $Return
    	$Return = StringLeft(StringReplace($aUserdata[2], "-", "") & "99999", 5) & _
    			StringMid($aUserdata[3], 9, 1) & _
    			($aUserdata[4] = "W" ? (StringMid($aUserdata[3], 4, 1) + 5 ) & StringMid($aUserdata[3], 5, 1) : StringMid($aUserdata[3], 4, 2)) & _
    			StringMid($aUserdata[3], 1, 2) & _
    			StringRight($aUserdata[3], 1) & _
    			StringLeft($aUserdata[0], 2) & ($aUserdata[1] = "" ? 99 : StringLeft($aUserdata[1], 2))
    	Local $iQuersumme = 0
    	For $iChar In StringToASCIIArray($Return)
    		$iQuersumme += $iChar
    	Next	
    	Do 
    		$iQuersummeAlt = $iQuersumme
    		$iQuersumme = 0
    		For $iZiffer In StringSplit($iQuersummeAlt, "",2)
    			$iQuersumme += $iZiffer
    		Next
    	Until StringLen($iQuersumme) < 2
    	$Return &= $iQuersumme
    	Return $Return
    EndFunc   ;==>_CreateID
    Global $LineEnd = @ScriptLineNumber
    Alles anzeigen
  • Wo finde ich eine Liste über alle Befehle, Funktionen?

    • AspirinJunkie
    • 7. März 2025 um 21:06
    Zitat von o0Julia0o

    warum finde ich da nirgends: GetSelectedFolder beschrieben?

    Ich kenne diese Funktion nicht. Auf was beziehst du dich?

    Zitat von o0Julia0o

    Stehen sonderfunktionen in Bibliotheken?

    Ist File.au3 eine solche?

    UDFs sind, wie gesagt, Funktionen die selbst in AutoIt geschrieben sind. Diese sind also selbst in .au3-Dateien hinterlegt, welche man in sein Skript einbinden kann (mit #include).

    Um das bisschen zu sortieren sind diese in thematische Dateien aufgeteilt. Diese könnte man als Bibliotheken bezeichnen. Und ja: File au3 ist genau so eine.

    Edit: Tweaky: Ja runterladen ist klar aber früher gab's die doch auch mal online zum direkt verlinken - oder?

  • Wo finde ich eine Liste über alle Befehle, Funktionen?

    • AspirinJunkie
    • 7. März 2025 um 20:56

    Nun du hast einmal die in der Sprache integrierten Funktionen. Das müsste ungefähr der Liste entsprechen die du gerade verlinkt hast.

    Auf dieser Basis kann man dann natürlich in AutoIt-Code selbst nützliche Funktionen schreiben. Hiervon werden gleich eine ganze Menge davon mit AutoIt mitgeliefert. Das sind die sogenannten UDF (user defined functions).

    Zusätzlich kannst du dir aus anderen Quellen wie z.b. den Forum hier weitere Funktionen besorgen. Hierfür gibt es auch ein paar Sammlungen.

    @all und insbesondere Tweaky: ich hätte gerne auf die deutsche Hilfe verlinkt aber irgendwie geht der Link auf der Startseite bei mir nicht. Ist das bei euch auch so?

  • Festgelegten Ordner in den aktuell ausgewählten Ordner kopieren

    • AspirinJunkie
    • 7. März 2025 um 17:09
    Zitat von SOLVE-SMART

    (kleiner lieber "wink" an AspirinJunkie 😚 😂),

    Naja da ich schonmal angesprochen wurde, hab ich mir dann doch schon bisschen Gedanken gemacht darüber.
    Mir ist dabei vor allem der Aspekt aufgestoßen, dass das Erkennen der aktuell ausgewählten Ordner evtl. etwas wacklig sein könnte.
    Nun ist es jedoch so, dass man die ausgewählten Dateien eines Explorerfensters auch robust ermitteln kann.

    Vielleicht könnt ihr daher ja folgendes zumindest als Grundkonstrukt verwenden?:

    AutoIt
    #include <Array.au3>
    #include <WinAPIShPath.au3>
    
    
    Global $mSelExpFiles = _getSelectExplorerFiles(False)
    
    For $sPath in MapKeys($mSelExpFiles)
    	$aSelected = $mSelExpFiles[$sPath]
    	_ArrayDisplay($aSelected, $sPath)
    Next
    
    
    ; #FUNCTION# ====================================================================================================================
    ; Name ..........: _getSelectExplorerFiles()
    ; Description ...: Returns a map of currently opened explorers with the opened path as key and an array with the selected files as value
    ; Syntax ........: _getSelectExplorerFiles($bFullpath = True)
    ; Parameters ....: bFullpath - [Boolean]
    ;                            ↳ true: the full path of the selected files are returned
    ;                            ↳ false: only the names of the selected files are returned
    ; Return value ..: Success: [Map]: opened path as key and an array with the selected files as value (@extended = number of returned founds)
    ;                  Failure: Null and set @error to:
    ;                           | 1: error during open Shell.Application
    ; Author ........: AspirinJunkie
    ; Modified.......: 2025-03-07
    ; Remarks .......: If you have opened the same path several times: you're out of luck - it will only be returned once ;-)
    ; Related .......: _WinAPI_PathCreateFromUrl()
    ; Link ..........: https://www.netlib.org/lapack/explore-html/dd/dc3/group__trsv_ga7a7dcbb8745b4776ce13063ab031141f.html#ga7a7dcbb8745b4776ce13063ab031141f
    ; Example .......: No
    ; ===============================================================================================================================
    Func _getSelectExplorerFiles($bFullpath = True)
    	Local $oShell = ObjCreate("Shell.Application"), _
    	      $oWin, $oSelectedFiles, $iC, $mReturn[]
    
    	If Not IsObj($oShell) Then Return SetError(1, 0, Null)
    
    	For $oWin in $oShell.Windows
    		$oSelectedFiles = $oWin.Document.SelectedItems()
    		If (Not IsObj($oSelectedFiles)) Then ContinueLoop
    
    		Local $aSelected[$oSelectedFiles.Count]
    		$iC = 0
    
    		For $oFile In $oSelectedFiles
    			$aSelected[$iC] = $bFullpath ? $oFile.Path : $oFile.Name
    			
    			$iC += 1
    		Next
    
    		$mReturn[_WinAPI_PathCreateFromUrl($oWin.LocationURL)] = $aSelected
    	Next
    
    	Return SetExtended(UBound($mReturn), $mReturn)
    EndFunc
    Alles anzeigen

    Das kann man natürlich noch erweitern indem man die Windows-Handles zurückgibt um Herauszufinden, welches Explorerfenster ganz oben steht (also das letzte geöffnete) usw.

  • Ordnernamen in Variable schicken

    • AspirinJunkie
    • 20. Februar 2025 um 17:19

    Schnuffel Dürfte ich - zugegeben etwa vorsichtig formuliert - deiner spannenden Lösung eine Veränderung vorschlagen?

    Der Umweg über eine tatsächliche Batch-Datei kann umgangen werden.
    Man kann auch direkt die cmd.exe entsprechend aufrufen:

    AutoIt
    Local $iPID = Run(@ComSpec & ' /C "FOR %I IN ("' & $sPath & '") DO @ECHO %~dI^|%~pI^|%~nI^|%~xI"', "", @SW_HIDE, 2)

    Diese Variante hätte zusätzlich auch den Vorteil, dass sie mit Leerzeichen im Ordnernamen klarkommt.

  • Ordnernamen in Variable schicken

    • AspirinJunkie
    • 20. Februar 2025 um 16:24
    Zitat von Peter S. Taler

    diskutieren gehört dazu - nur ob es für einen Hilfesuchenden immer sinnvoll ist?

    Nochmal: Es geht nicht ausschließlich um den Hilfesuchenden.
    Das hier ist kein Dienstleistungsunternehmen.
    Die Leute helfen hier weil es Ihnen Spaß macht und machen es nur in der Art wie es ihnen Spaß macht.
    Der Gewinn ist für alle da, wenn beides unter einen Hut gebracht werden kann.
    Mag sein dass die anschließende Diskussion den Fragenden nicht weiter bringt - und?
    Er hat dennoch genug Lösungen erhalten.
    Rückmeldung gab es ja eh nicht.

    Wir können uns noch so oft einreden, dass wir aus einem irgendwie gearteten Altruismus heraus allein hier sind um anderen zu helfen.
    Wenn man jedoch mal ehrlich und objektiv darüber nachdenkt kommt man am Ende darauf, dass man es tatsächlich nur für sich selbst macht.

    Zitat von Peter S. Taler

    Wer also sollte ermahnt werden eine freie Diskussion zuzulassen?

    Du. Deine übergriffige Aussage, dass wir bestimmte Diskussionen unverzüglich zu unterlassen haben ist völlig daneben.

    Zitat von Peter S. Taler

    nur eine Lösung zu "diskreditieren" weil sie, unbewiesen, angeblich etwas langsamer ist --> macht das Sinn?

    Es fand hier nirgends eine Diskreditierung statt. Es wurden verschiedene Varianten hinsichtlich ihrer Eigenschaften bewertet und verglichen.
    Dass eine Erkenntnis war, dass eine Lösung vermutlich etwas weniger performant ist, ist keine Diskreditierung.
    Wir werden auch in Zukunft derartige Bewertungen vornehmen.
    Der Anspruch den einige (mich eingeschlossen) hier haben ist jeweils bestmögliche Lösungen zu finden.
    Und diese findet man nicht ohne Diskussion.
    Diese mögen für den konkreten Fragesteller overdosed sein aber es geht um Wiederverwendung für andere in anderen Szenarien.

  • Anti "false-positive" Strategie mit PureBasic

    • AspirinJunkie
    • 20. Februar 2025 um 13:29

    Am Ende hat sich der Keylogger-Entwickler umgeschaut wie er das Ding am besten verstecken kann und ist ausgerechnet bei Dir fündig geworden. ^^

  • Anti "false-positive" Strategie mit PureBasic

    • AspirinJunkie
    • 20. Februar 2025 um 13:05

    Als ich das erste mal Schnuffels exe-Lösung mit Virustotal angesehen habe, schlugen nur 13 von 72 Scannern an.
    Wenn man den Test nun wiederholt sind auf einmal ganze 32 von 72 Scannern angesprungen.

    Hat irgendwer eine Erklärung warum Schnuffels Variante auf einmal so dermaßen auf dem Index gelandet sein könnte?
    Auch die x86-UPX-Variante wird nun von 21 Scannern als schlecht erkannt.
    Da gab es also auch einen Anstieg.

    Könnte das mit dem derzeitig grasierenden Keylogger zusammenhängen, der derzeit im Umlauf ist?

  • Ordnernamen in Variable schicken

    • AspirinJunkie
    • 20. Februar 2025 um 12:35

    Es geht nicht um performanter. Es geht um einfacher verständlich oder alternativ alle Fälle abdeckend.
    Die Variante bei der eine Funktion aufgerufen wird und direkt dessen Rückgabe als Index wiederrum diesen Funktionsaufruf erhält ist mit Sicherheit verunsichernder als eine einfache String*()-Lösung.
    Die in sich verschachtelte StringSplit-Lösung ist nicht die naheliegendste.

    Und ansonsten entscheidet jeder für sich selbst, worüber er diskutieren möchte.
    Das lässt sich hier keiner diktieren.
    Das Forum und dessen Inhalte sind nicht ausschließlich auf die Problemlösung von Fragestellern ausgerichtet sondern ebenso ein Diskussionsforum für das eigene Hobby.
    Würde eine Diskussion drumherum nicht zugelassen, gäbe es das Forum nicht mehr, da das Interesse der potentiell Helfenden verschwände.

    Also stopp Versuche eine freie Diskussionen zu unterdrücken.

  • Ordnernamen in Variable schicken

    • AspirinJunkie
    • 19. Februar 2025 um 12:02
    Zitat von Schnuffel

    es gibt Menschen, die suchen Fehler geben aber keine Hilfestellung.

    Schlechte Unterstellung.
    Ich habe eine einfachere Alternative zur Nicht-RegEx-Lösung gegeben.

    Und warum man erst die Initiative einleitet mit "alle mir gerade einfallenden [...] Eventualitäten mit abzufangen" und dann auf Hinweise, dass es eben noch weitere Eventualitäten gibt diese Diskussion dann wieder abwürgt ist ebenso nicht verständlich.

  • Ordnernamen in Variable schicken

    • AspirinJunkie
    • 19. Februar 2025 um 11:19
    Zitat von Schnuffel

    "/" ist aus der UNIX Welt und wird in Windows lediglich "übersetzt"

    Das ändert was? Pfade können überall in Windows mit Slash statt Backslash angegeben werden.
    Für deine Funktion, welche den Anspruch hat diesen Pfad korrekt zu zerlegen müssen ergo die Slashes ebenso beachtet werden.

    Zitat von Schnuffel

    Da im Explorer ein Ordnername aber folgende Zeichen nicht beinhalten darf ist es schwierig den root-Ordner korrekt als Ordnername zurückzugeben ;)

    Dann müsstest du überlegen ob du folgenden Fall bei dir noch entsprechend anders behandeln möchtest (folgendes ist ein korrekter UNC-Pfad):

    AutoIt
    _LastFolderofPath("\\.\C:\")

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™