CraigA Posted December 14, 2007 Share Posted December 14, 2007 Hello, I have been messing around with the UDF's under NamedPipes Management and cannot figure out how to get the pipe server to read and clear the data placed in the pipe by the pipe client. The server code can use the _NamedPipes_PeekNamedPipe() function to verify and look at the data placed in the pipe. The code below is a working "peeking" version. Run it the first time to start the server running and run it again to run the client code. It will EXIT correctly if the first message sent by the client is a "DIE". If it is not, another client cannot send because: "Client could NOT open pipe." The blocks of commented code below are an attempt at different server code and the another version of client code that works. For the server code, I also tried a few versions of fileRead() which failed in many ways. expandcollapse popup; First instance acts as a Pipe Server, second acts as a Pipe Client. AutoItSetOption("MustDeclareVars", 1) #Include <NamedPipes.au3> Local Const $vzbEZ_PIPE_NAME = "\\.\pipe\vzbEZPipe" _Main() Func _Main() If _Singleton("PipeServer", 1) == 0 Then ; We know the Pipe Server is running, act as a Pipe Client. Local $msg $msg = InputBox("pipeClient", "Input a message to send to the Pipe Server") Local $file = FileOpen($vzbEZ_PIPE_NAME, 2) If $file <> -1 Then FileWrite($file, $msg) FileClose($file) Else MsgBox(0,"Pipe Client", "Client could NOT open pipe.") EndIf Exit Endif ;********************************************* ; Only the Pipe Server gets to the code below. ;********************************************* Local $hndlPipe Local $aPipeData[4] $hndlPipe = _NamedPipes_CreateNamedPipe($vzbEZ_PIPE_NAME) ; wait for a client process to connect to an instance of a named pipe If _NamedPipes_ConnectNamedPipe($hndlPipe) Then ; Loop until you get a DIE msg. Do Sleep(1000) $aPipeData = _NamedPipes_PeekNamedPipe($hndlPipe) ConsoleWrite(@LF & "Pipe Server:: Data: """ & $aPipeData[0] & """" & ", " & $aPipeData[1] & ", " & $aPipeData[2] & ", " & $aPipeData[3] & @LF) Until $aPipeData[0] == "DIE" Else ConsoleWrite(@LF & "Pipe Server:: connectNamedPipe() failed. " & @LF) Endif EndFunc #cs Attempted Server Code that does not work. Local $hndlPipe Local $str = "char msgArray[128]" Local $dllStruct = DllStructCreate($str) Local $msgBufferSize = DllStructGetSize($dllStruct) Local $msgBufferPtr = DllStructGetPtr($dllStruct) Local $iRetVal Local $msg $hndlPipe = _NamedPipes_CreateNamedPipe($vzbEZ_PIPE_NAME) ; wait for a client process to connect to an instance of a named pipe If _NamedPipes_ConnectNamedPipe($hndlPipe) Then ; Loop until you get a DIE msg. ConsoleWrite(@LF & "Pipe Server:: connectNamedPipe() succeeded. " & @LF) Do Sleep(1000) $msg = "" _NamedPipes_CallNamedPipe($vzbEZ_PIPE_NAME, 0, 0, $msgBufferPtr, $msgBufferSize, $iRetVal, 0) $msg = DllStructGetData($dllStruct, 1) ConsoleWrite(@LF & "Pipe Server:: Data: """ & $msg & """" & " Num Read: " & $iRetVal & @LF) Until $msg == "DIE" Else ConsoleWrite(@LF & "Pipe Server:: connectNamedPipe() failed. " & @LF) Endif #ce #cs Former Client Code that also works. Local $myMsg = "hello", $iRetVal, $progress = "Client, " Local $str = "char msgArray[128]" Local $dllStruct = DllStructCreate($str) DllStructSetData($dllStruct, 1, $myMsg) Local $msgSize = DllStructGetSize($dllStruct) Local $msgPtr = DllStructGetPtr($dllStruct) If _NamedPipes_WaitNamedPipe($vzbEZ_PIPE_NAME, 1) Then ; 1, return when pipe is available. 0- The time-out interval is the default value specified by the server process. $progress = $progress & "waitNamedPipe, " If _NamedPipes_CallNamedPipe($vzbEZ_PIPE_NAME, $msgPtr, $msgSize, 0, 0,$iRetVal, -1) Then $progress = $progress & "callNamedPipe, " EndIf $progress = $progress & "Bytes Read: " & $iRetVal Endif MsgBox(0, "Pipe Client :: ", "Pipe Client :: " & $progress & " Msg Size: " & $msgSize & @LF & DllStructGetData($dllStruct, 1)) #ce ;#cs Link to comment Share on other sites More sharing options...
CraigA Posted December 14, 2007 Author Share Posted December 14, 2007 I really doubt this is even close to a correct way for a pipe server to read from a pipe but it is working. Inside a do-loop, the pipe server does a * _NamedPipes_ConnectNamedPipe($hndlPipe) , which does not return until a client sends a message, * peeks to get the data, * calls _NamedPipes_DisconnectNamedPipe($hndlPipe) which seems to clear the contents of the pipe and makes it again availble for a pipe client. (see code below) Here is a sample output: >Running:(3.2.10.0):C:\Program Files\AutoIt3\autoit3.exe "C:\Program Files\AutoIt3\Projects\testJunk\PipeServer.au3" Pipe Server:: Data: "msg01", 5, 5, 0 Pipe Server:: Data: "msg02", 5, 5, 0 Pipe Server:: Data: "The first human made object to break the sound barrier was a whip.", 66, 66, 0 Pipe Server:: Data: "pauseRequest,pauseTime;;requestSequenceNumber;senderID", 54, 54, 0 Pipe Server:: Data: "die", 3, 3, 0 Pipe Server:: Data: "DIE", 3, 3, 0 +>15:41:16 AutoIT3.exe ended.rc:0 expandcollapse popup; First instance acts as a Pipe Server, second acts as a Pipe Client. AutoItSetOption("MustDeclareVars", 1) #Include <NamedPipes.au3> Local Const $vzbEZ_PIPE_NAME = "\\.\pipe\vzbEZPipe" _Main() Func _Main() If _Singleton("PipeServer", 1) == 0 Then ; We know the Pipe Server is running, act as a Pipe Client. ;********************************************* ; Only the Pipe Client gets to the code below. ;********************************************* Local $msg, $file While True $msg = InputBox("pipeClient", "Input a message to send to the Pipe Server") If @error == 0 Then $file = FileOpen($vzbEZ_PIPE_NAME, 2) If $file <> -1 Then FileWrite($file, $msg) FileClose($file) Else MsgBox(0,"Pipe Client", "Client could NOT open pipe.") EndIf Else Exit Endif WEnd Exit Endif ;********************************************* ; Only the Pipe Server gets to the code below. ;********************************************* Local $hndlPipe Local $aPipeData[4] ; Create the named pipe. Get data from the pipe until a "DIE" message is received. $hndlPipe = _NamedPipes_CreateNamedPipe($vzbEZ_PIPE_NAME) If $hndlPipe <> -1 Then Do ; wait for a client process to connect to an instance of a named pipe If _NamedPipes_ConnectNamedPipe($hndlPipe) Then $aPipeData = _NamedPipes_PeekNamedPipe($hndlPipe) ConsoleWrite(@LF & "Pipe Server:: Data: """ & $aPipeData[0] & """" & ", " & $aPipeData[1] & ", " & $aPipeData[2] & ", " & $aPipeData[3] & @LF) If Not _NamedPipes_DisconnectNamedPipe($hndlPipe) Then ConsoleWrite(@LF & "Pipe Server:: DisconnectNamedPipe() Failed." & @LF) Endif Else ConsoleWrite(@LF & "Pipe Server:: connectNamedPipe() failed. " & @LF) Exit Endif Until $aPipeData[0] == "DIE" Else ConsoleWrite(@LF & "Pipe Server:: _CreateNamedPipe() failed. " & @LF) Endif EndFunc Link to comment Share on other sites More sharing options...
PsaltyDS Posted December 15, 2007 Share Posted December 15, 2007 (edited) Your topic got me interested in finally trying to figure out pipes. Started coding my own version, which blew up in my face! An existing demo for server and client was found by martin and GaryFrost converted them to the current AutoIt version. They work fine and I'm trying to study those now. Doesn't answer your questions, but just wanted to relay what I've got so far. Edited December 15, 2007 by PsaltyDS Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
CraigA Posted December 17, 2007 Author Share Posted December 17, 2007 PsaltyDS,Thanks for passing on the examples. Just a brief look through those examples answered many questions and makes what I read about named pipes in the lame "MSDN help file" less cryptic.Looking in to pipes, I think I have gained an understanding of the two-step AutoIt3 technique to provide a pointer argument to a Windows API function or an AutoIt3 function that requires a pointer parameter (usually a pointer to a buffer).MSDN WriteFile():BOOL WINAPI ReadFile(HANDLE hFile, LPCVOID lpBuffer, ... From AutoIt3's _WinAPI_ReadFile() help file: _WinAPI_ReadFile($hFile, $pBuffer, ..."$pBuffer - A Pointer to the buffer that receives the data read from a file."AutoIt3 code that provides a pointer argument:$tBuffer = DllStructCreate("char Text[4096]") ; Step 1 - Create the buffer.$pBuffer = DllStructGetPtr($tBuffer) ; Step 2 - Get a pointer to that buffer._WinAPI_ReadFile($hPipe, $pBuffer, ...The term DLL throws me off sometimes but I try to remember:"The [actual] Windows API functions are implemented in Dynamic Link Libraries (DLL's)".I'll have to look into why in the Client script, WriteMsg(GUICtrlRead($iEdit)) calls ReadMsg().Thanks again,Craig Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now