Click here to Skip to main content
15,885,652 members
Articles / Programming Languages / C#

Simple Managed Wrapper for Windows Pipes

Rate me:
Please Sign up or sign in to vote.
4.94/5 (18 votes)
4 May 2008Zlib5 min read 61.2K   1.3K   59  
This article presents a very simple and easy to use managed wrapper for Windows Pipes.
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 }
}

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.

License

This article, along with any associated source code and files, is licensed under The zlib/libpng License


Written By
Architect
United States United States
Nothing to brag about, just another passionate software developer.

Work to make a living, don't live to work!

Comments and Discussions