Ich brauchte die Tage eine Lösung, um parallel von 2 Rechnern mit einem Scanner zu arbeiten.
Herausgekommen ist folgende Lösung:
Server-Rechner:
- Server-Script
- Irfanview
- Port (Std. 39200) ist freigegeben
- keine Adminrechte notwendig
- Speicherort auf dem ein Scan abgelegt werden kann
Server-Script
#NoTrayIcon
#compiler_icon=nwscan.ico
#compiler_outfile=RemoteIVScan_Server.exe
Opt("TrayMenuMode",1)
Opt("TrayOnEventMode",1)
Opt("MustDeclareVars",1)
FileInstall("nwscan.ico",@TempDir & "\nwscan.ico",1)
Dim $pid, $trayexit, $ziel, $socketId, $acceptSocketId, $IVprogramm
Dim $port = 39200
Dim $aufloesung = 150
; Fenstertexte (z.B. die des Twain Treibers) die während des
; Scanvorgangs versteckt werden sollen
Dim $fenster[2] = ["Der Scanner befindet sich in der Aufwärmphase","Scanvorgang läuft"]
If FileExists(@ScriptDir & "\i_view32.exe") Then
$IVprogramm = @ScriptDir & "\i_view32.exe"
Else
If FileExists(@ProgramFilesDir & "\IrfanView\i_view32.exe") Then $IVprogramm = @ProgramFilesDir & "\IrfanView\i_view32.exe"
EndIf
If $IVprogramm = "" Then
MsgBox(48,"Fehler","Das notwendige Tool 'IrfanView' wurde weder in '" & @ScriptDir &"' noch in '" & @ProgramFilesDir & "' gefunden !")
Exit
EndIf
$trayexit = TrayCreateItem("RemoteIVScan Server beenden")
TrayItemSetOnEvent(-1,"ExitEvent")
TraySetIcon(@TempDir & "\nwscan.ico")
TraySetToolTip ("RemoteIVScan Server")
TraySetState()
TCPStartup()
$socketId = TCPListen(@IPAddress1,$port)
If $socketId = -1 Then
Msgbox(48,"Fehler","Der TCP Port " & $port & " konnte NICHT zur Kommunikation geöffnet werden !")
TCPShutDown()
Exit
Else
While 1
Do
$acceptSocketId = TCPAccept($socketId)
Until $acceptSocketId <> -1
$ziel = ""
While 1
$ziel &= TCPRecv($acceptSocketId,2048)
If @error Then ExitLoop
Wend
If FileExists(StringLeft($ziel,StringInStr($ziel,"\",2,-1))) Then
$pid = Run($IVprogramm & " /scanhidden /dpi=(" & $aufloesung & "," & $aufloesung & ") /convert=" & $ziel,"",@SW_HIDE)
While ProcessExists($pid)
For $i = 0 To UBound($fenster)-1
If WinWait("",$fenster[$i],1) = 1 Then WinSetState("",$fenster[$i],@SW_HIDE)
Next
Wend
Sleep(500)
If FileGetSize($ziel) = 0 Then FileDelete($ziel)
EndIf
Wend
EndIf
Func ExitEvent()
TCPCloseSocket($socketId)
TCPShutDown()
If FileExists(@TempDir & "\nwscan.ico") Then FileDelete(@TempDir & "\nwscan.ico")
Exit
EndFunc
Client-Rechner:
- Client-Script
- keine Adminrechte notwendig
- Zugriff auf den Speicherort der Scan's
- IrfanView wenn Bild angezeigt/geschnitten/nachbearbeitet werden soll
Client-Script
Opt("MustDeclareVars",1)
#compiler_icon=nwscan.ico
#compiler_outfile=RemoteIVScan_Client.exe
FileInstall("nwscan.ico",@TempDir & "\nwscan.ico",1)
TraySetIcon(@TempDir & "\nwscan.ico")
Dim $start, $antwort, $socketId, $IVprogramm
Dim $timeout = 60
Dim $server = "Micha1"
Dim $port = "39200"
Dim $ziel = FileSaveDialog( "Wählen Sie einen Ziel-Dateinamen","\\Micha1\Neu\BILDER_SELCO","Bilder (*.jpg;*.bmp)",2)
If $ziel <> "" Then
If StringInStr(StringRight($ziel,5),".") = 0 Then $ziel &= ".jpg"
If FileExists(@ScriptDir & "\i_view32.exe") Then
$IVprogramm = @ScriptDir & "\i_view32.exe"
Else
If FileExists(@ProgramFilesDir & "\IrfanView\i_view32.exe") Then $IVprogramm = @ProgramFilesDir & "\IrfanView\i_view32.exe"
EndIf
While FileExists($ziel)
$antwort = Msgbox(48 + 4,"Datei vorhanden","Die Datei ist bereits vorhanden ! Soll sie überschrieben werden ?")
If $antwort = 7 Then
$ziel = Inputbox("Zielname","Bitte Zielname mit Dateiendung eingeben",$ziel)
Else
FileDelete($ziel)
Endif
Wend
TCPStartup()
$socketId = TCPConnect(TCPNameToIP($server),$port)
If $socketId = -1 Then
MsgBox(48,"Fehler"," Eine Verbindung mit dem entfernten RemoteIVScan Server" _
& @CRLF & @CRLF & " Name/IP " & @TAB & ":" & @TAB & $server _
& @CRLF & @CRLF & " Portnummer" & @TAB & ":" & @TAB & $port _
& @CRLF & @CRLF & " konnte NICHT hergestellt werden !")
TCPShutDown()
Programm_beenden()
Else
TCPSend($socketId,$ziel)
TCPCloseSocket($socketId)
TCPShutDown()
EndIf
$start = TimerInit()
Do
If FileExists($ziel) Then
If FileGetSize($ziel) > 0 Then
Sleep(100)
If $IVProgramm <> "" Then
Run("C:\Programme\IrfanView\i_view32.exe " & $ziel)
Else
MsgBox(0,"Ausgabe","IrfanView konnte nicht gefunden werden !" & @CRLF & @CRLF _
& "Die Zieldatei liegt unter : '" & $ziel & "'.")
EndIf
Programm_beenden()
EndIf
EndIf
Until TimerDiff($start) >= $timeout * 1000
Msgbox(48,"Fehler","Die Zieldatei '" & $ziel & "' konnte nicht geöffnet werden !")
EndIf
Programm_beenden()
Func Programm_beenden()
If FileExists(@TempDir & "\nwscan.ico") Then FileDelete(@TempDir & "\nwscan.ico")
Exit
EndFunc
Ggf. muss man die Fenstertexte, der (zu versteckenden) Twain-Fenster, im Server-Script
noch an den eigenen Treiber anpassen und den Servernamen im Client-Script.
IrfanView kann im Scriptordner oder unter ...\Programme\IrfanView\.. liegen.
Hier noch das Icon :
Edit: neue Version, Client mit FileSaveDialog
Edit: neue Version V2, Versand des Bildes per TCP an den Client
Server
#NoTrayIcon
#compiler_icon=nwscan.ico
#compiler_outfile=RemoteIVScan_Server.exe
Opt("TrayMenuMode",1)
Opt("TrayOnEventMode",1)
Opt("MustDeclareVars",1)
Opt("WinTitleMatchMode",4)
Opt("WinTextMatchMode",2)
Opt("WinSearchChildren",1)
FileInstall("nwscan.ico",@TempDir & "\nwscan.ico",1)
Dim $pid, $trayexit, $socketId, $acceptSocketId, $IVprogramm
Dim $acceptIP, $dateiID, $dateiInhalt, $anforderung
Dim $ServerPort, $ClientPort, $aufloesung, $fenster
Dim $peek, $rueckgabe, $prozesse
Dim $gefunden = False
; ggf. Konfiguration aus der INI-Datei lesen
$ServerPort = IniRead("RemoteIVScan.ini","Server","Port",39200)
$ClientPort = IniRead("RemoteIVScan.ini","Client","Port",39200)
$aufloesung = IniRead("RemoteIVScan.ini","Server","Aufloesung",150)
$fenster = StringSplit(IniRead("RemoteIVScan.ini","Server","Fenster",""),"|")
If $fenster[0] = 1 And $fenster[1] = "" Then
ReDim $fenster[1]
$fenster[0] = 0
EndIf
; Prüfen ob ein RemoteIVScan-Server-Process bereits auf dem
; angegebenen Port läuft
$rueckgabe = ""
$pid = Run("netstat.exe -ona","",@SW_HIDE,6)
While 1
$peek = StdOutRead($pid, 0, True)
If Not @error And $peek > 0 Then
$rueckgabe &= StdoutRead($pid)
EndIf
$peek = StdErrRead($pid, 0, True)
If @error Then
Exitloop
Else
If $peek > 0 Then
$rueckgabe &= StderrRead($pid)
EndIf
EndIf
Sleep(100)
Wend
$prozesse = Processlist("RemoteIVScan_Server.exe")
For $i = 1 To $prozesse[0][0]
If StringRegExp($rueckgabe,"\r\n.*TCP.*:39200.*" & $prozesse[$i][1] & "\r\n") = 1 Then
$gefunden = True
ExitLoop
EndIf
Next
If $gefunden = True Then
; nur Beenden keine Meldung
;MsgBox(48,"Fehler","Die Server-Anwendung läuft bereits auf Port '" & $ServerPort &"' !")
Exit
EndIf
; IrfanView wird gesucht
If FileExists(@ScriptDir & "\i_view32.exe") Then
$IVprogramm = @ScriptDir & "\i_view32.exe"
Else
If FileExists(@ProgramFilesDir & "\IrfanView\i_view32.exe") Then $IVprogramm = @ProgramFilesDir & "\IrfanView\i_view32.exe"
EndIf
If $IVprogramm = "" Then
MsgBox(48,"Fehler","Das notwendige Tool 'IrfanView' wurde weder in '" & @ScriptDir &"' noch in '" & @ProgramFilesDir & "' gefunden !")
Exit
EndIf
; neuen Traymenu zum Beenden anlegen
$trayexit = TrayCreateItem("RemoteIVScan Server beenden")
TrayItemSetOnEvent(-1,"ExitEvent")
TraySetIcon(@TempDir & "\nwscan.ico")
TraySetToolTip ("RemoteIVScan Server")
TraySetState()
; einen ggf. vorhandenen alten Scan löschen
If FileExists(@TempDir & "\RemoteIVScan_OUT.jpg") Then FileDelete(@TempDir & "\RemoteIVScan_OUT.jpg")
TCPStartup()
While 1
$socketId = TCPListen(@IPAddress1,$ServerPort)
If $socketId = -1 Then
Msgbox(48,"Fehler","Der TCP Port " & $ServerPort & " konnte NICHT zur Kommunikation geöffnet werden !")
TCPShutDown()
ExitEvent()
Else
Do
$acceptSocketId = TCPAccept($socketId)
Until $acceptSocketId <> -1
$acceptIP = SocketToIP($acceptSocketId)
$anforderung = ""
While 1
$anforderung &= TCPRecv($acceptSocketId,2048)
If @error Then ExitLoop
Wend
TCPCloseSocket($socketId)
If StringLeft($anforderung,20) = "|RemoteIVScan|Start|" Then
$pid = Run($IVprogramm & " /scanhidden /dpi=(" & $aufloesung & "," & $aufloesung & ") /convert=" & @TempDir & "\RemoteIVScan_OUT.jpg")
While ProcessExists($pid)
For $i = 1 To $fenster[0]
;If WinExists("",$fenster[$i]) = 1 Then WinSetState("",$fenster[$i],@SW_HIDE)
;WinWait("[CLASS:#32770]", "",1)
WinSetState($fenster[$i],"",@SW_HIDE)
Next
;Sleep(10)
Wend
Sleep(500)
If FileGetSize(@TempDir & "\RemoteIVScan_OUT.jpg") = 0 Then
FileDelete(@TempDir & "\RemoteIVScan_OUT.jpg")
Else
_TCPSendFile(@TempDir & "\RemoteIVScan_OUT.jpg",$acceptIP,$ClientPort,5,0,0)
Sleep(200)
FileDelete(@TempDir & "\RemoteIVScan_OUT.jpg")
EndIf
EndIf
EndIf
Wend
Func ExitEvent()
TCPShutDown()
If FileExists(@TempDir & "\nwscan.ico") Then FileDelete(@TempDir & "\nwscan.ico")
Exit
EndFunc
Func SocketToIP($SHOCKET)
Local $sockaddr = DLLStructCreate("short;ushort;uint;char[8]")
Local $aRet = DLLCall("Ws2_32.dll","int","getpeername","int",$SHOCKET, _
"ptr",DLLStructGetPtr($sockaddr),"int*",DLLStructGetSize($sockaddr))
If Not @error And $aRet[0] = 0 Then
$aRet = DLLCall("Ws2_32.dll","str","inet_ntoa","int",DLLStructGetData($sockaddr,3))
If Not @error Then $aRet = $aRet[0]
Else
$aRet = 0
EndIf
$sockaddr = 0
Return $aRet
EndFunc
;=============================================== _TCPSendFile ==============================================
;
; Author: DJ Baselord
; Version: 1.0
; Requirements: Autoit v. 3.2.4.0
; Parameters: $sFile: File
; $sIP: IP to conenct to
; $iPort: TCP - Port to connect to
; $iTimeout: Time to wait for a connection
; $bPopup: 1 to popup Progress, 0 to hide
; $bShowMessageOnSuccess: 1 to show Msg on success, 0 to hide
; $iSleep: Time to sleep beetween each TCPSend, very important for the
; relation beetween CPU - ussage and transmition rate
; $iPartsize: Size in KB needed by TCP - Send also important for the
; relation beetween CPU - ussage and transmition rate
;
; Returnvalue: 1 on succes
; 0 on failure and @error is set as below:
; 1: file doesn't exist
; 2: error occured while file reading
; 3: if timer is expired
;
;===========================================================================================================
Func _TCPSendFile($sFile,$sIP,$iPort,$iTimeout=0,$bPopup=1,$bShowMessageOnSuccess=1,$iSleep=10,$iPartsize=128)
Local $hFile, $hFileRead, $iFilesize, $iConnectedSocket, $iCurrenttime, $TCPSend, $iFilesizeMB
Local $iNewTime, $iOldTime, $iTime, $iRate, $iSent, $hTimer
If $bPopup Then ProgressOn("Senden des Scan's","Verbindungsaufbau","Datei Einlesen",-1,-1,16)
If Not FileExists($sFile) Then Return SetError(1,0,0)
$hFile = FileOpen($sFile,16)
$hFileRead = FileRead($hFile)
FileClose($hFile)
$iFilesize = BinaryLen($hFileRead)
If Not BinaryLen($hFileRead) Then Return SetError(2,0,0)
If $bPopup And Not $iTimeout Then ProgressSet(0,"Warte auf Verbindung mit Client")
If $bPopup And $iTimeout Then ProgressSet(0,"Warte noch "&$iTimeout&" Sekunden")
If $iTimeout Then $hTimer = TimerInit()
Do
$iConnectedSocket = TCPConnect($sIP,$iPort)
Sleep(100)
If $bPopup And $iTimeout Then
$iCurrenttime = Int(TimerDiff($hTimer)/1000)
ProgressSet((TimerDiff($hTimer)/1000)/$iTimeout*100,"Warte noch "&$iTimeout-$iCurrenttime&" Sekunden")
If $iCurrenttime >= $iTimeout Then
ProgressSet(100,"Zeit abgelaufen")
Sleep(3000)
Return SetError(3,0,ProgressOff())
EndIf
EndIf
Until $iConnectedSocket > -1
$sFile = StringTrimLeft($sFile,StringInStr($sFile,"\",-1,-1))
Do
$TCPSend = TCPSend($iConnectedSocket,$sFile&Chr(3)&$iFilesize)
Sleep(100)
Until $TCPSend > 0
If $bPopup Then
$hTimer = TimerInit()
$iFilesizeMB = Round($iFilesize/1024^2,2)
ProgressSet(0,"Sende 0.0 von "&$iFilesizeMB&" MB @ 0.0 kb/s","Datei senden...")
EndIf
Do
$TCPSend = TCPSend($iConnectedSocket,BinaryMid($hFileRead,1,$iPartsize*1024))
$hFileRead = BinaryMid($hFileRead,1+$TCPSend)
If $bPopup Then
$iNewTime = TimerDiff($hTimer)
$iTime = $iNewTime - $iOldTime
$iRate = ($TCPSend/$iTime)/1.024
$iSent = ($iFilesize-BinaryLen($hFileRead))/1024^2
ProgressSet($iSent/$iFilesizeMB*100,"Sende "&Round($iSent,2)&" von "&$iFilesizeMB&" @ "&Round($iRate,2)&" kb/s")
$iOldTime = $iNewTime
EndIf
Sleep($iSleep)
Until BinaryLen($hFileRead) <= 0
TCPCloseSocket($iConnectedSocket)
If $bShowMessageOnSuccess Then MsgBox(64+262144,"Senden des Scan's","Scan erfolgreich gesendet")
ProgressOff()
Return 1
EndFunc
Client
Opt("MustDeclareVars",1)
#compiler_icon=nwscan.ico
#compiler_outfile=RemoteIVScan_Client.exe
FileInstall("nwscan.ico",@TempDir & "\nwscan.ico",1)
TraySetIcon(@TempDir & "\nwscan.ico")
Dim $socketId, $IVprogramm, $server, $ServerPort, $ClientPort, $timeout, $zieldatei
[/autoit] [autoit][/autoit] [autoit]; ggf. Konfiguration aus der INI-Datei lesen
$server = IniRead("RemoteIVScan.ini","Server","NameIP","Micha1")
$ServerPort = IniRead("RemoteIVScan.ini","Server","Port",39200)
$ClientPort = IniRead("RemoteIVScan.ini","Client","Port",39200)
$timeout = IniRead("RemoteIVScan.ini","Client","Timeout",60)
; möglichst IrfanView finden, ansonsten erfolgt keine Anzeige
If FileExists(@ScriptDir & "\i_view32.exe") Then
$IVprogramm = @ScriptDir & "\i_view32.exe"
Else
If FileExists(@ProgramFilesDir & "\IrfanView\i_view32.exe") Then $IVprogramm = @ProgramFilesDir & "\IrfanView\i_view32.exe"
EndIf
TCPStartup()
; Server kontaktieren und Scan anfordern
$socketId = TCPConnect(TCPNameToIP($server),$ServerPort)
If $socketId = -1 Then
MsgBox(48,"Fehler"," Eine Verbindung mit dem entfernten RemoteIVScan Server" _
& @CRLF & @CRLF & " Name/IP " & @TAB & ":" & @TAB & $server _
& @CRLF & @CRLF & " Portnummer" & @TAB & ":" & @TAB & $ServerPort _
& @CRLF & @CRLF & " konnte NICHT hergestellt werden !")
Else
TCPSend($socketId,"|RemoteIVScan|Start|")
TCPCloseSocket($socketId)
; jetzt wird bis zum Timeout auf die gesendete Datei gewartet
If _TCPRecvFile(@TempDir & "\RemoteIVScan_IN.jpg",@IPAddress1,$ClientPort,$timeout,1,0) = 1 Then
If $IVProgramm <> "" Then
Run("C:\Programme\IrfanView\i_view32.exe " & @TempDir & "\RemoteIVScan_IN.jpg")
Sleep(1000)
FileDelete(@TempDir & "\RemoteIVScan_IN.jpg")
Else
$zieldatei = FileSaveDialog( "Wählen Sie einen Ziel-Dateinamen","","JPG-Grafiken (*.jpg)",2)
If $zieldatei <> "" Then
FileMove(@TempDir & "\RemoteIVScan_IN.jpg",$zieldatei,1)
EndIf
EndIf
EndIf
EndIf
TCPShutDown()
If FileExists(@TempDir & "\nwscan.ico") Then FileDelete(@TempDir & "\nwscan.ico")
;=============================================== _TCPRecvFile ==============================================
;
; Author: DJ Baselord
; Version: 1.0
; Requirements: Autoit v. 3.2.4.0
; Parameters: $sFile: String to save file to if "", orignial filename will be used
; $sIP: IP to wait for connection
; $iPort: TCP - Port to open up listening port
; $iTimeout: Time to wait for a connection
; $bPopup: 1 to popup Progress, 0 to hide
; $bShowMessageOnSuccess: 1 to show Msg on success, 0 to hide
; $iSleep: Time to sleep beetween each TCPRecv, very important for the
; relation beetween CPU - ussage and transmition rate
; $iPartsize: Size in KB needed by TCPRecv also important for the
; relation beetween CPU - ussage and transmition rate
;
; Returnvalue: 1 on succes
; 0 on failure and @error is set as below:
; 1: if timer is expired
;
;===========================================================================================================
Func _TCPRecvFile($sFile,$sIP,$iPort,$iTimeout=0,$bPopup=1,$bShowMessageOnSuccess=1,$iSleep=10,$iPartsize=128)
Local $ListeningSocket, $hTimer, $iConnectedSocket, $iCurrenttime, $Recv, $iFilesize, $SFilename
Local $sBuffer, $iFilesizeMB, $iNewTime, $iOldTime, $iRate, $iSent, $iTime, $hFile
If $bPopup Then ProgressOn("Empfang des Scan's","Warte auf Sendung des Scans","Warten",-1,-1,16)
$ListeningSocket = TCPListen($sIP,$iPort)
If $bPopup And Not $iTimeout Then ProgressSet(0,"Warte auf Verbindung")
If $bPopup And $iTimeout Then ProgressSet(0,"Warte noch "&$iTimeout&" Sekunden")
If $iTimeout Then $hTimer = TimerInit()
Do
$iConnectedSocket = TCPAccept($ListeningSocket)
Sleep(100)
If $bPopup And $iTimeout Then
$iCurrenttime = Int(TimerDiff($hTimer)/1000)
ProgressSet((TimerDiff($hTimer)/1000)/$iTimeout*100,"Warte noch "&$iTimeout-$iCurrenttime&" Sekunden")
If $iCurrenttime >= $iTimeout Then
ProgressSet(100,"Timeout abgelaufen. Es wurde kein Scan gesendet !")
Sleep(5000)
SetError(1)
ProgressOff()
Return 0
EndIf
EndIf
Until $iConnectedSocket > -1
Do
$Recv = TCPRecv($iConnectedSocket,2048)
Sleep(100)
Until $Recv <> ""
$Recv = StringSplit($Recv,Chr(3))
$iFilesize = $Recv[2]
$SFilename = $Recv[1]
$sBuffer = Binary("")
If $bPopup Then
$hTimer = TimerInit()
$iFilesizeMB = Round($iFilesize/1024^2,2)
ProgressSet(0,"Sende 0.0 von "&$iFilesizeMB&" MB @ 0.0 kb/s","Datei senden...")
EndIf
Do
$Recv = Binary(TCPRecv($iConnectedSocket,$iPartsize*1024))
$sBuffer &= $Recv
Sleep($iSleep)
If $bPopup Then
$iNewTime = TimerDiff($hTimer)
$iTime = $iNewTime - $iOldTime
$iRate = (BinaryLen($Recv)/$iTime)/1.024
$iSent = (BinaryLen($sBuffer))/1024^2
ProgressSet($iSent/$iFilesizeMB*100,"Empfange "&Round($iSent,2)&" von "&$iFilesizeMB&" @ "&Round($iRate,2)&" kb/s")
$iOldTime = $iNewTime
EndIf
Until BinaryLen($sBuffer) >= $iFilesize
If $sFile = "" Then $sFile = $SFilename
$hFile = FileOpen($sFile,18)
FileWrite($hFile,$sBuffer)
FileClose($hFile)
$sBuffer = ""
TCPCloseSocket($ListeningSocket)
TCPCloseSocket($iConnectedSocket)
If $bShowMessageOnSuccess Then MsgBox(64+262144,"Empfang des Scan's","Scan erfolgreich empfangen")
ProgressOff()
Return 1
EndFunc