Hallo Leute,
als erstes mal eine Beschreibung meines Problems. Ich bin dabei, ein Backup Tool zu schreiben, was prinzipiell dazu in der Lage sein soll, Backups von FTP, SFTP und lokalen Dateien zu machen. Das ist ja alles kein Problem. Ich habe mir vorgenommen, dass ganze im schönen alten Konsolen-Stil zu machen. Da AutoIt da eher etwas beschränkt ist, habe ich also die console.au3 UDF aus dem englischen Forum verwendet. Das Problem an der UDF ist, dass die cin()-Funktion das Script solange pausiert, bis die Enter-Taste in der Konsole gedrückt wird. Das ist allerdings nicht in meinem Interesse, also musste ich eine Lösung finden. Über die coproc UDF, bis hin zu Thread-Funktion habe ich alles versucht durchzuexerzieren, bis ich endlich, in der guten alten Microsoft Hilfe auf Interprocess communication Möglichkeiten gestoßen bin. Ziemlich weit oben das "piping". Da viel mir ein, ah ja, da hat Autoit ja schon was... und nun sitze ich da und komme nicht weiter. Ich musste mein Script schon in einen Processor (das Main-Script, welches die ganzen Jobs verarbeiten soll) und die Konsole (das Programm, welches eigentlich nur die Eingaben des Users verarbeitet und gegebenenfalls an den Processor weiterleiten soll) geteilt, daher benötige ich auch einen effektiven Weg, die beiden Prozesse kommunizieren zu lassen. Envget/set Funktionen erzielen nicht den gewünschten Effekt, warum auch immer gibt es, wenn das eine Programm etwas in eine Variable setzt bei dem anderen keine Antwort, die Variable ist leer. Temporäre Dateien zu erstellen ist auch keine Option, bei großen Datenmengen dauert mir das Schreiben und lesen zu lange und vor allem ist der Datenverkehr abhörbar. Nicht das er das auf anderen Wegen nicht auch wäre, aber da jedenfalls deutlich einfacher. Nunja, lange Rede kurzer Sinn, ich hänge bei den Pipes fest. Hier also die beiden Teile, die ich bisher geschrieben habe (jeweils die Funktion pipe_initialize() vor dem Main-Script aufrufen).
Processor:
Spoiler anzeigen
dim const $pbufsize =4096
dim const $pipename = "\\.\\pipe\\mcbackup"
dim const $ptimeout =5000
dim const $error_io_pending =997
dim const $error_pipe_connected =535
dim $boverlap = dllstructcreate($tagoverlapped)
dim $poverlap = dllstructgetptr($boverlap)
dim $cstate, $pipe
func pipe_initialize()
global $pevent = _winapi_createevent()
if $pevent =0 then
msgbox(64, "MCBackup - Error", "Couldn't initialize event for interprocess communication. Please contact www.software@satoprogs.de with the following Error details:" & @crlf & @tab & "Errorcode: " & _winapi_getlasterror() & @crlf & @tab & "Error-Message: " & _winapi_getlasterrormessage())
mcb_shutdown()
endif
dllstructsetdata($boverlap, "hEvent", $pevent)
$pipe = _namedpipes_createnamedpipe($pipename, _
2, _
2, _
0, _
1, _
1, _
0, _
1, _
$pbufsize, _
$pbufsize, _
$ptimeout, _
0)
if $pipe =-1 then
msgbox(64, "MCBackup - Error", "Initialization of Pipe for the interprocess communication failed. Please contact software@satoprogs.de with the following Error-Information. " & @crlf & @tab & "Error-Code: " & _winapi_getlasterror() & @crlf & @tab & "Error-Message: " & _winapi_getlasterrormessage())
mcb_shutdown()
else
pipe_connect()
endif
endfunc
func ReadMsg()
local $pbuf, $tbuf, $iRead, $bSuccess
$tbuf = dllstructcreate("char Text[" & $pbufsize & "]")
$pbuf = dllstructgetptr($tbuf)
$bSuccess = _winapi_ReadFile($pipe, $pbuf, $pbufsize, $iRead, $poverlap)
if not $bSuccess and ($iRead <> 0) then
if not _winapi_getoverlappedresult($pipe, $poverlap, $iRead, true) then
pipe_reconnect()
return
else
$bsuccess = _winapi_readfile($pipe, $pbuf, $pbufsize, $iRead, $poverlap)
if not $bSuccess or ($iRead =0) then
pipe_reconnect()
return
endif
endif
endif
return dllstructgetdata($tbuf, "Text")
endfunc
func pipe_reconnect()
if not _namedpipes_disconnectnamedpipe($pipe) then
return
endif
pipe_connect()
endfunc
func pipe_connect()
$cstate=0
$pconnect = _namedpipes_connectnamedpipe($pipe, $poverlap)
if $pconnect then
msgbox(64, "MCBackup - Error", "Couldn't connect to Pipe. Please contact software@satoprogs.de and sent us the following Error-Information." & @crlf & @tab & "Error-Code: " & _winapi_getlasterror() & @crlf & @tab & "Error-Message: " & _winapi_getlasterrormessage())
mcb_shutdown()
else
switch number(_winapi_getlasterror())
case $error_pipe_connected
$cstate =1
if not _winapi_setevent(dllstructgetdata($boverlap, "hEvent")) then
msgbox(64, "MCBackup - Error", "Failed to set the event for the pipe. Please contact software@satoprogs.de and sent us the following Error-Information." & @crlf & @tab & "Error-Code: " & _winapi_getlasterror() & @crlf & @tab & "Error-Message: " & _winapi_getlasterrormessage())
mcb_shutdown()
endif
case else
msgbox(64, "MCBackup - Error", "Failed to connect to the pipe a second time. Please contact software@satoprogs.de with the following Error-Information." & @crlf & @tab & "Error-Code: " & _winapi_getlasterror() & @crlf & @tab & "Error-Message: " & _winapi_getlasterrormessage())
mcb_shutdown()
endswitch
endif
endfunc
func WriteMsg($msg)
if not _namedpipes_setnamedpipehandlestate($pipe, 1, 0, 0, 0) then return false
local $iWritten, $ibuf, $pbuf, $tbuf
$ibuf = stringlen($msg) +1
$tbuf = dllstructcreate("char Text[" & $ibuf & "]")
$pbuf = dllstructgetptr($tbuf)
dllstructsetdata($tbuf, "Text", $msg)
if not _winapi_writefile($pipe, $pbuf, $ibuf, $iwritten, 0) then return false
return true
endfunc
Console:
Spoiler anzeigen
dim const $pbufsize =4096
dim const $pipename = "\\.\\pipe\\MCBackup"
dim const $error_more_data =234
dim $boverlap = dllstructcreate($tagoverlapped)
dim $poverlap = dllstructgetptr($boverlap)
dim $pipe
func pipe_initialize()
global $pevent = _winapi_createevent()
if $pevent =0 then
msgbox(64, "MCBackup - Error", "Couldn't initialize event for interprocess communication in console. Please contact www.software@satoprogs.de with the following Error details:" & @crlf & @tab & "Errorcode: " & _winapi_getlasterror() & @crlf & @tab & "Error-Message: " & _winapi_getlasterrormessage())
mcb_shutdown()
endif
dllstructsetdata($boverlap, "hEvent", $pevent)
$pipe = _winapi_createfile($pipe, 2, 6)
if $pipe <> -1 then return true
msgbox(64, "MCBackup - Error", "Error connecting the console to the pipe. Please contact software@satoprogs.de with the following Error-Information. " & @crlf & @tab & "Error-Code: " & _winapi_getlasterror() & @crlf & @tab & "Error-Message: " & _winapi_getlasterrormessage())
mcb_shutdown()
return false
endfunc
func WriteMsg($msg)
if not _namedpipes_setnamedpipehandlestate($pipe, 1, 0, 0, 0) then return false
local $iWritten, $ibuf, $pbuf, $tbuf
$ibuf = stringlen($msg) +1
$tbuf = dllstructcreate("char Text[" & $ibuf & "]")
$pbuf = dllstructgetptr($tbuf)
dllstructsetdata($tbuf, "Text", $msg)
if not _winapi_writefile($pipe, $pbuf, $ibuf, $iwritten, 0) then return false
return true
endfunc
func ReadMsg()
local $pbuf, $tbuf, $iRead, $bSuccess
$tbuf = dllstructcreate("char Text[" & $pbufsize & "]")
$pbuf = dllstructgetptr($tbuf)
$bSuccess = _winapi_ReadFile($pipe, $pbuf, $pbufsize, $iRead, $poverlap)
if not $bSuccess and ($iRead <> 0) then
if not _winapi_getoverlappedresult($pipe, $poverlap, $iRead, true) then
pipe_initialize()
return
else
$bsuccess = _winapi_readfile($pipe, $pbuf, $pbufsize, $iRead, $poverlap)
if not $bSuccess or ($iRead =0) then
pipe_initialize()
return
endif
endif
endif
return dllstructgetdata($tbuf, "Text")
endfunc
Momentan ist das Problem, dass ich nicht weiß, wie ich überprüfen soll, wann er endlich die Verbindung in pipe_connect() (Processor) hergestellt hat, es wird immer noch gemeldet, dass er noch am arbeiten ist (Error-Code 997). Vielleicht gibt es ja auch eine viel rentablere Lösung, vielleicht sogar eine Möglichkeit, die Console nicht ständig das Hauptskript pausieren zu lassen, dann könnte ich mir diese Funktionen natürlich auch in die Haare schmieren.
Hinweis: Ich habe fast keinen Plan, was ich da überhaupt mache, dafür habe ich nicht wirklich den Einblick in die Winapi, ich habe diese Funktionen fast vollständig aus den Beispielen, die in AutoIt mitgeliefert werden übernommen.
Kann mir einer irgendwie Denkanstöße geben?
Vielen Dank im Voraus.
mfg.
Timtam
PS: Ob die Lesen /Schreiben (ReadMsg und WriteMsg) so überhaupt funktionieren weiß ich auch nicht, komme ja nicht mal dazu das zu testen...