Variable aus einem anderen laufenden AHK-Prozess einlesen

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

Stroker-007
Posts: 135
Joined: 28 Jan 2021, 17:09
Location: Germany

Variable aus einem anderen laufenden AHK-Prozess einlesen

03 Apr 2023, 00:32

Moin!

Irgendein Skript ist mittels Darstellung einer GUI permanent am Laufen und hält (u.a.) auch eine anfangs ermittelte Variable "PfadDatei" vorrätig.

Zusätzlich wird nun ein weiteres AHK-Skript gestartet, das diese Variable "PfadDatei" aus dem bereits laufenden 1. Skript verwenden und dafür eben irgendwie einlesen soll:

Code: Select all

...
send, %PfadDatei%, [aus Skript mit Fenstertitel XY, oder sonstwas ProzessID, ... , egal: was muß wie?]
...

Vermutlich ganz einfach, aber ich sitz wohl grad auf der Leitung.
Wer hilft mir bitte?
Rohwedder
Posts: 7774
Joined: 04 Jun 2014, 08:33
Location: Germany

Re: Variable aus einem anderen laufenden AHK-Prozess einlesen

03 Apr 2023, 00:55

Hallo,
leider nicht so einfach. Aber wenn es denn unbedingt sein muß, dann z.B. so:
viewtopic.php?f=6&t=3275
Last edited by Rohwedder on 03 Apr 2023, 05:20, edited 2 times in total.
just me
Posts: 9575
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Variable aus einem anderen laufenden AHK-Prozess einlesen

03 Apr 2023, 03:15

Oder so: https://ahkde.github.io/docs/v1/lib/OnMessage.htm#SendString

Und noch eine einfache Alternative:
Skript 1 schreibt den Inhalt der Variablen bei jeder Änderung in eine Datei. Wenn Skript 2 den Namen verwenden will, liest es vorher diese Datei.
Rohwedder
Posts: 7774
Joined: 04 Jun 2014, 08:33
Location: Germany

Re: Variable aus einem anderen laufenden AHK-Prozess einlesen

03 Apr 2023, 03:24

Oder so:

Code: Select all

; Skript 1
q::MsgBox,% Inhalt("Var1")
w::MsgBox,% Inhalt("Var2")
Inhalt(Name)
{ ;Skript1 fragt Skript2 bzgl. Variableninhalt
	ClipSicherung := ClipBoardAll
	ClipBoard := "Name:" Name
	SendLevel, 1
	SendInput, {vkFF}
	While, !InStr(ClipBoard, "Inhalt:")
		Sleep, 50
	Inhalt := StrReplace(ClipBoard, "Inhalt:")
	ClipBoard := ClipSicherung
	Return, Inhalt
}

Code: Select all

; Skript 2
Var1 = Hallo
Var2 = du da!
vkFF:: ;Skript1 fragt Skript2 bzgl. Variableninhalt
While, !InStr(ClipBoard, "Name:")
	Sleep, 50
Name := StrReplace(ClipBoard, "Name:")
ClipBoard := "Inhalt:" %Name%
Return
Stroker-007
Posts: 135
Joined: 28 Jan 2021, 17:09
Location: Germany

Re: Variable aus einem anderen laufenden AHK-Prozess einlesen

03 Apr 2023, 23:40

Schönen Dank für die Bemühungen!
Ist also nicht so einfach, die Sache, weil wohl die AHK-Götter es nicht als einfach vorgesehen haben.

@Rohwedder:
Dein letzter "Oder so" Vorschlag ist ein hübscher Ansatz, wenngleich im Verhältnis zur geplanten simplen Angelegenheit immer noch vergleichsweise aufwändig.

@just me:
Das mit dem Zwischlagern auf Masse ist schon klar, hab ich ja selbst auch favorisiert in "Textdatei im Hintergrund bearbeiten" viewtopic.php?f=9&t=113458, da war es sogar essentiell, wie dort ausgeführt. Im jetzigen Fall wäre es aber eher kontraproduktiv, weil auch die Möglichkeit mehrerer gleichzeitiger Bearbeitungsinstanzen besteht, die sich dann als Zwischenlager entweder eine FortKnox-Station teilen müßten und je nachdem auch drum schlagen dürften, oder ich muß mir wiederum ein aufwändiges Management mit mehreren Stationen ausdenken. Alles Goggolores...

Es geht um mehr Komfort bei der Videobearbeitung. Beim (AHK-Skript-)Aufruf einer Datei zur Bearbeitung werden vorher per MediaInfoCLI deren bearbeitungsrelevante Daten ermittelt, vor allem die originale Bitrate sowie Pfad+Datei, und dann bei der Bearbeitung in einer kleinen GUI am oberen Rand permanent eingeblendet, damit ich jederzeit Zugriff darauf habe, und zwischendurch nicht immer im Dateimanager per MediaInfoCLI-AHK-Skript nachschauen muß. Und dann wollte ich eben beim Einlesen per Mausgeste einer zusätzlichen Datei aus selbem Verzeichnis den bereits in dieser GUI-Skript hinterlegten PfadDatei mitverwenden, um nicht umständlich erst im Öffnen-Explorer-Fenster wühlen zu müssen.

Kommt noch dazu, daß ich öfters mehrere Schnittsitzungen mit Dateien aus unterschiedlichen Pfaden gleichzeitig am Laufen habe, weswegen ich, bzw. die Skripte, dann mit einer oder mehreren Austauschspeicherdateien so recht ins Schwitzen kommen könnte...

Weil das "Rüberlesen" von Variablen also eine extra Steilwandpartie zu sein scheint, liegt es in diesem Fall deutlich näher, einen Job wie das zusätzliche Einlesen an bekannter Pfadstelle gleich von dem sowieso schon offenen und per Dauer-GUI anwesenden Skript erledigen zu lassen: Entweder per Klick-Button, oder per Hotkey im Skript, der dann wiederum per gewohnter Mausgeste zum Vorgang bedient wird. Damit bin ich dann betreffs Daten und Variablen im Skript-Selbstversorgermodus.

Eine solche Lösung mit Klick-Button sieht jetzt probehalber mal so aus:

Code: Select all

#SingleInstance Force
#NoTrayIcon
SendMode input

OrgZwAbl := clipboard
Clipboard := ""
send ^2                 ; im TotalCommander Pfad+Datei in Zwischenablage 
ClipWait
PfadDatei := Clipboard
SplitPath, % PfadDatei, Datei, Verz,, Name

; zunächst Video-Daten sammeln:

clipboard := "" 
run %ComSpec% /c c:\P\MediaInfoCLI\MediaInfo.exe "--Output=Video;`%Width/String`%" "%PfadDatei%" | Clip, , hide
clipwait
Clipboard := StrReplace(Clipboard, "`r`n")
Clipboard := StrReplace(Clipboard, "pixels")
Width := clipboard

clipboard := "" 
run %ComSpec% /c c:\P\MediaInfoCLI\MediaInfo.exe "--Output=Video;`%Height/String`%" "%PfadDatei%" | Clip, , hide
clipwait
Clipboard := StrReplace(Clipboard, "`r`n")
Clipboard := StrReplace(Clipboard, "pixels")
Height := clipboard

clipboard := "" 
run %ComSpec% /c c:\P\MediaInfoCLI\MediaInfo.exe "--Output=Video;`%BitRate/String`%" "%PfadDatei%" | Clip, , hide
clipwait
Clipboard := StrReplace(Clipboard, "`r`n")
Clipboard := StrReplace(Clipboard, "kb/s")
BitRate := clipboard

clipboard := "" 
run %ComSpec% /c c:\P\MediaInfoCLI\MediaInfo.exe "--Output=Video;`%FrameRate/String`%" "%PfadDatei%" | Clip, , hide
clipwait
Clipboard := StrReplace(Clipboard, "`r`n")
PosZiffer := InStr(Clipboard, ".")
Clipboard := SubStr(Clipboard, 1, (PosZiffer + 1))
FrameRate := clipboard

run, c:\P\Vegas18\vegas180.exe "%PfadDatei%"   ; jetzt Schnittprogramm mit gewählter Datei starten
WinWait ahk_class Vegas.Class.Frame,, 8
if errorlevel = 1
   ExitApp

sleep 1000
send ^{home}     ; in der Timeline Cursor vom Ende an den Anfang setzen
sleep 1000

send ^s          ; Projekt speichern
WinWait, Speichern unter
send %Verz%\%Name%
sleep 1000
send {enter}

clipboard := OrgZwAbl

Gui, -Caption +AlwaysOnTop   ; Info- und Service-GUI starten 
Gui, Color, 232323
Gui, Font, s10 bold DDDDDD
Gui, Add, Text, x10 y9, %PfadDatei% 
Gui, Add, Text, x10 y30, %Width%x %Height%- %BitRate%- %FrameRate%
Gui, Add, Button, x230 y30 w140 h23, Datei importieren
Gui, Add, Button, x400 y30 w45 h23, Pfad
Gui, Show, x805 y8

WinActivate ahk_class Vegas.Class.Frame
Return

ButtonDateiimportieren:
WinActivate ahk_class Vegas.Class.Frame
send {ALT}
send d
sleep 50
send pm
send %Verz%
send {enter}
Return

ButtonPfad:
send !{tab}
sleep 100
send %Verz%
send {enter}
Return

GuiEscape:
GuiClose:
ExitApp
gero
Posts: 173
Joined: 02 Oct 2013, 05:36

Re: Variable aus einem anderen laufenden AHK-Prozess einlesen

04 Apr 2023, 18:00

Eigentlich ist das ein Fall für die Registry ... schreiben und lesen geht quasi in RealTime.

gruss
gero
Stroker-007
Posts: 135
Joined: 28 Jan 2021, 17:09
Location: Germany

Re: Variable aus einem anderen laufenden AHK-Prozess einlesen

05 Apr 2023, 18:54

Hallo gero, welch interessanter Ansatz, danke!

Aber prinzipiell ist es dasselbe Vorgehen wie das (Zwischen-)Lagern und Abrufen mittels Steuerdateien. Habe dafür systemweit ein Extra-Verz., das auch von meinen Batchskripten genutzt wird. Liegt auch daran, daß ich von Anfang NT4 bzw. win95 an ein Registry-Hasser, aber nachwievor ein INI-Befürworter, -Liebhaber und -Nutzer bin. Weg vom Zentralissmus. Skripter wie Ghisler mit TotalCommander oder auch Uwe Sieber sind ja gleichfalls auf dieser Linie.

Inzwischen finde ich aber durchaus Gefallen an meiner obigen Lösung, und bin jetzt dabei, das für mehrere gleichzeitige Instanzen des Schnittprogramms auszutüfteln, wo dann jede bei Aktiv-Schaltung sofort ihren eigenen - persönlichen - GUI-Coach mit nach vorne bringt und AlwaysOnTop setzt. Solange, bis die nächste Sitzung dran ist, ebenso mit IHREM immer noch offenen Coach... usw. Wenn ich´s nicht auf die Reihe kriege, mach ich dafür aber einen eigenen Thread auf.

Weil es grad paßt in Sachen Steuerdatei bzw. Infoauslagerung gebe ich hier noch ein kleines Gimick zum Besten. Eigentlich geht sowas bei der MsgBox gar nicht, weil diese ja immer ein genereller Stop im Ablauf ist. Aber "von außerhalb" und in vorauseilendem Gehorsam zur "Zeitlinie" :angel: :wave: geht es eben doch. Wie bei Hase und Igel. Ich nenne es meine "Sekundenfliege", obwohl es tatsächlich ja eine Micro-Sekundenfliege ist. Kann man immer wieder mal einbauen und ist einfach nur nett :dance:

Code: Select all

#SingleInstance Force

; Demo_SecFly.ahk
; Mauszeiger-Spitze in die Mitte z.B. des OK-Button einer "nachfolgenden" (oder vorausgegangenen? ?-o ) MsgBox bewegen

^!m::  ; nur zum Testen

; irgendein Skript ist am Laufen und will jetzt per MsgBox irgendwas anzeigen oder auswählen lassen:

FileAppend,
(
sleep 800   ; um der nachfolgenden MsgBox die Zeit zu geben, erst mal zu erscheinen, und zwecks Extra-Show
ControlGetPos, X, Y, b, h, Button1, A
MouseMove, X+b/2, Y+h/2
FileDelete c:\SecFly.ahk
), c:\SecFly.ahk
run c:\SecFly.ahk

MsgBox Na sowas!

; nachdem wunschgemäß geklickt wurde, geht das Skript weiter seinen Gang...
just me
Posts: 9575
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Variable aus einem anderen laufenden AHK-Prozess einlesen

07 Apr 2023, 05:34

Moin @Stroker-007,

wenn Du die MediaInfo.exe hast, hast Du vielleicht auch die MediaInfo.dll. Damit kannst Du die Informationen auch direkt innerhalb eines AHK-Skripts abgreifen:

Code: Select all

#NoEnv
SetWorkingDir, %A_ScriptDir%
MediaFile := A_ScriptDir . "\20-Black Night (Unedited Roger Glover Remix).mp3"
MediaFile := "D:\Downloads\Test\MahiruHino.mp4"
MI := New MediaInfo()
MI.Open(MediaFile)
Info := {}
For K, V In StrSplit("BitRate|Height|FrameRate|Width", "|")
   Info[V] := MI.Get("Video", V)
Msg := ""
For K, V In Info
   Msg .= K . " : " . V . "`r`n"
MsgBox, %Msg%
MsgBox, % MI.Inform()
Return
; ==================================================================================================
; Lade Dir die passende MediaInfo.dll (32/64-Bit) als Zip- oder 7Z-Archiv von
; https://mediaarea.net/de/MediaInfo/Download/Windows
; und lege sie ins Skriptverzeichnis.
; Der entpackte Download enthält im Unterverzeichnis Developers\List_Of_Parameters
; CSV-Dateien mit den möglichen Parameternamen.
; Die Datei Documentation.html im Unterverzeichnis Developers enthält eine minimale
; Dokumentation.
; ==================================================================================================
Class MediaInfo {
   Static Stream := {General: 0
                   , Video: 1
                   , Audio: 2
                   , Text: 3
                   , Chapters: 4
                   , Image: 5
                   , Menu: 6}
   Handle := 0
   Module := 0
   Opened := 0
   ; -----------------------------------------------------------------------------------------------
   __New() {
      If !(Module := DllCall("LoadLibrary", "Str", "MediaInfo.dll", "UPtr"))
         Throw Exception("Die MediaInfo.dll konnte nicht geladen werden!", -1)
      If !(Handle := DllCall("MediaInfo.dll\MediaInfo_New", "UPtr")) {
         DllCall("FreeLibrary", "Ptr", Module)
         Throw Exception("Die MediaInfo.dll konnte nicht initialisiert werden!", -1)
      }
      This.Module := Module
      This.Handle := Handle
   }
   ; -----------------------------------------------------------------------------------------------
   __Delete() {
      If (This.Opened)
         This.Close()
      If (This.Handle)
         This.Delete()
      If (This.Module)
         DllCall("FreeLibrary", "Ptr", Module)
   }
   ; -----------------------------------------------------------------------------------------------
   Open(MediaFile) {
      If !(This.Handle)
         Return False
      Return (This.Opened := DllCall("MediaInfo.dll\MediaInfo_Open", "Ptr", This.Handle
                                                                   , "Str", MediaFile
                                                                   , "UPtr"))
   }
   ; -----------------------------------------------------------------------------------------------
   Get(Stream, Param) {
      If !(This.Handle) || !(This.Opened)
         Return ""
      If !This.Stream.HasKey(Stream)
         Return ""
      Return DllCall("MediaInfo.dll\MediaInfo_Get", "Ptr", This.Handle
                                                  , "UInt", This.Stream[Stream]
                                                  , "UInt", 0
                                                  , "Str", Param
                                                  , "UInt", 1
                                                  , "UInt", 0
                                                  , "Str")
   }
   ; -----------------------------------------------------------------------------------------------
   Inform() {
      If !(This.Handle) || !(This.Opened)
         Return False
      Return DllCall("MediaInfo.dll\MediaInfo_Inform", "Ptr", This.Handle
                                                     , "UInt", 0
                                                     , "Str")
   }
   ; -----------------------------------------------------------------------------------------------
   Close() {
      If (This.Opened)
         DllCall("MediaInfo.dll\MediaInfo_Close")
      This.Opened := 0
      Return True
   }
   ; -----------------------------------------------------------------------------------------------
   Delete() {
      If (This.Opened)
         This.Close()
      If (This.Handle)
         DllCall("MediaInfo.dll\MediaInfo_Delete", "Ptr", This.Handle)
      This.Handle := 0
      Return True
   }
}
Wenn Dir das mit der Klasse nicht behagt, kann ich auch Funktionen bereitstellen.

Zum Thema MsgBox:
Wenn Du eine MsgBox aus dem eigenen Skript bearbeiten/verändern willst, geht das auch mit einem Timer.
Stroker-007
Posts: 135
Joined: 28 Jan 2021, 17:09
Location: Germany

Re: Variable aus einem anderen laufenden AHK-Prozess einlesen

08 Apr 2023, 16:40

@just me:
Donnerwetter, das erschlägt mich jetzt aber. Steig ich auf die Schnelle noch nicht durch.

Was das weiter unten mit der MsgBox und dem Timer betrifft, geht das schon eher.
Du meinst wohl so:

Code: Select all

#SingleInstance Force

^!m::

SetTimer, TimerFly, -800

MsgBox Na sowas!

TimerFly:
ControlGetPos, X, Y, b, h, Button1, A
MouseMove, X+b/2, Y+h/2

if not WinExist(, "Na sowas!")  ; Zusätzlich nötig bei TimerFly, wenn das Skript danach weiterlaufen soll,
   MsgBox Erstaunlich...        ; SecFly braucht das nicht...

Und dann noch, wenn ich beide Varianten abwechselnd im Vergleich teste, dann läuft die TimerFly etwas holpriger, weil sie die Maus vor dem OK-Button immer erst noch einen Haken schlagen läßt, indem sie zunächst die Mitte der MsgBox ansteuert, während die SecFly-Maus den OK-Button direkt ansteuert und damit angenehm rund läuft:

Code: Select all

#SingleInstance Force

^!m::

FileAppend,
(
sleep 800   ; um der nachfolgenden Msg-Box die Zeit zu geben, erst mal zu erscheinen, und zwecks Extra-Show
ControlGetPos, X, Y, b, h, Button1, A
MouseMove, X+b/2, Y+h/2
FileDelete c:\SecFly.ahk
), c:\SecFly.ahk
run c:\SecFly.ahk

MsgBox Na sowas!

MsgBox Erstaunlich...  ; Skript läuft normal weiter ohne zusätzliche Direktiven 

Fröhliches Eiersuchen!
just me
Posts: 9575
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Variable aus einem anderen laufenden AHK-Prozess einlesen

09 Apr 2023, 03:08

@Stroker-007,

ich meinte das etwa so:

Code: Select all

#SingleInstance Force

^!m::

SetTimer, TimerFly, -800

MsgBox Na sowas!

MsgBox Hier geht es weiter!
Return

TimerFly:
ControlGetPos, X, Y, b, h, Button1, A
MouseMove, X+b/2, Y+h/2, 0
Return

; Das Folgende verstehe ich nicht:
; if not WinExist(, "Na sowas!")  ; Zusätzlich nötig bei TimerFly, wenn das Skript danach weiterlaufen soll,
;    MsgBox Erstaunlich...        ; SecFly braucht das nicht...
Wenn Dir die Klasse zu kompliziert erscheint und Du immer nur dieselben Informationen per MediaInfo abgreifen willst, kann ich das auch in eine einzelne Funktion packen, der nur der Dateipfad und die Parameternamen übergeben werden.

Frohe Ostern!
Stroker-007
Posts: 135
Joined: 28 Jan 2021, 17:09
Location: Germany

Re: Variable aus einem anderen laufenden AHK-Prozess einlesen

09 Apr 2023, 14:20

@just me

Danke für Deine Ausformulierung der Timer-Fliege, denn genau daruf bin ich trotz Rumprobieren nicht gekommen. Nämlich, daß (ähnlich wie beim GUI-Prinzip) erst der Hauptlauf des Skripts angeführt und mit Return abgeschlossen werden muß, und erst danach eventuelle Arbeitsblöcke (wie hier "TimerFly:") kommen dürfen, die ihrerseits auch wieder mit Return zu integrieren sind. Denn bei mir hatte sich ständig die 2. MsgBox "vorgedrängt", oder es ist gar nichts passiert, je nachdem. Hatte das beispielsweise so:

Code: Select all

#SingleInstance Force

^!m::

SetTimer, TimerFly, -800

MsgBox Na sowas!

TimerFly:
ControlGetPos, X, Y, b, h, Button1, A
MouseMove, X+b/2, Y+h/2
;Return  ; hat auch nicht geholfen

MsgBox Hier geht´s weiter


; if not WinExist(, "Na sowas!")  ;  ...war dann mein kreatives Workaround, um den gewollten Skriptfluß doch noch irgendwie hinzukriegen. 
;    MsgBox Hier geht´s weiter  ;  hat ja auch funktioniert, in Ermangelung meines Wissens, wie man einen Timer korrekt laufen läßt.
Also danke Dir, daß Du mir gezeigt hast, wie so eine Timer-Nummer wirklich funktioniert, wenn es danach weitergehen soll.

Aber was das andere mit MediaInfo betrifft, weiß ich jetzt nicht genau, wie Du das meinst:
...kann ich das auch in eine einzelne Funktion packen

Heißt "ich" hier soviel wie "man" und ich soll mich doch hurtig selber dranmachen, oder bezieht sich sich dieses "ich" auf Dich selbst und Du bietest mir an, mir ein für meine Anwendung passendes Skript zu erstellen, wohl wissend, daß ich noch weit davon entfernt bin, das in dieser demonstrierten Art selbst machen zu können, also über diese DLL ?
just me
Posts: 9575
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Variable aus einem anderen laufenden AHK-Prozess einlesen

10 Apr 2023, 03:06

Moin @Stroker-007,

"ich" bedeutet hier einfach "ich". Ich habe das jetzt mal in eine Funktion gepackt, in der die angeforderten Parameter (BitRate, FrameRate, Height und Width) fest verdrahtet sind. Es ist wegen der DllCalls immer noch kompliziert genug, ist aber vielleicht nicht ganz so 'einschüchternd' wie die Klasse. Du brauchst dafür die zu Deiner AHK-Version (32/64-Bit) passende Mediainfo.dll im Skriptverzeichnis oder im Systemverzeichnis. Alternativ kannst Du im DllCall "LoadLibrary" einen kompletten Pfad vorgeben. Die Funktion funktioniert nur mit AHK Unicode.

Code: Select all

#NoEnv
SetWorkingDir, %A_ScriptDir%
MediaFile := "PfadZuEinerVideoDatei" ; <<<<<
Info := MediaInfo_GetInfo(MediaFile)
Msg := Info.Bitrate . "`n"
     . Info.FrameRate . "`n"
     . Info.Height . "`n"
     . Info.Width
MsgBox, %Msg%
Return

; ==================================================================================================
; Lade Dir die passende MediaInfo.dll (32/64-Bit) als Zip- oder 7Z-Archiv von
; https://mediaarea.net/de/MediaInfo/Download/Windows
; und lege sie ins Skriptverzeichnis.
; Der entpackte Download enthält im Unterverzeichnis Developers\List_Of_Parameters
; CSV-Dateien mit den möglichen Parameternamen.
; Die Datei Documentation.html im Unterverzeichnis Developers enthält eine minimale
; Dokumentation.
; Mediainfo Streams:
; MediaInfo_Stream_General = 0
; MediaInfo_Stream_Video   = 1
; MediaInfo_Stream_Audio   = 2
; MediaInfo_Stream_Text    = 3
; MediaInfo_Stream_Other   = 4 (Chapters)
; MediaInfo_Stream_Image   = 5
; MediaInfo_Stream_Menu    = 6
; ==================================================================================================
MediaInfo_GetInfo(FilePath) {
   Static Stream := 1 ; entspricht Video in --Output=Video;%Width/String%
   Handle := 0
   Module := 0
   If !(Module := DllCall("LoadLibrary", "Str", "MediaInfo.dll", "UPtr"))
      Throw Exception("Die MediaInfo.dll konnte nicht geladen werden!", -1)
   If !(Handle := DllCall("MediaInfo.dll\MediaInfo_New", "UPtr")) {
      DllCall("FreeLibrary", "Ptr", Module)
      Throw Exception("Die MediaInfo.dll konnte nicht initialisiert werden!", -1)
   }
   If !DllCall("MediaInfo.dll\MediaInfo_Open", "Ptr", Handle
                                             , "Str", FilePath
                                             , "UPtr") {
      DllCall("MediaInfo.dll\MediaInfo_Delete", "Ptr", Handle)
      DllCall("FreeLibrary", "Ptr", Module)
      Throw Exception("Die Datei " . FilePath . " konnte nicht geöffnet werden!", -1)
   }
   Result := {}
   For I, Param In StrSplit("BitRate|Height|FrameRate|Width", "|")
      Result[Param] :=  DllCall("MediaInfo.dll\MediaInfo_Get", "Ptr", Handle
                                                             , "UInt", 1
                                                             , "UInt", 0
                                                             , "Str", Param
                                                             , "UInt", 1
                                                             , "UInt", 0
                                                             , "Str")
   DllCall("MediaInfo.dll\MediaInfo_Close")
   DllCall("MediaInfo.dll\MediaInfo_Delete", "Ptr", Handle)
   DllCall("FreeLibrary", "Ptr", Module)
   Return Result
}
effel
Posts: 555
Joined: 16 Jan 2018, 13:34

Re: Variable aus einem anderen laufenden AHK-Prozess einlesen

13 Apr 2023, 14:36

Hallo

ich bin etwas verwirrt, weil ich mit meinem Script unterschiedliche Ergebnisse erziele.

Wenn ich via FileSelectFolder zu den Dateien gehe, dann funktioniert es nur wenn ich mein Script so : For K, thisMediaFile In StrSplit(thisFileList, "`n") nutze, wenn ich eine Datei als Quelle nutze funktioniert es nur wenn ich es so: For K, thisMediaFile In StrSplit(thisFileList, "`r", "`n") schreibe.

Dann habe ich festgestellt, das der MD5 Wert bei der gleichen Datei unterschiedliche Werte bringt.

Was mache ich falsch?

Danke fürs lesen


Code: Select all

; Variable aus einem anderen laufenden AHKProzess einlesen
; https://www.autohotkey.com/boards/viewtopic.php?f=9&t=115685

#NoEnv
SetWorkingDir, %A_ScriptDir%
#SingleInstance force
;#Persistent
FileEncoding, UTF-8
SetBatchLines, -1
SetTitleMatchMode, 2
SetKeyDelay 20
ANow := A_Now
If !FileExist(A_ScriptDir "\save\")
FileCreateDir,% A_ScriptDir "\save\"
FileCopy, % A_ScriptFullPath, % A_ScriptDir "\save\" A_ScriptName " save " A_Now " .ahk"
;##########################################################################################################

audio 			:= "|aac|ac3|aif|aifc|aiff|au|cda|dts|fla|flac|it|m1a|m2a|m3u|m4a|mid|midi|mka|mod|mp2|mp3|mpa|ogg|ra|rmi|spc|rmi|snd|umx|voc|wav|wma|xm|"
bilder 			:= "|ani|bmp|gif|ico|jpe|jpeg|jpg|pcx|png|psd|tga|tif|tiff|wmf|"
videos 			:= "|3g2|3gp|3gp2|3gpp|amr|amv|asf|avi|bdmv|bik|d2v|divx|drc|dsa|dsm|dss|dsv|evo|f4v|flc|fli|flic|flv|hdmov|ifo|ivf|m1v|m2p|m2t|m2ts|m2v|m4b|m4p|m4v|mkv|mp2v|mp4|mp4v|mpe|mpeg|mpg|mpls|mpv2|mpv4|mov|mts|ogm|ogv|pss|pva|qt|ram|ratdvd|rm|rmm|rmvb|roq|rpm|smil|smk|swf|tp|tpr|ts|vob|vp6|webm|wm|wmp|wmv|"
Ausführbare_Dateien	:= "|bat|cmd|exe|msi|msp|scr|com|"
Dokumente 		:= "|c|chm|cpp|csv|cxx|doc|docm|docx|dot|dotm|dotx|h|hpp|htm|html|hxx|ini|java|lua|mht|mhtml|odt|pdf|potx|potm|ppam|ppsm|ppsx|pps|ppt|pptm|pptx|rtf|sldm|sldx|thmx|txt|vsd|wpd|wps|wri|xlam|xls|xlsb|xlsm|xlsx|xltm|xltx|xml|"
Archive 		:= "|7z|ace|arj|bz2|cab|gz|gzip|jar|r00|r01|r02|r03|r04|r05|r06|r07|r08|r09|r10|r11|r12|r13|r14|r15|r16|r17|r18|r19|r20|r21|r22|r23|r24|r25|r26|r27|r28|r29|rar|tar|tgz|z|zip|"

   allMedia 	:= audio bilder videos 
   TrueFileExt 	:= allMedia
   thisFileList	:= ""
   FilesMD5	:= ""

   FileSelectFolder, QuellPfad, , 3, Verzeichnis auswählen
   if !QuellPfad 
   goto LoadFileList

   Loop, Files, %QuellPfad%\*.*, FR   
  {
  If TrueFileExt contains |%A_LoopFileExt%|  
  {
  FileGetSize, FileSize, %A_LoopFilePath%		; MD5 erzeugen
  thisMD5	:= Calc_MD5(&A_LoopFilePath,FileSize)	; MD5 erzeugen
  FilesMD5	.= thisMD5 a_tab A_LoopFilePath "`n"
  thisFileList	.= A_LoopFilePath "`n"
   }}

  ANow := A_Now
  FileAppend,% FilesMD5    ,% A_ScriptDir "\" ANow A_Space " FilesMD5.txt"
; FileAppend,% thisFileList,% A_ScriptDir "\" ANow A_Space " thisFileList.txt"

LoadFileList:
  if !thisFileList 
  {
  Files := "O:\mediainfo\testDateiListe.txt"
  FileRead, thisFileList,% Files
   }

	thisCounter := 0
;	For K, thisMediaFile In StrSplit(thisFileList, "`r`n")     ; funktioniert via LoadFileList:
;	For K, thisMediaFile In StrSplit(thisFileList, "`r", "`n") ; funktioniert via LoadFileList:
	For K, thisMediaFile In StrSplit(thisFileList, "`n")       ; funktioniert via QuellPfad 
	{
	if !thisMediaFile
	continue
	if fileExist(thisMediaFile ".txt")
	continue
	FileGetSize, FileSize, %thisMediaFile%		; MD5 erzeugen
	thisMD5	:= Calc_MD5(&thisMediaFile,FileSize)	; MD5 erzeugen
	FilesMD5	:= thisMD5 "`n"
	MI := New MediaInfo()
	MI.Open(thisMediaFile)
	Info := {}
	For K, V In StrSplit("BitRate|Height|FrameRate|Width", "|")
	   Info[V] := MI.Get("Video", V)
	res := ""
	For K, V In Info
	   res .= K . " : " . V . "`n"
	fileAppend, % "File MD5 : " FilesMD5 "`n" MI.Inform() "`n" res "`n",% thisMediaFile ".txt"
	if !errorlevel
	thisCounter++
	}

msgBox,% thisCounter " Files`nDone"
Return

;##########################################################################################################

; ==================================================================================================
; Lade Dir die passende MediaInfo.dll (32/64-Bit) als Zip- oder 7Z-Archiv von
; https://mediaarea.net/de/MediaInfo/Download/Windows
; und lege sie ins Skriptverzeichnis.
; Der entpackte Download enthält im Unterverzeichnis Developers\List_Of_Parameters
; CSV-Dateien mit den möglichen Parameternamen.
; Die Datei Documentation.html im Unterverzeichnis Developers enthält eine minimale
; Dokumentation.
; ==================================================================================================
Class MediaInfo {
   Static Stream := {General: 0
                   , Video: 1
                   , Audio: 2
                   , Text: 3
                   , Chapters: 4
                   , Image: 5
                   , Menu: 6}
   Handle := 0
   Module := 0
   Opened := 0
   ; -----------------------------------------------------------------------------------------------
   __New() {
      If !(Module := DllCall("LoadLibrary", "Str", "MediaInfo.dll", "UPtr"))
         Throw Exception("Die MediaInfo.dll konnte nicht geladen werden!", -1)
      If !(Handle := DllCall("MediaInfo.dll\MediaInfo_New", "UPtr")) {
         DllCall("FreeLibrary", "Ptr", Module)
         Throw Exception("Die MediaInfo.dll konnte nicht initialisiert werden!", -1)
      }
      This.Module := Module
      This.Handle := Handle
   }
   ; -----------------------------------------------------------------------------------------------
   __Delete() {
      If (This.Opened)
         This.Close()
      If (This.Handle)
         This.Delete()
      If (This.Module)
         DllCall("FreeLibrary", "Ptr", Module)
   }
   ; -----------------------------------------------------------------------------------------------
   Open(MediaFile) {
      If !(This.Handle)
         Return False
      Return (This.Opened := DllCall("MediaInfo.dll\MediaInfo_Open", "Ptr", This.Handle
                                                                   , "Str", MediaFile
                                                                   , "UPtr"))
   }
   ; -----------------------------------------------------------------------------------------------
   Get(Stream, Param) {
      If !(This.Handle) || !(This.Opened)
         Return ""
      If !This.Stream.HasKey(Stream)
         Return ""
      Return DllCall("MediaInfo.dll\MediaInfo_Get", "Ptr", This.Handle
                                                  , "UInt", This.Stream[Stream]
                                                  , "UInt", 0
                                                  , "Str", Param
                                                  , "UInt", 1
                                                  , "UInt", 0
                                                  , "Str")
   }
   ; -----------------------------------------------------------------------------------------------
   Inform() {
      If !(This.Handle) || !(This.Opened)
         Return False
      Return DllCall("MediaInfo.dll\MediaInfo_Inform", "Ptr", This.Handle
                                                     , "UInt", 0
                                                     , "Str")
   }
   ; -----------------------------------------------------------------------------------------------
   Close() {
      If (This.Opened)
         DllCall("MediaInfo.dll\MediaInfo_Close")
      This.Opened := 0
      Return True
   }
   ; -----------------------------------------------------------------------------------------------
   Delete() {
      If (This.Opened)
         This.Close()
      If (This.Handle)
         DllCall("MediaInfo.dll\MediaInfo_Delete", "Ptr", This.Handle)
      This.Handle := 0
      Return True
   }
}

;##########################################################################################################

; https://autohotkey.com/board/topic/77408-md5-function-for-comparing-images/
Calc_MD5(_VarAddress, _VarSize){
	Static Hex = "123456789ABCDEF0"
	Ptr := A_PtrSize ? "Ptr" : "Uint"
	, VarSetCapacity(MD5_CTX,104,0)
	, DllCall("advapi32\MD5Init",Ptr,&MD5_CTX)
	, DllCall("advapi32\MD5Update",Ptr,&MD5_CTX,Ptr,_VarAddress,"UInt",_VarSize)
	, DllCall("advapi32\MD5Final",Ptr,&MD5_CTX)
	Loop,16
	N := NumGet( MD5_CTX,87+A_Index,"Char"), MD5 .= SubStr(Hex,N>>4,1) . SubStr(Hex,N&15,1)
	Return MD5
}



Beispiel für unterschiedliche MD5 Werte für die gleiche Datei


04_14_23 @12_12_43.PNG
04_14_23 @12_12_43.PNG (48.92 KiB) Viewed 798 times
just me
Posts: 9575
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Variable aus einem anderen laufenden AHK-Prozess einlesen

14 Apr 2023, 05:35

Moin @effel,
Wenn ich via FileSelectFolder zu den Dateien gehe, dann funktioniert es nur wenn ich mein Script so : For K, thisMediaFile In StrSplit(thisFileList, "`n") nutze, wenn ich eine Datei als Quelle nutze funktioniert es nur wenn ich es so: For K, thisMediaFile In StrSplit(thisFileList, "`r", "`n") schreibe.
Wenn Du die Dateien via FileSelectFolder einliest, erstellst Du die Dateiliste so:

Code: Select all

thisFileList .= A_LoopFilePath "`n"
Es ist damit nicht verwunderlich, wenn der StrSplit() mit einem einfachen `n funktioniert.

Wenn Du die Dateiliste aus einer Datei einliest, sind deren Zeilen höchstwahrscheinlich durch die Windows-Standardzeilentrennung `r`n getrennt. Deshalb funktionieren hier sowohl

Code: Select all

StrSplit(thisFileList, "`r`n")
als auch

Code: Select all

StrSplit(thisFileList, "`r", "`n")
Du bist allerdings unter Windows mit maximaler Wahrscheinlichkeit immer auf der sicheren Seite, wenn Du

Code: Select all

StrSplit(thisFileList, "`n", "`r")
verwendest. Damit wird immer bei `n gesplittet und ein `r wird entfernt, so es denn vorhanden ist. Das einzelne `r als Zeilentrennung gibt/gab es nur auf dem Mac.

Zum Theme MD5:
Die Prüfsumme muss über den Dateinhalt gebildet werden, nicht über den Namen. Dazu musst Du die Dateien einlesen

Code: Select all

FileRead, Inhalt, *C Dateiname
und dann &Inhalt an die Funktion übergeben. Bei den internen Variablen weiß ich nicht, ob der Adressoperator bei z.B. &A_LoopFilePath überhaupt einen sinnvollen Wert liefert.
effel
Posts: 555
Joined: 16 Jan 2018, 13:34

Re: Variable aus einem anderen laufenden AHK-Prozess einlesen

17 Apr 2023, 17:30

Danke Just Me


Code: Select all

#NoEnv
SetWorkingDir, %A_ScriptDir%
#SingleInstance force
;#Persistent
FileEncoding, UTF-8
SetBatchLines, -1
SetTitleMatchMode, 2
SetKeyDelay 20
;##########################################################################################################
; https://www.autohotkey.com/boards/viewtopic.php?f=9&t=115685

global iteration := 0		; test

Gui, New, +hwndhGUIA +E0x20 ; +AlwaysOnTop +Owner +LastFound +Border +Caption +Resize -ToolWindow, control
Gui, Font, 	s10
Gui, Add, Tab3,,Home|Statistik
Gui, Tab, 1
Gui, Add, ListView,% "w" A_ScreenWidth-430 " r20 vLV gLV +LV0x00010000 Section", Count|Iterum|MD5|Medium|Speicherort
Gui, Add, Button, Section w160 gEditScript,% Chr(0xE115) " Edit Script"
Gui, Add, Button, ys w160    gPauseScript vPauseScript, Pause
Gui, Add, Button, ys w160 gClearListView, ClearListView
;Gui, Tab, 2
Gui, Show,% " w" A_ScreenWidth-380 " h" A_ScreenHeight-450,% a_scriptName

GuiControl , Choose , systabcontrol321 , 1

audio 			:= "|aac|ac3|aif|aifc|aiff|au|cda|dts|fla|flac|it|m1a|m2a|m3u|m4a|mid|midi|mka|mod|mp2|mp3|mpa|ogg|ra|rmi|spc|rmi|snd|umx|voc|wav|wma|xm|"
bilder 			:= "|ani|bmp|gif|ico|jpe|jpeg|jpg|pcx|png|psd|tga|tif|tiff|wmf|"
videos 			:= "|3g2|3gp|3gp2|3gpp|amr|amv|asf|avi|bdmv|bik|d2v|divx|drc|dsa|dsm|dss|dsv|evo|f4v|flc|fli|flic|flv|hdmov|ifo|ivf|m1v|m2p|m2t|m2ts|m2v|m4b|m4p|m4v|mkv|mp2v|mp4|mp4v|mpe|mpeg|mpg|mpls|mpv2|mpv4|mov|mts|ogm|ogv|pss|pva|qt|ram|ratdvd|rm|rmm|rmvb|roq|rpm|smil|smk|swf|tp|tpr|ts|vob|vp6|webm|wm|wmp|wmv|"
Ausführbare_Dateien	:= "|bat|cmd|exe|msi|msp|scr|com|"
Dokumente 		:= "|c|chm|cpp|csv|cxx|doc|docm|docx|dot|dotm|dotx|h|hpp|htm|html|hxx|ini|java|lua|mht|mhtml|odt|pdf|potx|potm|ppam|ppsm|ppsx|pps|ppt|pptm|pptx|rtf|sldm|sldx|thmx|txt|vsd|wpd|wps|wri|xlam|xls|xlsb|xlsm|xlsx|xltm|xltx|xml|"
Archive 		:= "|7z|ace|arj|bz2|cab|gz|gzip|jar|r00|r01|r02|r03|r04|r05|r06|r07|r08|r09|r10|r11|r12|r13|r14|r15|r16|r17|r18|r19|r20|r21|r22|r23|r24|r25|r26|r27|r28|r29|rar|tar|tgz|z|zip|"

   allMedia 	:= audio videos 
   TrueFileExt 	:= allMedia

   thisFileList	:= ""
   QuellPfad	:= ""
   thisANow 	:= A_Now

   FileSelectFolder, QuellPfad, , , Verzeichnis auswählen
   if QuellPfad
   {
   Loop, Files, %QuellPfad%\*.*, FR   
   If TrueFileExt contains |%A_LoopFileExt%|  
   thisFileList	.= A_LoopFilePath "`n"
    }else{
	ExitApp
   }

		thisCounter := 0
		For K, thisMediaFile In StrSplit(thisFileList, "`n", "`r")
		{
		if !thisMediaFile
		continue
		if fileExist(thisMediaFile ".txt")
		continue

		 setTimer, thisToolTip, 500
		 
		 thisMD5 := 					; MD5 erzeugen
		 thisMD5 := File_MD5(thisMediaFile, iteration)	; MD5 erzeugen
	         thisFile := thisMD5 a_tab thisMediaFile "`n"
	         FileAppend,% thisFile ,% A_ScriptDir "\" thisANow A_Space " SessionFileList.txt"

			MI := New MediaInfo()
			MI.Open(thisMediaFile)

			Info := {}
			For K, V In StrSplit("BitRate|Height|FrameRate|Width", "|")
			   Info[V] := MI.Get("Video", V)

			res := ""
			For K, V In Info
			   res .= K . " : " . V . "`n"
			FileAppend, % "Hash`nFile MD5 `t`t`t`t : " thisMD5 "`n`n" MI.Inform() "`n" res "`n",% thisMediaFile ".txt"
			   if !errorlevel
			   thisCounter++

		    GuiControl, -ReDraw, LV
		tooltipText := thisMediaFile
		split := strSplit(thisMediaFile, "\")
		verzeichnis := strReplace( thisMediaFile, split[split.length()])
		LV_Modify(LV_Add("", thisCounter, iteration, thisMD5, split[split.length()], verzeichnis, ""), "Vis")
		    Loop, % LV_GetCount("Columns")
		    LV_ModifyCol(A_Index, "AutoHdr")
		    GuiControl, +Redraw, LV
		iteration := 0
		setTimer, thisToolTip, off
		SplashTextOff
	}



msgBox,% thisCounter " Files`nDone"
Return

thisToolTip:
SplashTextOn,% (A_ScreenWidth-500),,% "MD5: " thisMediaFile "   :   " iteration
return

LV:
Gui, Submit, nohide
thisCounter := 0
LV_Delete()
return

EditScript:
try run, notepad.exe %A_ScriptName%
return

ClearListView:
Gui, Default 
LV_Delete()
return

Pause::Pause ; , Toggle ; Die PAUSE/UNTBR-Taste.

PauseScript: 
Pause
return
;##########################################################################################################

; ==================================================================================================
; Lade Dir die passende MediaInfo.dll (32/64-Bit) als Zip- oder 7Z-Archiv von
; https://mediaarea.net/de/MediaInfo/Download/Windows
; und lege sie ins Skriptverzeichnis.
; Der entpackte Download enthält im Unterverzeichnis Developers\List_Of_Parameters
; CSV-Dateien mit den möglichen Parameternamen.
; Die Datei Documentation.html im Unterverzeichnis Developers enthält eine minimale
; Dokumentation.
; ==================================================================================================
Class MediaInfo {
   Static Stream := {General: 0
                   , Video: 1
                   , Audio: 2
                   , Text: 3
                   , Chapters: 4
                   , Image: 5
                   , Menu: 6}
   Handle := 0
   Module := 0
   Opened := 0
   ; -----------------------------------------------------------------------------------------------
   __New() {
      If !(Module := DllCall("LoadLibrary", "Str", "MediaInfo.dll", "UPtr"))
         Throw Exception("Die MediaInfo.dll konnte nicht geladen werden!", -1)
      If !(Handle := DllCall("MediaInfo.dll\MediaInfo_New", "UPtr")) {
         DllCall("FreeLibrary", "Ptr", Module)
         Throw Exception("Die MediaInfo.dll konnte nicht initialisiert werden!", -1)
      }
      This.Module := Module
      This.Handle := Handle
   }
   ; -----------------------------------------------------------------------------------------------
   __Delete() {
      If (This.Opened)
         This.Close()
      If (This.Handle)
         This.Delete()
      If (This.Module)
         DllCall("FreeLibrary", "Ptr", Module)
   }
   ; -----------------------------------------------------------------------------------------------
   Open(MediaFile) {
      If !(This.Handle)
         Return False
      Return (This.Opened := DllCall("MediaInfo.dll\MediaInfo_Open", "Ptr", This.Handle
                                                                   , "Str", MediaFile
                                                                   , "UPtr"))
   }
   ; -----------------------------------------------------------------------------------------------
   Get(Stream, Param) {
      If !(This.Handle) || !(This.Opened)
         Return ""
      If !This.Stream.HasKey(Stream)
         Return ""
      Return DllCall("MediaInfo.dll\MediaInfo_Get", "Ptr", This.Handle
                                                  , "UInt", This.Stream[Stream]
                                                  , "UInt", 0
                                                  , "Str", Param
                                                  , "UInt", 1
                                                  , "UInt", 0
                                                  , "Str")
   }
   ; -----------------------------------------------------------------------------------------------
   Inform() {
      If !(This.Handle) || !(This.Opened)
         Return False
      Return DllCall("MediaInfo.dll\MediaInfo_Inform", "Ptr", This.Handle
                                                     , "UInt", 0
                                                     , "Str")
   }
   ; -----------------------------------------------------------------------------------------------
   Close() {
      If (This.Opened)
         DllCall("MediaInfo.dll\MediaInfo_Close")
      This.Opened := 0
      Return True
   }
   ; -----------------------------------------------------------------------------------------------
   Delete() {
      If (This.Opened)
         This.Close()
      If (This.Handle)
         DllCall("MediaInfo.dll\MediaInfo_Delete", "Ptr", This.Handle)
      This.Handle := 0
      Return True
   }
}

;##########################################################################################################

; basiert auf https://autohotkey.com/board/topic/77408-md5-function-for-comparing-images/
; https://www.autohotkey.com/boards/viewtopic.php?p=262628#p262628 ; danke just me
File_MD5(FilePath,ByRef iteration) {
   Static MaxSize := 64 * 1024 * 1024 ; 64 MB 
   MD5 := ""
   If !(File := FileOpen(FilePath, "r"))
      Return "" ; hier vielleicht noch eine aussagekräftigere Fehlerbehandlung einfügen
   File.Pos := 0
   FileSize := File.Length
   VarSetCapacity(MD5_CTX, 104, 0)
   DllCall("Advapi32.dll\MD5Init", "Ptr", &MD5_CTX)
   While (FileSize > MaxSize) {
      File.RawRead(Buffer, MaxSize)
      DllCall("Advapi32.dll\MD5Update", "Ptr", &MD5_CTX, "Ptr", &Buffer, "UInt", MaxSize)
      FileSize -= MaxSize
      iteration++
   }
   File.RawRead(Buffer, FileSize)
   DllCall("Advapi32.dll\MD5Update", "Ptr", &MD5_CTX, "Ptr", &Buffer, "UInt", FileSize)
   DllCall("Advapi32.dll\MD5Final", "Ptr", &MD5_CTX)
   File.CLose()
   Loop, 16
      MD5 .= Format("{:02X}", NumGet(MD5_CTX, 87 + A_Index, "UChar"))
   Return MD5
}

Return to “Ich brauche Hilfe”

Who is online

Users browsing this forum: No registered users and 30 guests