Visual Basic .NET & named pipes

A

andrewb

Hi all,

Having some trouble using named pipes and Visual Basic .NET and would
appreciate and help you could offer.

Essentially I am trying to develop a simple client/server application
that exchanges text messages using named pipes. The internet resources
seem a bit scarce and the only Microsoft resource I can find is
http://support.microsoft.com/kb/871044.

I have managed to get the above KB example working but I am struggling
to convert it to just use string data between the client & server.

Anyone done this already using Visual Basic .NET?

Cheers.
 
K

kimiraikkonen

Hi all,

Having some trouble using named pipes and Visual Basic .NET and would
appreciate and help you could offer.

Essentially I am trying to develop a simple client/server application
that exchanges text messages using named pipes. The internet resources
seem a bit scarce and the only Microsoft resource I can find ishttp://support.microsoft.com/kb/871044.

I have managed to get the above KB example working but I am struggling
to convert it to just use string data between the client & server.

Anyone done this already using Visual Basic .NET?

Cheers.

Hi,
I hope that provides better info for sending strings using pipes:
http://msdn.microsoft.com/en-us/library/system.io.pipes.anonymouspipeserverstream.aspx

or:

http://msdn.microsoft.com/en-us/library/system.io.pipes.aspx

However you can also consider using System.Net.Sockets.

HTH,

Onur Güzel
 
A

andrewb

Thanks for the help guys - appreciate it

I am using Visual Studio 2005, still unable to get a string through -
here is my code, hopefully you can spot my error(s) :

Server code
=========

Dim pipeName As String = "\\.\pipe\MServerPipe"
Dim hPipe As Integer
Dim openMode, pipeMode As Integer

Dim stringIn As String
Dim dataIn(256) As Byte

Dim res, nChars As Integer

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)

res = ConnectNamedPipe(hPipe, 0)

res = ReadFile(hPipe, dataIn, 256, nChars, 0)
stringIn = System.Text.Encoding.ASCII.GetString(dataIn)

CloseHandle(hPipe)

Client code
========

Dim pipeName As String = "\\.\pipe\MServerPipe"

Dim res, cbRead, numBytes As Integer
Dim stringOut As String
Dim dataOut(256), dataIn(256) As Byte

stringOut = "This is a test"
dataOut = System.Text.Encoding.ASCII.GetBytes(stringOut)

res = CallNamedPipe(pipeName, dataOut, stringOut.Length,
dataIn, numBytes, cbRead, 30000)

API declarations
============

Public Declare Function CallNamedPipe Lib "kernel32" Alias
"CallNamedPipeA" _
(ByVal lpNamedPipeName As String, _
ByRef lpInBuffer() As Byte, _
ByVal nInBufferSize As Integer, _
ByRef lpOutBuffer() As Byte, _
ByVal nOutBufferSize As Integer, _
ByRef lpBytesRead As Integer, ByVal nTimeOut 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, ByVal lpBuffer() As Byte, _
ByVal nNumberOfBytesToRead As Integer, ByRef
lpNumberOfBytesRead As Integer, _
ByVal lpOverlapped As Integer _
) As Integer
 
H

Herfried K. Wagner [MVP]

andrewb said:
Dim pipeName As String = "\\.\pipe\MServerPipe"

Dim res, cbRead, numBytes As Integer
Dim stringOut As String
Dim dataOut(256), dataIn(256) As Byte

Note that these arrays will have 257 elements with indices running from 0 to
256.
Public Declare Function CallNamedPipe Lib "kernel32" Alias
"CallNamedPipeA" _

Is there any reason you are using the Windows ANSI version of the function?
If not, use 'Public Declare Auto Function' and remove the alias.

ByRef lpBytesRead As Integer, ByVal nTimeOut As Integer) As
Integer

=> 'As Boolean'.
Declare Function WriteFile Lib "kernel32" _
(ByVal hFile As Integer

=> 'ByVal hFile As IntPtr'.

, ByRef lpBuffer() As Byte, _
ByVal nNumberOfBytesToWrite As Integer, ByRef
lpNumberOfBytesWritten As Integer, _
ByVal lpOverlapped As Integer _

=> 'As IntPtr'.
) As Integer

=> 'As Boolean'.

The same applies to 'ReadFile'.
 
A

andrewb

Ok... I looked at their sample, and here is what I have:

' client
Option Strict On
Option Explicit On

Imports System.Text

Module Module1

    Sub Main()

        Dim outBuffer() As Byte = Encoding.ASCII.GetBytes("Hi, Server!")
        Dim inBuffer(BUFFSIZE) As Byte
        Dim bytesRead As Integer

        'Call the CallNamedPipe function to do the transactions
        CallNamedPipe(pipeName, outBuffer, outBuffer.Length, inBuffer, inBuffer.Length, bytesRead, 30000)
        Console.WriteLine(Encoding.ASCII.GetString(inBuffer, 0, bytesRead))
    End Sub

    Private Const pipeName As String = "\\.\pipe\MyPipe"
    Private Const BUFFSIZE As Integer = 10000
    Private hpipe As IntPtr

    Public ReadOnly INVALID_HANDLE_VALUE As IntPtr = New IntPtr(-1)

    Public Declare Auto Function CallNamedPipe Lib "kernel32" ( _
        ByVal lpNamedPipeName As String, _
        ByVal lpInBuffer() As Byte, _
        ByVal nInBufferSize As Integer, _
        ByVal lpOutBuffer() As Byte, _
        ByVal nOutBufferSize As Integer, _
        ByRef lpBytesRead As Integer, _
        ByVal nTimeOut As Integer) As Boolean

End Module

' server
Option Strict On
Option Explicit On

Imports System.Text

Module Module1
    Private Const pipeName As String = "\\.\pipe\MyPipe"
    Private Const BUFFSIZE As Short = 10000
    Private hPipe As IntPtr

    Sub Main()
        Dim openMode As Integer
        Dim 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)
        If hPipe <> INVALID_HANDLE_VALUE Then
            Console.WriteLine("Created the named pipe and waiting for the clients.")

            Dim byteCount As Integer
            Dim i As Integer
            Dim cbnCount As Integer

            Dim outBuffer() As Byte = Encoding.ASCII.GetBytes("Hello from the server")
            Dim inputBuffer(BUFFSIZE) As Byte

            'Wait for a connection, block until a client connects
            Console.WriteLine("Waiting for client connections")

            Do
                ConnectNamedPipe(hPipe, IntPtr.Zero)

                ''Read the data sent by the client over the pipe
                cbnCount = BUFFSIZE
                ReadFile(hPipe, inputBuffer, inputBuffer.Length, cbnCount, IntPtr.Zero)
                Console.WriteLine("Client Says {0}", Encoding.ASCII.GetString(inputBuffer, 0, cbnCount))

                WriteFile(hPipe, outBuffer, outBuffer.Length, cbnCount, IntPtr.Zero)
                'res = FlushFileBuffers(hPipe)
                ''Disconnect the named pipe.
                DisconnectNamedPipe(hPipe)
                'Loop until the client makes no more requests for data.
            Loop Until byteCount = 0

            Console.WriteLine("Read or Write completed")

            'Close the pipe handle when the client makes no requests
            CloseHandle(hPipe)
            Console.WriteLine("Disconnected the named pipe")
        Else
            Console.WriteLine("Pipe creation failed")
        End If
    End Sub

    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 ReadOnly INVALID_HANDLE_VALUE As IntPtr = New IntPtr(-1)

    Declare Auto Function CreateNamedPipe Lib "kernel32" ( _
        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 IntPtr

    Declare Function ConnectNamedPipe Lib "kernel32" ( _
        ByVal hNamedPipe As IntPtr, _
        ByVal lpOverlapped As IntPtr _
    ) As Boolean

    Declare Function DisconnectNamedPipe Lib "kernel32" ( _
        ByVal hNamedPipe As IntPtr _
    ) As Boolean

    Declare Function WriteFile Lib "kernel32" ( _
        ByVal hFile As IntPtr, _
        ByVal lpBuffer() As Byte, _
        ByVal nNumberOfBytesToWrite As Integer, _
        ByRef lpNumberOfBytesWritten As Integer, _
        ByVal lpOverlapped As IntPtr _
    ) As Integer

    Declare Function ReadFile Lib "kernel32" ( _
        ByVal hFile As IntPtr, _
        ByVal lpBuffer() As Byte, _
        ByVal nNumberOfBytesToRead As Integer, _
        ByRef lpNumberOfBytesRead As Integer, _
        ByVal lpOverlapped As IntPtr _
    ) As Integer

    Declare Function FlushFileBuffers Lib "kernel32" _
        (ByVal hFile As IntPtr) As Integer

    Declare Function CloseHandle Lib "kernel32" _
        (ByVal hObject As IntPtr) As Integer

End Module

They made a lot of strange choices for their declares :) Anyway - hope this
helps.

Awesome - job done - thanks Tom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top