WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

Pipes

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

Communicating with Named Pipes


See WindowsInterfaceLanguage.chm for Pipe functions.


Another option for interprogram communication... 'named pipes'.

Here are two sample programs: a server program creates a "named pipe" and waits for a client to connect. It reads a message from the client and sends back a reply.

The client program sends a message and displays the reply from the server.

PSERVER.WBT
The 'server'

;********************************************************************
;
;  The "server".  
;
;  Create a pipe.  
;  Wait for a client to connect and send us a message.
;  Read the client's message and write a reply.
;
;********************************************************************

PipeName = "\\.\pipe\Test.Server.Pipe"

PIPE_ACCESS_DUPLEX    = 3
PIPE_WAIT             = 0
PIPE_READMODE_MESSAGE = 2
PIPE_TYPE_MESSAGE     = 4
INVALID_HANDLE_VALUE  = -1
FILE_FLAG_WRITE_THROUGH = -2147483648

;-----------------------------------------------------------------
;  Function to get an error message after an API error.
;-----------------------------------------------------------------
#DefineFunction SystemMessage()
  Err = DllLastError()
  Text = StrCat("Error (",Err,")")
  Buffer = BinaryAlloc(256)
  BinaryEodSet(Buffer,255)
  if DllCall(StrCat(DirWindows(1),"Kernel32.dll"),long:"FormatMessageA",long:4096,long:0,long:Err,long:0,lpbinary:Buffer,long:256,long:0)
     Text = StrCat(Text," ",BinaryPeekStr(Buffer,0,256))
  endif
  BinaryFree(Buffer)
  Return Text
#EndFunction

;-------------------------------------------------------------
;  Create a NULL security descriptor and put it into
;  a SECURITY_ATTRIBUTES structure.
;-------------------------------------------------------------
PSD    = BinaryAlloc(20)
SATTR  = BinaryAlloc(12)
Adv32 = DLLLoad(StrCat(DirWindows(1),"advapi32.dll"))
ok = DLLCall(Adv32,long:"InitializeSecurityDescriptor",lpbinary:PSD,long:1)
ok = DLLCall(Adv32,long:"SetSecurityDescriptorDacl",lpbinary:PSD,long:-1,long:0,long:0)
BinaryPoke4(SATTR,0,12)
BinaryPoke4(SATTR,4,IntControl(42,PSD,0,0,0))
BinaryPoke4(SATTR,8,-1)
DLLFree(Adv32)

;------------------------------------------------------------
;  Create the named pipe
;------------------------------------------------------------
K32 = DllLoad(StrCat(dirwindows(1),"Kernel32.DLL"))
OpenMode = PIPE_ACCESS_DUPLEX | FILE_FLAG_WRITE_THROUGH
PipeMode = PIPE_WAIT | PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE

hPipe = DLLCall(K32,long:"CreateNamedPipeA",lpstr:PipeName,long:OpenMode,long:PipeMode,long:1,long:10240,long:1024,long:100,lpbinary:SATTR)
if hPipe == INVALID_HANDLE_VALUE
    Msg = StrCat("Unable to open named pipe.",@CRLF,SystemMessage(Err))
    Message("",Msg)
    BinaryFree(SATTR)
    BinaryFree(PSD)
    return
endif

;------------------------------------------------------------
;  Wait for a client to connect
;------------------------------------------------------------
Buffer = BinaryAlloc(1024)
Dword  = BinaryAlloc(4)

if !DLLCall(K32,long:"ConnectNamedPipe",long:hPipe,long:0)
   Msg = StrCat("Error waiting for connect to named pipe.",@CRLF,SystemMessage(Err))
   Message("",Msg)
   goto SHUTDOWN
endif
   
;------------------------------------------------------------
;  Read the message from the client.
;------------------------------------------------------------
BinaryEodSet(Buffer,1024)
if !DLLCall(K32,long:"ReadFile",long:hPipe,lpbinary:Buffer,long:1024,lpbinary:Dword,long:0)
   Msg = StrCat("Error reading named pipe.",@CRLF,SystemMessage(Err))
   Message("",Msg)
   goto SHUTDOWN
endif

nBytes = BinaryPeek4(DWORD,0)
ClientMsg = BinaryPeekStr(Buffer,0,nBytes)

;-------------------------------------------------------------
;  Send a message back to the client.
;-------------------------------------------------------------
Msg = "Hello from the server!"
DLLCall(K32,long:"WriteFile",long:hPipe,lpstr:Msg,long:StrLen(Msg),lpBinary:Dword,long:0)
DLLCall(K32,long:"FlushFileBuffers",long:hPipe)

;-------------------------------------------------------------
;  Make sure the client has disconnected.
;  (Once this is done, you could go back and wait
;   for another connection.)
;-------------------------------------------------------------
if !DLLCall(K32,long:"DisconnectNamedPipe",long:hPipe)
   Msg = StrCat("Error disconnecting named pipe.",@CRLF,SystemMessage(Err))
   Message("",Msg)
   goto SHUTDOWN
endif

;-------------------------------------------------------------
;  We're all done.  Close the pipe.
;-------------------------------------------------------------
:SHUTDOWN
DLLCall(K32,long:"CloseHandle",long:hPipe)
DLLFree(K32)
BinaryFree(Buffer)
BinaryFree(Dword)
BinaryFree(SATTR)
BinaryFree(PSD)
return


PCLIENT.WBT
The 'client'

;-----------------------------------------------------------------
;
;  The "Client".
;
;  Send a message to the server's named pipe and read its reply.
;
;-----------------------------------------------------------------
ServerPipeName = "\\.\pipe\Test.Server.Pipe"

;-----------------------------------------------------------------
;  Function to get an error message after an API error.
;-----------------------------------------------------------------
#DefineFunction SystemMessage()
  Err = DllLastError()
  Text = StrCat("Error (",Err,")")
  Buffer = BinaryAlloc(256)
  BinaryEodSet(Buffer,255)
  if DllCall(StrCat(DirWindows(1),"Kernel32.dll"),long:"FormatMessageA",long:4096,long:0,long:Err,long:0,lpbinary:Buffer,long:256,long:0)
     Text = StrCat(Text," ",BinaryPeekStr(Buffer,0,256))
  endif
  BinaryFree(Buffer)
  Return Text
#EndFunction

;-----------------------------------------------------------------
;  Send a message and read the reply.  (Timeout after 5 seconds.)
;-----------------------------------------------------------------
Buffer = BinaryAlloc(1024)
Dword  = BinaryAlloc(4)
K32 = DllLoad(StrCat(dirwindows(1),"Kernel32.DLL"))

Text = "Hello from the client."
BinaryEodSet(Buffer,1024)
if !DLLCall(K32,long:"CallNamedPipeA",lpstr:ServerPipeName,lpstr:Text,long:StrLen(Text),lpbinary:Buffer,long:1024,lpbinary:Dword,long:5000)
   Msg = StrCat("Error calling named pipe.",@CRLF,SystemMessage())
   Message("Client",Msg)
   BinaryFree(Buffer)
   BinaryFree(Dword)
   return
endif

nByte = BinaryPeek4(DWord,0)
ServerMsg = BinaryPeekStr(Buffer,0,nByte)

Message("Message from server",ServerMsg)
return


By the way - named pipes can be used to commucate between programs on the same computer, or between different computers on a network.

In the example programs, the pipe name is coded as "\\.\pipe\NameOfPipe", where "\\.\" means "on this computer".

To communicate with a server on another system, code the name, in the client, as "\\HostComputer\pipe\NameOfPipe"


Article ID:   W16451
File Created: 2007:07:12:12:24:14
Last Updated: 2007:07:12:12:24:14