Schöner wäre, wenn das auch mit X86-Mode geht..
Naja, es geht schon, nur musst Du AutoIt dann irgendwie beibringen mit 64-Bit-Zahlen umzugehen.
Lo- und Hi-DWORD wäre so eine Möglichkeit.
Schöner wäre, wenn das auch mit X86-Mode geht..
Naja, es geht schon, nur musst Du AutoIt dann irgendwie beibringen mit 64-Bit-Zahlen umzugehen.
Lo- und Hi-DWORD wäre so eine Möglichkeit.
Vielleicht hat ja einer der User hier eine fertige Lösung parat?
Ich habe eben mal eine Assembler-UDF erstellt: BitOperations64
Diese kleine UDF enthält 8 Funktionen (BitAND, BitOR, BitNOT, BitROL, BitROR, BitSHL, BitSHR, BitXOR) zum bearbeiten von Integerzahlen im 64-Bit-Format.
Das sind 8 Assembler-Funktionen, die da aufgerufen werden. Das AutoIt-Script muss aber im 64-Bit-Modus laufen (siehe Example).
Edit 26.12.2018: Neue Version
- Bei AND, OR und XOR können nun bis zu 8 Parameter direkt im Funktionsaufruf übergeben werden. Wer mehr Parameter benötigt, muss sie als Array in Parameter Eins übergeben. Danke, Bitnugger!
- Es gibt jetzt noch zwei Hilfsfunktionen "_BitRotate64" und "_BitShift64" in Anlehnung an die originalen Funktionen. Allerdings einheitlich (im Gegensatz zu den originalen Funktionen): mit negativen Werten nach links und positiven Werten nach rechts.
Edit 27.12.2018: Neue Version
- OnAutoItExitRegister erst nach der Deklaration der globalen Variablen.
- Die Anforderung des Speichers geschieht jetzt in einer Funktion: "__BitOp64OnStart".
- Fehler behoben bei "_BitRotate64" und "_BitShift64", wenn 0 für Rotate oder Shift übergeben wurde.
- Fehler behoben bei "_BitROx64" und "_BitSHx64". Der Parameter-Aufruf war falsch rum. ![]()
- Das Beispiel-Script komplett überarbeitet und aufgeräumt.
Wäre es ggf. sinnvoll, die .png und .html-Datei(en) auch unter \results zu speichern, nicht im Hauptverzeichnis mit den .exe's ?
Ja, stimmt! Das ist wohl sinnvoller.
Werde ich in die nächste Version einbauen.
Edit:
Wer es gleich haben möchte, braucht nur 3 Zeilen (die Zeilen 190, 210 und 221) im Script "FlashTest-Viewer.au3" ändern:
von FileChangeDir(@ScriptDir) in FileChangeDir(@ScriptDir & '\results\').
So, rechtzeitig zum Weihnachtsfest ist die erste, richtige Version fertig.
Es gibt jetzt ein eigenes Auswerteprogramm, mit dem man die Grafik und den Text anzeigen und speichern kann.
Einige Neuerungen (CPU-Auslastung, RAM-Belegung) sind auch noch beim eigentlichen Testprogramm dazugekommen.
Das Fenster lässt sich jetzt (während des Test) nicht verschieben, damit die Scriptausführung nicht blockiert wird.
Alles weitere in Post#1.
Warum wird das Treeview alle 5 Minuten neu erstellt/aktualisiert?
Greift da ein anderes Programm auch auf die Dateien zu?
Das was Du bei $read_reservierung, $read_important und $read_liefertermin machst, ist schlecht, weil dort die Datei geöffnet wird, bis zu der angegebenen Zeilennummer gesprungen wird, die Zeile eingelesen und dann die Datei wieder geschlossen wird und das Ganze 3 Mal hintereinander.
Wenn Du mehrere Zeilen aus einer Datei auslesen willst, dann immer erst die Datei öffnen (mit "FileOpen"), dann die Zeilen mit dem FileHandle auslesen: "FileReadLine($handle, Zeilennummer)" und am Schluss die Datei wieder schließen "FileClose($handle)".
Ich persönlich würde gerne zur "pro Frage einen Thread" tendieren
Ja, das würde ich auch so sehen.
Es sei denn die Fragen gehören inhaltlich zusammen, aber wenn es um unterschiedliche Probleme geht, dann auch jeweils ein Thread.
Also irgendwas scheint da zu langsam zu sein, vielleicht wird das Gui vor _Timer_KillAllTimers() gelöscht, sodass die Funktion auf einen NULL Pointer zugreift und dann abstürzt.
Sowas hatte ich auch schon vermutet, aber wenn man die Gui vorher löscht (GuiDelete), dann gibt _Timer_KillAllTimers ein False zurück und das Script stürzt nicht ab, also so, als ob man _Timer_KillAllTimers gar nicht aufruft.
Packt man den Befehl aber in eine OnAutoItExitRegister-Funktion, so wird korrekt ein True zurückgegeben und das Script stürzt auch nicht ab.
Das ist zwar für mich im vorliegenden Fall ausreichend (weil der Timer beim Scriptende gekillt wird), aber man sollte im Hinterkopf behalten, dass es beim "killen" eines Timers während der Laufzeit eines Scripts zu Problemen kommen kann.
@Musashi hat dazu ja auch bereits einiges gepostet.
Hmm...wenn ich _Timer_KillAllTimers in eine OnAutoItExitRegister-Funktion packe, stürzt AutoIt beim beenden nicht mehr ab. ![]()
#AutoIt3Wrapper_UseX64=y ; 64Bit-Modus
#include <Date.au3>
#include <GUIConstantsEx.au3>
#include <ProgressConstants.au3>
#include <Timers.au3>
#include <WinAPISys.au3>
#include <WindowsConstants.au3>
Opt('GuiOnEventMode', 1)
OnAutoItExitRegister('_Exit')
Global $hMainGui = GUICreate('CPU-Test', 300, 420)
GUISetOnEvent($GUI_EVENT_CLOSE, '_CloseMainGui')
Global $idCPUCycle = GUICtrlCreateProgress(20, 10, 12, 400, $PBS_VERTICAL)
Global $idProgressLabel = GUICtrlCreateLabel('', 60, 30, 80, 20)
GUICtrlSetFont(-1, 16)
GUISetState()
Global $idTimer = _Timer_SetTimer($hMainGui, 250, '_CPUCycleTime')
While True
;~ Sleep(1000)
WEnd
Func _Exit()
Local $iRet = _Timer_KillAllTimers($hMainGui)
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $iRet = ' & $iRet & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
EndFunc
Func _CPUCycleTime($hWnd, $iMsg, $iIDTimer, $iTime)
#forceref $hWnd, $iMsg, $iIDTimer, $iTime
Local $iPercent = _GetCPUUsage()
GUICtrlSetData($idCPUCycle, $iPercent)
GUICtrlSetData($idProgressLabel, $iPercent & '%')
EndFunc
Func _GetCPUUsage()
Local Static $aOld[3], $iTicksOld, $aSystemInfo
Local $aRet, $iTime1, $iTime2, $iPercent, $iTicks
$iTicks = _WinAPI_GetTickCount()
$aRet = _WinAPI_GetSystemTimes()
If @error Then Return SetError(@error, @extended, 0)
If $aOld[0] = 0 Then ; beim ersten Aufruf die Static-Variablen fuellen
$aSystemInfo = _WinAPI_GetSystemInfo() ; $aSystemInfo[5] = Number of physical processors
If @error Then Return SetError(@error, @extended, 0)
$iTicksOld = $iTicks
$aOld = $aRet
Return
EndIf
$iTime1 = $aRet[1] - $aRet[0] + $aRet[2] ; [0] = idle-time, [1] = kernel-time, [2] = user-time
$iTime2 = $aOld[1] - $aOld[0] + $aOld[2] ; [0] = idle-time, [1] = kernel-time, [2] = user-time
$iPercent = Int(($iTime1 - $iTime2) / (($iTicks - $iTicksOld) * 100) / $aSystemInfo[5])
$iTicksOld = $iTicks
$aOld = $aRet
Return $iPercent
EndFunc
Func _CloseMainGui()
Exit
EndFunc
Alles anzeigen
Was soll mir das jetzt sagen?
Bei mir stürzt das Skript tatsächlich nicht ab. (64bit)
Also ich habe das Script einfach so c&p, gestartet und anschließend beendet.Muss ich sonst etwas spezielles beachten?
Äh?
Wenn Du das so gestartet hast, wie das das oben steht, dann sollte es abstürzen. Mit !>17:20:16 AutoIt3.exe ended.rc:-1073741819 in der Konsole.
Welches Betriebssystem verwendest Du? Welche AutoIt-Version?
Ich habe mir gerade eine Funktion zum ermitteln der Prozessorauslastung geschrieben.
Das klappt auch, aber wenn ich die Funktion innerhalb einer Timer-Funktion aufrufe und diese Timer-Funktion bei Scriptende "kille", dann stürzt AutoIt ab.
Aber nicht immer, sondern nur im 64-Bit-Modus #AutoIt3Wrapper_UseX64=y.
Im 32-Bit-Modus passiert das nicht #AutoIt3Wrapper_UseX64=n.
Könnt ihr einen Grund dafür erkennen?
BTW: Wenn ich bei Scriptende nicht aufräume _Timer_KillAllTimers($hMainGui) auskommentiere, dann beendet sich AutoIt ohne Absturz.
#AutoIt3Wrapper_UseX64=y ; 64Bit-Modus
#include <GUIConstantsEx.au3>
#include <ProgressConstants.au3>
#include <Timers.au3>
#include <WinAPISys.au3>
Opt('GuiOnEventMode', 1)
Global $hMainGui = GUICreate('CPU-Test', 300, 420)
GUISetOnEvent($GUI_EVENT_CLOSE, '_CloseMainGui')
Global $idCPUCycle = GUICtrlCreateProgress(20, 10, 12, 400, $PBS_VERTICAL)
Global $idProgressLabel = GUICtrlCreateLabel('', 60, 30, 80, 20)
GUICtrlSetFont(-1, 16)
GUISetState()
Global $idTimer = _Timer_SetTimer($hMainGui, 250, '_CPUCycleTime')
While True
;~ Sleep(1000)
WEnd
Func _CPUCycleTime($hWnd, $iMsg, $iIDTimer, $iTime)
#forceref $hWnd, $iMsg, $iIDTimer, $iTime
Local $iPercent = _GetCPUUsage()
GUICtrlSetData($idCPUCycle, $iPercent)
GUICtrlSetData($idProgressLabel, $iPercent & '%')
EndFunc
Func _GetCPUUsage()
Local Static $aOld[3], $iTicksOld, $aSystemInfo
Local $aRet, $iTime1, $iTime2, $iPercent, $iTicks
$iTicks = _WinAPI_GetTickCount()
$aRet = _WinAPI_GetSystemTimes()
If @error Then Return SetError(@error, @extended, 0)
If $aOld[0] = 0 Then ; beim ersten Aufruf die Static-Variablen fuellen
$aSystemInfo = _WinAPI_GetSystemInfo() ; $aSystemInfo[5] = Number of physical processors
If @error Then Return SetError(@error, @extended, 0)
$iTicksOld = $iTicks
$aOld = $aRet
Return
EndIf
$iTime1 = $aRet[1] - $aRet[0] + $aRet[2] ; [0] = idle-time, [1] = kernel-time, [2] = user-time
$iTime2 = $aOld[1] - $aOld[0] + $aOld[2] ; [0] = idle-time, [1] = kernel-time, [2] = user-time
$iPercent = Int(($iTime1 - $iTime2) / (($iTicks - $iTicksOld) * 100) / $aSystemInfo[5])
$iTicksOld = $iTicks
$aOld = $aRet
Return $iPercent
EndFunc
Func _CloseMainGui()
_Timer_KillAllTimers($hMainGui)
;~ _Timer_KillTimer($hMainGui, $idTimer)
Exit
EndFunc
Alles anzeigen
In meinem Fall ist der 1. Use Case, dass es sehr wichtig ist, Nachts die Einheiten in Sicherheit zu bringen. Dafür schickt man seinen Helden beim Schlafengehen auf große Tour, sodass er möglichst zum Weckerklingeln grade wieder ankommt. So sind die Einheiten nachts nicht angreifbar, gängige Praxis. Jetzt muss man das gut timen und die Einheiten haben unterschiedliche Geschwindigkeiten, es gibt Hintour und Rücktour und andere Parameter, die man manuell berechnen muss. Einiges ist mit Excel aufgreifbar, aber ich hatte die Idee, das etwas praktikabler zu gestalten und AutoIt mal wieder aufzufrischen.
Die Forenregeln untersagen Bots und Automatisierung von Websiten und Tools, die das in den AGB verbieten und ich möchte mir einfach nur einen "speziellen Taschenrechner" basteln...
[gelöschte Beiträge wiederhergestellt]
Und genau das ist ein Gamebot!
Du verschaffst Dir Vorteile in dem Spiel. Da hilft es auch nicht, wenn Du es "Taschenrechner" nennst.
Somit wird der Thread jetzt geschlossen!
Muss man den 1. Tab irgendwie vorher wieder den Focus geben?
Ja! Dafür gibt es GUISwitch.
Hmm, das geht auch ohne "Multitasking/threading", so wie du es bei deiner Digitaluhr schon umgesetzt hast, per _Timer_SetTimer($hMainGui, 100, '_ClockUpdate')
Mit der Timer-UDF habe ich das schonmal getestet. Die Timer-Funktion sollte die Anzeige übernehmen, aber das klappte nicht stabil.
Wenn ich die Aufrufzeit zu hoch gesetzt habe, passte die Anzeige nicht mehr (es muss dann ja eine Zeitskala sein) und wenn ich die Aufrufzeit niedriger gesetzt habe, dann schaffte die Funktion das nicht rechtzeitig.
Das Ganze war extrem zeitkritisch und ich will mir gar nicht vorstellen, wie das auf langsameren Systemen aussieht.
Ich werde wohl noch ein Multiprozessing einbauen. Zwei Prozesse: einer für die Anzeige und einer für das Schreiben/Lesen.
Wobei ich da noch testen muss, ob das mit der Interprozesskommunikation (IPC) auch klappt. Ein erster Test mit einem versteckten Edit-Control war nicht erfolgreich. Da holte der eine Prozess gerade etwas ab, während der zweite Prozess in das Edit-Control schrieb.
Ich werde da doch mal Tests mit NamedPipes machen. BTW: Weiß jemand, ob NamedPipes einen Schreib-/Lesepuffer benutzen? Wenn nicht, wird das auch schon wieder kritisch...
Im vorliegenden Programm finde ich die Grafik schon gut! Ggf. Schreib/Leserate in zwei Fenstern nebeneinander. Die X-Achse sollte den gesamten ausgewählten Speicherplatz abbilden, dann wird das Fensterchen auch immer schön voll^^
Die Fortschritt-Grafik sollte nur einen ersten Überblick verschaffen.
Bei der Auswerte-Grafik (die ich momentan in Arbeit habe) werden beide Wertetabellen als Linien auf einer Grafik dargestellt. Das sieht schon ganz gut aus.
Ich skaliere dann die Werte auf die volle Breite. Das ist kein Problem!
Woran ich momentan noch hänge, sind zu viele Werte.
Solange die Anzahl der Werte die Pixel auf der X-Achse nicht überschreitet, ist ja noch alles ok, aber wenn es mehr Werte sind, als ich Pixel auf der X-Achse zur Verfügung habe, male ich quasi mehrmals auf der Stelle.
Da muss ich wohl mehrere Werte zu Einem reduzieren (Mittelwert bilden)...
es war nicht viel umzuschreiben (eigentlich nur die ASM-Codes und die DllCallAddress() ),
Ich danke Dir für Deine Mühe! ![]()
So kann es dann auch eine 64-Bit-Version geben.
Im Moment arbeite ich gerade an der Ausgabe-Grafik. Es soll ja nicht wirklich diese Zahlenwüste gespeichert werden. ![]()
Ich habe schon mit GDI+ eine schöne Grafik mit den beiden Testabläufen (schreiben/lesen) erstellt. Ich kann die auch beliebig skalieren.
Jetzt bin ich mir nur noch nicht sicher, wie das am Ende aussehen soll:
- als Text- und Grafikdatei (.txt und .png)
- als HTML- und Grafikdatei (.html und .png)
- als PDF-Datei (.pdf)
Ich tendiere zur PDF-Datei (schaue mir gerade die "MPDF_UDF.au3" an).
Was meint ihr? Welche Ausgabe bevorzugt ihr? Und in welcher Auflösung soll die Grafik sein?
Das gehört aber eigentlich zum Grundlagenwissen.
Insofern besteht da bei Dir etwas Nachholbedarf. Vielleicht mal hinsetzen und die Beispiele aus der Hilfe ausprobieren/verstehen?!
Einfach einen Leerstring zuweisen: $var = ""
Zum verketten von Strings benutzt man in AutoIt das "&"-Zeichen:
#include <Inet.au3>
TCPStartup()
Local $ip = StringRegExp($sFile, "\s+TCP\s+\d+\.\d+\.\d+\.\d+:\d+\s+(\d+\.\d+\.\d+\.\d+):\d+\s+HERGESTELLT", 3)
;folgende Arrays sind vorhanden:
;$ip[0] = 172.16.1.228
;$ip[1] = 172.16.2.45
;$ip[2] = 172.16.2.46
Local $sNames
For $i = 0 to Ubound($ip) -1
$sNames &= _TCPIpToName($ip[$i],0) & ', '
Next
$sNames = StringTrimRight($sNames, 2)
MsgBox (1,"Ausgabe", "Diese sind verbunden: " & $sNames)
TCPShutdown()
Alles anzeigen
zunächst einmal: Super Script!
Danke!
Ein 64-Bit-Modus würde gut zum Programm passen!
AssembleIt bzw FASM und auch die FASM.dll assemblieren ja 64-Bit-Code auch auf 32-Bit-Systemen.
Naja, aber damit wäre das Script dann nur auf x64-Rechnern lauffähig.
Ich benutze hier die Assembler-Routinen ja hauptsächlich, weil das füllen/testen des Buffers mit AutoIt zu lange dauern würde.
Mein, nicht optimierter, Assembler-Code ist bereits ein paar tausend Mal schneller als AutoIt das schaffen würde. Eine weitere Optimierung des Assembler-Codes bringt nicht viel, weil das in Relation zu dem übrigen AutoIt-Code nur noch ein paar Mikrosekunden sind.
Bei Messwerten von MegaByte pro Sekunde (mit nur 2 Nachkommastellen) geht das in der Messgenauigkeit unter. Mal abgesehen von dem "Windows-Einfluss".
Obwohl, dann kann man auch die Handvoll Zeilen direkt anpassen, sieht dann beim disassembeln auch "besser" aus
Du musst nicht disassembeln. Im Thread "https://autoit.de/index.php?thread/86236-bytemuster-zum-testen-der-laufwerksgeschwindigkeit/&postID=692725#post692725" hatte ich den Assembler-Code bereits gepostet.
Hier nochmal direkt:
#cs CheckBuffer
Use32 ; 32Bit Modus!
mov esi,[esp+4] ; esi = Buffer (Pointer)
mov edx,dword[esp+8] ; edx = Anzahl
mov eax,dword[esp+12] ; eax = Startwert
xor ecx,ecx ; ecx = counter (auf 0 setzen)
@loop: ; Hauptschleife
mov ebx,dword[esi+ecx*4] ; den Wert aus dem Buffer holen und in ebx speichern
cmp ebx,eax ; vergleichen, ob eax und ebx gleich sind
jne @end ; wenn Wert ungleich, dann Routine verlassen
xor eax,0xffffffff ; eax invertieren
inc ecx ; counter++
mov ebx,dword[esi+ecx*4] ; den Wert aus dem Buffer holen und in ebx speichern
cmp ebx,eax ; vergleichen, ob eax und ebx gleich sind
jne @end ; wenn Wert ungleich, dann Routine verlassen
xor eax,0xffffffff ; eax wieder zurueck invertieren
inc eax ; eax++
inc ecx ; counter++
cmp ecx,edx ; Vergleich Counter mit Anzahl
jb @loop ; wenn kleiner, dann Schleife @loop weiter ausfuehren
mov eax,0 ; kein Fehler, also 0 in eax laden (Rueckgabe an AutoIt)
ret
@end:
mov eax,ecx ; den Counter nach eax (Rueckgabe an AutoIt)
ret
#ce
#cs FillBuffer
Use32 ; 32Bit Modus!
mov esi,[esp+4] ; esi = Buffer (Pointer)
mov edx,dword[esp+8] ; edx = Anzahl
mov eax,dword[esp+12] ; eax = Startwert
xor ecx,ecx ; ecx = counter (auf 0 setzen)
@loop: ; Hauptschleife
mov dword[esi+ecx*4],eax ; den Wert von eax in den Buffer schreiben
xor eax,0xffffffff ; eax invertieren
inc ecx ; counter++
mov dword[esi+ecx*4],eax ; den invertierten Wert von eax in den Buffer schreiben
xor eax,0xffffffff ; eax wieder zurueck invertieren
inc eax ; eax++
inc ecx ; counter++
cmp ecx,edx ; Vergleich Counter mit Anzahl
jb @loop ; wenn kleiner, dann Schleife @loop weiter ausfuehren
ret
#ce
Alles anzeigen
Korrekt, im 32-Bit modus funktioniert es auch bei mir:
Ah! Gut, dann lag es nur daran.
warum die Speicherkarte im Lesen schlechtere Werte hat als beim Schreiben verstehe ich nicht.
Bei nur 1 GB Test-Speicherplatz ist das nicht so aussagekräftig. Versuch's mal mit 8 oder 12 GB.