This step-by-step article discusses how to use named pipes in Microsoft Visual Basic .NET or in Microsoft Visual Basic 2005 for interprocess communication. This article includes a code sample that demonstrates client/server communication by using a named pipe in Visual Basic .NET or in Visual Basic 2005. The article describes the interprocess communication by creating a named pipe server and a named pipe client. The communication over the pipe is performed in the following way:
Create a named pipe.
Block the server application by using the ConnectNamedPipe function until a client connects.
Connect to the server by using the CallNamedPipe function.
Call the ReadFile function or the WriteFile function to communicate over the pipe.
Call the DisconnectNamedPipe function when the process finishes using the pipe.
Call the CloseHandle function on the named pipe after you completed communicating over the pipe.
A named pipe is a one-way or duplex pipe for communication between a pipe server and one or more pipe clients. You can user named pipes to provide communication between processes on the same computer or between processes on different computers across a network.
The term "named pipe server" refers to a process that creates a named pipe, and the term "named pipe client" refers to a process that connects to an instance of a named pipe.
You can use Microsoft Visual Basic .NET or Microsoft Visual Basic 2005 to create applications that communicate to other processes by using named pipes. This article contains a code sample that uses a named pipe to communicate between two Visual Basic .NET or Visual Basic 2005 Windows applications.
Add all the declarations to a module in the Windows application
To add the function declarations that are required to implement the interprocess communication by using the named pipe, follow these steps:
In Solution Explorer, right-click MyServerApp, point to Add, and then click Add Module.
In the Add New Item - MyServerApp dialog box, click Open.
Add the following code to the Module1.vb module:
Public Const FILE_ATTRIBUTE_NORMAL As Short = &H80S
Public Const FILE_FLAG_NO_BUFFERING As Integer = &H20000000
Public Const FILE_FLAG_WRITE_THROUGH As Integer = &H80000000
Public Const PIPE_ACCESS_DUPLEX As Short = &H3S
Public Const PIPE_READMODE_MESSAGE As Short = &H2S
Public Const PIPE_TYPE_MESSAGE As Short = &H4S
Public Const PIPE_WAIT As Short = &H0S
Public Const INVALID_HANDLE_VALUE As Short = -1
Declare Function CreateNamedPipe Lib "kernel32" Alias "CreateNamedPipeA" _
(ByVal lpName As String, ByVal dwOpenMode As Integer, _
ByVal dwPipeMode As Integer, ByVal nMaxInstances As Integer, _
ByVal nOutBufferSize As Integer, ByVal nInBufferSize As Integer, _
ByVal nDefaultTimeOut As Integer, ByVal lpSecurityAttributes As IntPtr _
) As Integer
Declare Function ConnectNamedPipe Lib "kernel32" _
(ByVal hNamedPipe As Integer, ByVal lpOverlapped As Integer) As Integer
Declare Function DisconnectNamedPipe Lib "kernel32" _
(ByVal hNamedPipe As Integer) As Integer
Declare Function WriteFile Lib "kernel32" _
(ByVal hFile As Integer, ByRef lpBuffer() As Byte, _
ByVal nNumberOfBytesToWrite As Integer, ByRef lpNumberOfBytesWritten As Integer, _
ByVal lpOverlapped As Integer _
) As Integer
Declare Function ReadFile Lib "kernel32" _
(ByVal hFile As Integer, ByRef lpBuffer As Integer, _
ByVal nNumberOfBytesToRead As Integer, ByRef lpNumberOfBytesRead As Integer, _
ByVal lpOverlapped As Integer _
) As Integer
Declare Function FlushFileBuffers Lib "kernel32" _
(ByVal hFile As Integer) As Integer
Declare Function CloseHandle Lib "kernel32" _
(ByVal hObject As Integer) As Integer
After you create a named pipe, wait for the connections from the client. When the client connects to the server, read or write the data over the pipe. To do this, follow these steps:
In Solution Explorer, right-click Form1, and then click Open.
In Design view of the Form1 form, double-click Create a named pipe, and then add the following code to the Button1_Click procedure:
Dim openMode, pipeMode As Integer
'Create the named pipe
openMode = PIPE_ACCESS_DUPLEX Or FILE_FLAG_WRITE_THROUGH
pipeMode = PIPE_WAIT Or PIPE_TYPE_MESSAGE Or PIPE_READMODE_MESSAGE
hPipe = CreateNamedPipe(pipeName, openMode, pipeMode, 10, 10000, 2000, 10000, IntPtr.Zero)
Label1.Text = "Created the named pipe and waiting for the clients."
Button1.Visible = False
Button2.Visible = True
Button3.Visible = True
Add the following code before the Button1_Click procedure:
Private Const pipeName As String = "\\.\pipe\MyPipe"
Private Const BUFFSIZE As Short = 10000
Private Buffer(BUFFSIZE) As Byte
Private hPipe As Integer
In Solution Explorer, double-click Form1.vb.
In Design view of the Form1 form, double-click Wait for the client connections, and then add the following code to the Button2_Click procedure:
Dim byteCount, i, res, cbnCount As Integer
For i = 0 To BUFFSIZE - 1 'Fill an array of numbers
Buffer(i) = i Mod 256
Next i
'Wait for a connection, block until a client connects
Label1.Text = "Waiting for client connections"
Me.Refresh()
Do
res = ConnectNamedPipe(hPipe, 0)
'Read the data sent by the client over the pipe
cbnCount = 4
res = ReadFile(hPipe, byteCount, Len(byteCount), cbnCount, 0)
If byteCount > BUFFSIZE Then 'Client requested for byteCount bytes
byteCount = BUFFSIZE 'but only send up to 20000 bytes
End If
'Write the number of bytes requested by the client
res = WriteFile(hPipe, Buffer, byteCount, cbnCount, 0)
res = FlushFileBuffers(hPipe)
'Disconnect the named pipe.
res = DisconnectNamedPipe(hPipe)
'Loop until the client makes no more requests for data.
Loop Until byteCount = 0
Label1.Text = "Read or Write completed"
Button2.Visible = False
In Design view, double-click Form1, and then add the following code to the Form1_Load procedure:
Button2.Visible = False
Button3.Visible = False
In Solution Explorer, double-click Form1.vb.
In Design view of the Form1 form, double-click Disconnect the server, and then add the following code to the Button3_Click procedure:
Dim res As Integer
'Close the pipe handle when the client makes no requests
CloseHandle(hPipe)
Label1.Text = "Disconnected the named pipe"
To create a named pipe client that communicates with the server, follow these steps:
Call the CreateFile function to create a handle to the named pipe.
Call the ReadFile function or the WriteFile function to communicate over the pipe.
Call the CloseHandle function on the handle that is created in the CreateFile function.
You can also use a named pipe transaction for client/server communication. The named pipe transaction combines a write operation and a read operation in a single network operation. A transaction can be used only on a duplex, message-type pipe. Processes can use the TransactNamedPipe function or the CallNamedPipe function to perform the named pipe transactions.
In this code sample, you use the CallNamedPipe function to connect to the named pipe server, write the data to the pipe, and then read the data from the pipe.
Connect to the named pipe server by using the CallNamedPipe function. After connecting to the server, the CallNamedPipe function writes to the pipe, reads from the pipe, and then closes the pipe. To connect to the server, and then read or write the data, follow these steps:
In Design view, double-click Connect to the server, and then add the following code to the Button1_Click procedure:
Dim i, res, cbRead,numBytes As Integer
Dim bArray() As Byte
Dim temp As String
numBytes = CInt(TextBox1.Text)
If numBytes < 0 Then
MessageBox.Show("Value must be at least 0.", MsgBoxStyle.OKOnly)
Exit Sub
End If
If numBytes = 0 Then
Label1.Visible = True
Label1.Text = "The connection to the server is disconnected."
Button1.Visible = False
TextBox1.Visible = False
TextBox2.Visible = False
End If
If numBytes > BUFFSIZE Then
numBytes = BUFFSIZE
End If
ReDim bArray(numBytes) 'Create the return buffer
'Call the CallNamedPipe function to do the transactions
res = CallNamedPipe(pipeName, numBytes, Len(numBytes), bArray(0), numBytes, cbRead, 30000)
'Wait up to 30 seconds for a response
'Format the data received, and then display the data in the text box
If res > 0 Then
temp = Format(bArray(0), " 000")
For i = 1 To cbRead - 1
If (i Mod 16) = 0 Then temp = temp & vbCrLf
temp = temp & " " & Format(bArray(i), "000")
Next i
TextBox2.Text = temp
Else
MessageBox.Show("Error number " & Err.LastDllError & _
"while trying to call the CallNamedPipe function.", MsgBoxStyle.OKOnly)
End If
Add the following code before the Button1_Click procedure:
Private Const pipeName As String = "\\.\pipe\MyPipe"
Private Const BUFFSIZE As Integer = 10000
Private hpipe As Integer
Public Const INVALID_HANDLE_VALUE As Short = -1
Public Declare Function CallNamedPipe Lib "kernel32" Alias "CallNamedPipeA" _
(ByVal lpNamedPipeName As String, _
ByRef lpInBuffer As Integer, _
ByVal nInBufferSize As Integer, _
ByRef lpOutBuffer As Byte, _
ByVal nOutBufferSize As Integer, _
ByRef lpBytesRead As Integer, ByVal nTimeOut As Integer) As Integer
To verify that your code works, follow these steps:
To start the server application, click Start on the Debug menu of the MyServerApp project.
On the Form1 form, click Create a named pipe, and then click Wait for the client connections. The application is now blocked and waits for the client to connect.
To start the client application, click Start on the Debug menu of the MyClientApp project.
On the Form1 form, type 10 in the TextBox1 box, and then click Connect to the server. You can see the byte array that is received in the TextBox2 box.
To disconnect the client application from the server, type 0 in the TextBox1 box in the client application, and then click Connect to the server.
Close the client application.
To disconnect the server end of the named pipe, and then close the server application, click Disconnect the server on the Form1 form of the server application.