using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.IO;
using Microsoft.Win32.SafeHandles;
namespace WindowsPipes
{
public class ManagedPipe : IDisposable
{
protected const int PIPE_ACCESS_INBOUND = 0x00000001;
protected const int PIPE_ACCESS_OUTBOUND = 0x00000002;
protected const int FILE_FLAG_FIRST_PIPE_INSTANCE = 0x00080000;
protected const int PIPE_TYPE_BYTE = 0x00000000;
protected const int PIPE_READMODE_BYTE = 0x00000000;
protected const int PIPE_WAIT = 0x00000000;
protected const int PIPE_NOWAIT = 0x00000001;
protected const UInt32 GENERIC_READ = 0x80000000;
protected const UInt32 GENERIC_WRITE = 0x40000000;
protected const int OPEN_EXISTING = 3;
protected SafeFileHandle _hSendPipe;
protected SafeFileHandle _hReceivePipe;
protected TextReader _textReader;
protected TextWriter _textWriter;
protected bool _disposed;
protected string _name;
protected ManagedPipeType _type;
protected BlockingMode _blockingMode;
protected UInt32 _inputBufferSize;
protected UInt32 _outputBufferSize;
public string Name
{
get { return _name; }
}
public ManagedPipeType Type
{
get { return _type; }
}
public BlockingMode BlockingMode
{
get { return _blockingMode; }
}
public UInt32 InputBufferSize
{
get { return _inputBufferSize; }
}
public UInt32 OutputBufferSize
{
get { return _outputBufferSize; }
}
public ManagedPipe(string name, ManagedPipeType type, BlockingMode blockingMode,
UInt32 inputBufferSize, UInt32 outputBufferSize)
{
_hSendPipe = null;
_disposed = false;
_name = name;
_type = type;
_blockingMode = blockingMode;
_inputBufferSize = inputBufferSize;
_outputBufferSize = outputBufferSize;
}
public void Open()
{
if (_type == ManagedPipeType.Server)
CreateServer();
else
CreateClient();
_textReader = new StreamReader(new FileStream(_hReceivePipe, FileAccess.Read));
_textWriter = new StreamWriter(new FileStream(_hSendPipe, FileAccess.Write));
}
public void Send(string message)
{
if (_hSendPipe == null)
throw new InvalidOperationException("Pipe is not open.");
_textWriter.WriteLine(message);
_textWriter.Flush();
}
public string Receive()
{
if (_hReceivePipe == null)
throw new InvalidOperationException("Pipe is not open.");
return _textReader.ReadLine();
}
public void WaitForClientToConnect()
{
if (_type != ManagedPipeType.Server)
throw new InvalidOperationException(
"WaitForClientToConnect() is not a valid call for a non Server pipe.");
ConnectNamedPipe(_hSendPipe, IntPtr.Zero);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
if (_textReader != null)
_textReader.Dispose();
if (_textWriter != null)
_textWriter.Dispose();
_hSendPipe.Dispose();
_hReceivePipe.Dispose();
_hSendPipe = null;
_hReceivePipe = null;
}
_disposed = true;
}
}
~ManagedPipe()
{
Dispose(false);
}
protected void CreateServer()
{
UInt32 pipeMode;
if (_blockingMode == BlockingMode.Wait)
pipeMode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT;
else
pipeMode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_NOWAIT;
_hSendPipe = CreateNamedPipe(@"\\.\pipe\Send_" + _name,
PIPE_ACCESS_OUTBOUND,
pipeMode,
1,
_outputBufferSize,
_inputBufferSize,
0,
IntPtr.Zero);
if (_hSendPipe.IsInvalid)
throw new Win32Exception(Marshal.GetLastWin32Error());
_hReceivePipe = CreateNamedPipe(@"\\.\pipe\Receive_" + _name,
PIPE_ACCESS_INBOUND,
pipeMode,
1,
_outputBufferSize,
_inputBufferSize,
0,
IntPtr.Zero);
if (_hReceivePipe.IsInvalid)
throw new Win32Exception(Marshal.GetLastWin32Error());
}
protected void CreateClient()
{
_hSendPipe = CreateFile(@"\\.\pipe\Receive_" + _name,
GENERIC_WRITE,
0,
IntPtr.Zero,
OPEN_EXISTING,
0,
IntPtr.Zero);
if (_hSendPipe.IsInvalid)
throw new Win32Exception(Marshal.GetLastWin32Error());
_hReceivePipe = CreateFile(@"\\.\pipe\Send_" + _name,
GENERIC_READ,
0,
IntPtr.Zero,
OPEN_EXISTING,
0,
IntPtr.Zero);
if (_hReceivePipe.IsInvalid)
throw new Win32Exception(Marshal.GetLastWin32Error());
}
[DllImport("Kernel32.dll", SetLastError = true)]
extern static SafeFileHandle CreateNamedPipe(string name, UInt32 openMode, UInt32 pipeMode,
UInt32 maxInstances, UInt32 outBufferSize, UInt32 inBufferSize, UInt32 defaultTimeOut,
IntPtr securityAttributes);
[DllImport("Kernel32.dll", SetLastError = true)]
extern static SafeFileHandle CreateFile(string name, UInt32 desiredAccess, UInt32 shareMode,
IntPtr securityAttributes, UInt32 creationDisposition, UInt32 flagsAndAttributes,
IntPtr templateFile);
[DllImport("Kernel32.dll", SetLastError = true)]
extern static Int32 ConnectNamedPipe(SafeFileHandle namedPipe, IntPtr overlapped);
}
public enum BlockingMode { Wait, NoWait }
public enum ManagedPipeType { Client, Server }
}