|
Imports System.Threading, System.Runtime.InteropServices
Friend Class ServerPipeInstance
Implements IDisposable
Private mAccess As IO.FileAccess, mBufferSize As Integer, mIsAsync As Boolean
Public Function GetStream() As IO.Stream
Return New IO.FileStream(Me.Handle, mAccess, mBufferSize, mIsAsync)
End Function
''' <summary>
'''
''' </summary>
''' <param name="Name">Pipe name. Must be up to 246 characters long and without backslashes (\).</param>
''' <param name="access">Access to the pipe.</param>
''' <param name="bufferSize">Size of input/output buffers.</param>
''' <param name="isAsync">True to enable overlapped input/output.</param>
''' <remarks></remarks>
Public Sub New(ByVal name As String, ByVal access As IO.FileAccess, ByVal bufferSize As Integer, ByVal isAsync As Boolean)
If name.Contains("\") Or name = "" Or name.Length > 247 Then Throw New ArgumentException("Pipe name must be between 1 and 247 characters long and it cannot contain backslash (\).")
mAccess = access
mBufferSize = bufferSize
mIsAsync = isAsync
mName = name
Dim mode As Integer = access
If isAsync Then
mode = mode Or NativeMethods.FILE_FLAG_OVERLAPPED
End If
mHandle = New Microsoft.Win32.SafeHandles.SafeFileHandle( _
NativeMethods.CreateNamedPipe(Me.FullName, _
mode, _
NativeMethods.PIPE_WAIT Or NativeMethods.PIPE_TYPE_BYTE, _
NativeMethods.PIPE_UNLIMITED_INSTANCES, _
bufferSize, bufferSize, _
NativeMethods.NMPWAIT_WAIT_FOREVER, 0) _
, True)
If Handle.IsInvalid Then ThrowUnknownException("CreateNamedPipe")
End Sub
Private Sub ThrowUnknownException(ByVal FunctionName As String)
Throw New InvalidOperationException("Error #" & Marshal.GetLastWin32Error & " was returned by the operating system while calling " & FunctionName & ".", New System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error))
End Sub
Public Sub Connect()
Dim result As Integer = NativeMethods.ConnectNamedPipe(Me.Handle.DangerousGetHandle, Nothing)
If result = 0 Then ThrowUnknownException("ConnectNamedPipe")
End Sub
''' <summary>
''' Begins the connection operation with and returns an instance of AsyncOperationInfo which the caller can use to wait until a client connects.
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Function BeginConnect(ByVal DelegateCallback As AsyncCallback, ByVal DelegateAsyncState As Object) As IAsyncResult
If Not mIsAsync Then Throw New InvalidOperationException("This function cannot be used unless the isAsync parameter in the constructor is set to True.")
Dim Async As New AsyncOperationInfo(Me.Handle, DelegateAsyncState, DelegateCallback)
If NativeMethods.ConnectNamedPipe(Me.Handle.DangerousGetHandle, Async.Overlapped) = 0 Then
Select Case Err.LastDllError
Case NativeMethods.ERROR_IO_PENDING
Return Async
Case NativeMethods.ERROR_PIPE_CONNECTED
Async.SetCompletedSynchronously()
Return Async
Case Else
ThrowUnknownException("ConnectNamedPipe")
Return Nothing
End Select
Else
Async.SetCompletedSynchronously()
Return Async
End If
End Function
''' <summary>
''' Disconnects the client currently connected in order to allow the next client to connect.
''' </summary>
''' <remarks></remarks>
Public Sub Disconnect()
If Not NativeMethods.DisconnectNamedPipe(Me.Handle.DangerousGetHandle) Then
ThrowUnknownException("DisconnectNamedPipe")
End If
End Sub
''' <summary>
''' Ends the connect operation.
''' </summary>
''' <param name="ar">The instance of IAsyncResult that was returned by BeginConnect.</param>
''' <remarks></remarks>
Public Sub EndConnect(ByVal ar As IAsyncResult)
EndAsyncOperation(ar, True, 0)
End Sub
Private Function EndAsyncOperation(ByVal AsyncInfo As AsyncOperationInfo, ByVal Wait As Boolean, ByRef BytesRead As Integer) As Boolean
Dim R As Boolean = NativeMethods.GetOverlappedResult(Me.Handle.DangerousGetHandle, AsyncInfo.Overlapped, BytesRead, Wait)
If R Then AsyncInfo.AsyncWaitHandle.Close()
Return R
End Function
Private mName As String
Public Property Name() As String
Get
Return mName
End Get
Set(ByVal value As String)
mName = value
End Set
End Property
Public ReadOnly Property FullName() As String
Get
Return "\\.\pipe\" + Me.Name
End Get
End Property
''' <summary>
''' Returns the handle of the named pipe.
''' </summary>
''' <remarks></remarks>
Private mHandle As Microsoft.Win32.SafeHandles.SafeFileHandle
Public ReadOnly Property Handle() As Microsoft.Win32.SafeHandles.SafeFileHandle
Get
Return mHandle
End Get
End Property
Private Class AsyncOperationInfo
Implements IAsyncResult
Private mOverlapped As NativeOverlapped
Private mWaitHandle As WaitHandle
Private mPipeHandle As Microsoft.Win32.SafeHandles.SafeFileHandle
Private mState As Object
Private mCallback As AsyncCallback
Private mComplete As Boolean
Friend Sub New(ByVal PipeHandle As Microsoft.Win32.SafeHandles.SafeFileHandle, ByVal state As Object, ByVal DelegateAsyncCallback As AsyncCallback)
mWaitHandle = New ManualResetEvent(False)
mOverlapped.EventHandle = mWaitHandle.SafeWaitHandle.DangerousGetHandle
mCallback = DelegateAsyncCallback
mState = state
mPipeHandle = PipeHandle
Dim D As New iWaitForSignal(AddressOf WaitForSignal)
' D.BeginInvoke(Nothing, Nothing)
End Sub
Friend Sub SetCompletedSynchronously()
mCompletedSynchronously = True
End Sub
Friend Sub SetOffset(ByVal o As Integer)
mOverlapped.OffsetLow = o
End Sub
Private mCompletedSynchronously As Boolean
Friend ReadOnly Property Overlapped() As NativeOverlapped
Get
Return mOverlapped
End Get
End Property
Public ReadOnly Property AsyncState() As Object Implements System.IAsyncResult.AsyncState
Get
Return mState
End Get
End Property
Public ReadOnly Property AsyncWaitHandle() As System.Threading.WaitHandle Implements System.IAsyncResult.AsyncWaitHandle
Get
Return mWaitHandle
End Get
End Property
Public ReadOnly Property CompletedSynchronously() As Boolean Implements System.IAsyncResult.CompletedSynchronously
Get
Return mCompletedSynchronously
End Get
End Property
Public ReadOnly Property IsCompleted() As Boolean Implements System.IAsyncResult.IsCompleted
Get
Return mComplete
End Get
End Property
Private Delegate Sub iWaitForSignal()
Private Sub WaitForSignal()
Me.AsyncWaitHandle.WaitOne()
If Not mCallback Is Nothing Then mCallback.Invoke(Me)
Me.AsyncWaitHandle.Close()
mComplete = True
End Sub
End Class
Private disposedValue As Boolean = False ' To detect redundant calls
' IDisposable
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
Handle.Close()
End If
End If
Me.disposedValue = True
End Sub
#Region " IDisposable Support "
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.
A list of licenses authors might use can be found here