使用 C# FileStream 创建 Windows 命名管道
Creating a Windows named pipe with a C# FileStream
在 FileStream
class 的 docs 中,Remarks
部分说:
Use the FileStream class to read from, write to, open, and close files on a file system, and to manipulate other file-related operating system handles, including pipes, standard input, and standard output.
我知道 System.IO.Pipes 存在用于创建、读取和写入 Windows 中的管道,但由于我目前正在从事的项目的限制,我无法访问那个包裹。似乎 FileStreams 可以与管道交互,但我似乎无法找到任何有关如何执行此操作的示例。
如何直接使用 FileStream 对 Windows 中的命名管道进行基本 I/O?
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace Test
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateNamedPipe(string lpName, uint dwOpenMode,
uint dwPipeMode, uint nMaxInstances, uint nOutBufferSize, uint nInBufferSize,
uint nDefaultTimeOut, IntPtr lpSecurityAttributes);
static uint PIPE_ACCESS_DUPLEX = 0x00000003;
static uint PIPE_ACCESS_INBOUND = 0x00000001;
static uint PIPE_ACCESS_OUTBOUND = 0x00000002;
static uint FILE_FLAG_FIRST_PIPE_INSTANCE = 0x00080000;
static uint FILE_FLAG_WRITE_THROUGH = 0x80000000;
static uint FILE_FLAG_OVERLAPPED = 0x40000000;
static uint WRITE_DAC = 0x00040000;
static uint WRITE_OWNER = 0x00080000;
static uint ACCESS_SYSTEM_SECURITY = 0x01000000;
//One of the following type modes can be specified. The same type mode must be specified for each instance of the pipe.
static uint PIPE_TYPE_BYTE = 0x00000000;
static uint PIPE_TYPE_MESSAGE = 0x00000004;
//One of the following read modes can be specified. Different instances of the same pipe can specify different read modes
static uint PIPE_READMODE_BYTE = 0x00000000;
static uint PIPE_READMODE_MESSAGE = 0x00000002;
//One of the following wait modes can be specified. Different instances of the same pipe can specify different wait modes.
static uint PIPE_WAIT = 0x00000000;
static uint PIPE_NOWAIT = 0x00000001;
//One of the following remote-client modes can be specified. Different instances of the same pipe can specify different remote-client modes.
static uint PIPE_ACCEPT_REMOTE_CLIENTS = 0x00000000;
static uint PIPE_REJECT_REMOTE_CLIENTS = 0x00000008;
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
var name = "test";
var p = CreateNamedPipe(@"\.\pipe\" + name, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_MESSAGE | PIPE_WAIT, 255, 0, 4096, 0xffffffff, IntPtr.Zero);
if (p.ToInt32() == -1)
{
throw new Exception("Error creating named pipe " + name + " . Internal error: " + Marshal.GetLastWin32Error().ToString());
}
var fs = new FileStream(new Microsoft.Win32.SafeHandles.SafeFileHandle(p, true), FileAccess.Write);
fs.Close();
}
}
}
这似乎工作得很好。比我希望的要丑一些,但并非不可能。感谢@David Browne 为我指明了正确的方向。
更完整的示例:https://www.pinvoke.net/default.aspx/kernel32.createnamedpipe
在 FileStream
class 的 docs 中,Remarks
部分说:
Use the FileStream class to read from, write to, open, and close files on a file system, and to manipulate other file-related operating system handles, including pipes, standard input, and standard output.
我知道 System.IO.Pipes 存在用于创建、读取和写入 Windows 中的管道,但由于我目前正在从事的项目的限制,我无法访问那个包裹。似乎 FileStreams 可以与管道交互,但我似乎无法找到任何有关如何执行此操作的示例。
如何直接使用 FileStream 对 Windows 中的命名管道进行基本 I/O?
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace Test
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateNamedPipe(string lpName, uint dwOpenMode,
uint dwPipeMode, uint nMaxInstances, uint nOutBufferSize, uint nInBufferSize,
uint nDefaultTimeOut, IntPtr lpSecurityAttributes);
static uint PIPE_ACCESS_DUPLEX = 0x00000003;
static uint PIPE_ACCESS_INBOUND = 0x00000001;
static uint PIPE_ACCESS_OUTBOUND = 0x00000002;
static uint FILE_FLAG_FIRST_PIPE_INSTANCE = 0x00080000;
static uint FILE_FLAG_WRITE_THROUGH = 0x80000000;
static uint FILE_FLAG_OVERLAPPED = 0x40000000;
static uint WRITE_DAC = 0x00040000;
static uint WRITE_OWNER = 0x00080000;
static uint ACCESS_SYSTEM_SECURITY = 0x01000000;
//One of the following type modes can be specified. The same type mode must be specified for each instance of the pipe.
static uint PIPE_TYPE_BYTE = 0x00000000;
static uint PIPE_TYPE_MESSAGE = 0x00000004;
//One of the following read modes can be specified. Different instances of the same pipe can specify different read modes
static uint PIPE_READMODE_BYTE = 0x00000000;
static uint PIPE_READMODE_MESSAGE = 0x00000002;
//One of the following wait modes can be specified. Different instances of the same pipe can specify different wait modes.
static uint PIPE_WAIT = 0x00000000;
static uint PIPE_NOWAIT = 0x00000001;
//One of the following remote-client modes can be specified. Different instances of the same pipe can specify different remote-client modes.
static uint PIPE_ACCEPT_REMOTE_CLIENTS = 0x00000000;
static uint PIPE_REJECT_REMOTE_CLIENTS = 0x00000008;
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
var name = "test";
var p = CreateNamedPipe(@"\.\pipe\" + name, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_MESSAGE | PIPE_WAIT, 255, 0, 4096, 0xffffffff, IntPtr.Zero);
if (p.ToInt32() == -1)
{
throw new Exception("Error creating named pipe " + name + " . Internal error: " + Marshal.GetLastWin32Error().ToString());
}
var fs = new FileStream(new Microsoft.Win32.SafeHandles.SafeFileHandle(p, true), FileAccess.Write);
fs.Close();
}
}
}
这似乎工作得很好。比我希望的要丑一些,但并非不可能。感谢@David Browne 为我指明了正确的方向。
更完整的示例:https://www.pinvoke.net/default.aspx/kernel32.createnamedpipe