Hallo Leute,
ich hab hier ein Problem das ich nicht verstehe. Hab schon so mega viel getestet, aber ich versteh nicht warum es nicht klappt ..
Erstmal etwas hinführendes:
Wenn man in Windows ein Programm im Contextmenü von Dateien registriert und mehrere Dateien selektiert und dann den Befehl ausführt, wird das registrierte Programm mehrfach gestartet, anstatt einmal. Hierbei wird immer die selektierte Datei als Parameter übergeben. Also muss man hier ein Workaround machen. Es geht leider wirklich nicht anders ..
Man könnte jetzt den Parameter den Windows übergibt in eine Datei schreiben und das Hauptprogramm diese ständig angucken lassen, aber das würde zu extrem vielen Festplattenzugriffen führen, was suboptimal ist
Also erstelle ich eine Variable im RAM auf welche zwei Autoit-Exen zugreifen können. An sich keine schwere Sache dank der vielen UDFs die es für Autoit schon gibt.
Doch leider verhält sich das Programm, wenn es durch Windows aufgerufen wird beim ersten Start anders, als bei den darauf folgenden.
Ich weiß nicht ob ihr mir bis hierhin folgen könnt ..
Ich habe meine Code auf die nötigen Stellen vereinfacht, damit das Problem nachvollzogen werden kann.
Alle nötigen includes und eine compilierte Exe findet sich im Anhang.
Bevor die Main.exe bzw. au3 ausgeführt werden kann muss einmal das Install-Script ausgeführt werden.
Hier mal der Code vom Install:
#RequireAdmin
#AutoIt3Wrapper_UseX64=y
Global $dest = "C:\Test"
RegWrite("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\test", "MUIVerb", "REG_SZ", "Test1")
RegWrite("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\test\command", "", "REG_SZ", $dest&"\test.exe %1 test1|test2")
RegWrite("HKEY_CLASSES_ROOT\*\shell\Test", "MUIVerb", "REG_SZ", "test")
RegWrite("HKEY_CLASSES_ROOT\*\shell\Test", "SubCommands", "REG_SZ", "test")
Und hier der Code der Main.au3:
#include "_SharedVar2.au3"
Global $dest = "C:\Test"
DirCreate($dest)
Global $L_var1 = 1
Global $L_var2 = 2
_SharedVar_SetDeclarationsInProcess(0,1)
_SharedVar_DeclareVar($L_var1,'char[4000]', "")
_SharedVar_DeclareVar($L_var2,'char[4000]', "")
Global $pointer = $gg_sv_pPointer4vars
_createExe($pointer)
If @error Then ;in very rare cases the pointer can't be created. If so then retry it ..
Run(@AutoItExe)
Exit
EndIf
While 1
If ProcessExists("test.exe") Then ;let the other program finish it's writing
While ProcessExists("test.exe")
Sleep(500)
WEnd
EndIf
If _sv_read($L_var1) <> "" Then
MsgBox(0, _sv_read($L_var2), _sv_read($L_var1))
_sv_write($L_var1, "")
_sv_write($L_var2, "")
EndIf
Sleep(200)
WEnd
Func _createExe($pointer)
Local $file
$src = '#NoTrayIcon' & @CRLF & _
'#include "_SharedVar.au3"' & @CRLF & _
'If $cmdline[0] > 0 Then' & @CRLF & _
' $cmd = ""' & @CRLF & _
' For $i = 1 to ($cmdline[0]-1)' & @CRLF & _
' $cmd = $cmd & $cmdline[$i] & " "' & @CRLF & _
' Next' & @CRLF & _
' $cmd = $cmd & "|"' & @CRLF & _
' _SharedVar_SetDeclarationsInProcess('&@AutoItPID&',1, String('&$pointer&'))' & @CRLF & _
' Global $O_var1 = 1' & @CRLF & _
' Global $O_var2 = 2' & @CRLF & _
' _SharedVar_DeclareVar($O_var1)' & @CRLF & _
' _SharedVar_DeclareVar($O_var2)' & @CRLF & _
' $temp = _sv_read($O_var1)' & @CRLF & _
' _sv_write($O_var1,$temp & $cmd)' & @CRLF & _
' _sv_write($O_var2,$cmdline[$cmdline[0]])' & @CRLF & _
'EndIf'
$file = FileOpen($dest&"\test.au3", 2)
FileWrite($file, $src)
FileClose($file)
FileInstall("_SharedVar.au3", $dest&"\_SharedVar.au3", 1)
FileInstall("Array.au3", $dest&"\Array.au3", 1)
FileInstall("NomadMemory.au3", $dest&"\NomadMemory.au3", 1)
FileInstall("StringConstants.au3", $dest&"\StringConstants.au3", 1)
FileInstall("MsgBoxConstants.au3", $dest&"\MsgBoxConstants.au3", 1)
FileInstall("AutoItConstants.au3", $dest&"\AutoItConstants.au3", 1)
FileInstall("Aut2exe.exe", $dest&"\Aut2exe.exe", 1)
RunWait($dest&"\Aut2exe.exe /in "&$dest&"\test.au3", "", @SW_HIDE)
FileDelete($dest&"\Aut2exe.exe")
;~ FileDelete($dest&"\test.au3")
FileDelete($dest&"\_SharedVar.au3")
FileDelete($dest&"\Array.au3")
FileDelete($dest&"\AutoItConstants.au3")
FileDelete($dest&"\NomadMemory.au3")
FileDelete($dest&"\MsgBoxConstants.au3")
FileDelete($dest&"\StringConstants.au3")
If FileExists($dest&"\test.exe") Then
SetError(0)
Else
SetError(1)
EndIf
EndFunc
Alles anzeigen
Das ganze funktioniert so, dass die Main.exe eine zweite erstellt, in welche die PID des Hauptprozesses und die Speicheradresse im RAM geschrieben wird. Das muss leider so sein, da sich diese beiden Variablen bei jedem Start der Main.exe ändern. Die zweite exe wird von Windows aufgerufen, wenn man den Rechtsklick macht und übergibt den dabei als Parameter übergebenen Pfad inklusive der Parameter an das Main Script.
Die Includes habe ich so angepasst, dass sie stand-alone sind und auch auf PCs ohne Autoit compiliert werden können.
Das funktioniert alles ohne Probleme.
Das Problem ist folgendes:
Wenn ich zwei Dateien markiere, dann sollten der Pfad und die exe getrennt durch ein Pipe | in die shared Variable geschrieben werden.
Dies geschieht allerdings nur beim zweiten Aufruf des Programms. Beim ersten wird nur eine hineingeschrieben. Warum weiß der Geier ..
Getestet wird, indem zwei Dateien markiert werden und dann Rechtsklick -> test -> Test1
Ich hoffe ihr könnt euch die Zeit nehmen um da mal einen Blick drauf zu werfen. Ich bin mit meinem Latein leider echt am Ende ..
Vielen vielen Dank schonmal im Vorraus für eure Zeit!
P.S.: Das Script (main.au3) funktionieren nur im compilierten Zustand und nur wenn es als x86 compiliert wurde