我正在尝试在.NET中启动子进程并将其输出重定向到命名管道。尝试写入子进程中的stdout应该阻塞,直到客户端实际读取命名管道。
这是我的代码:
using System;
using System.Diagnostics;
using System.IO.Pipes;
namespace psub
{
class Program
{
static void Main(string[] args)
{
var pipeName = "testpipe"; // Guid.NewGuid().ToString();
Console.WriteLine($@"\\.\pipe\{pipeName}");
var psi = new ProcessStartInfo()
{
FileName = "ping",
Arguments = "google.com",
UseShellExecute = false,
RedirectStandardOutput = true
};
using (var pipeServer = new NamedPipeServerStream(pipeName, PipeDirection.Out))
using (var process = new Process { StartInfo = psi })
{
pipeServer.WaitForConnection();
process.Start();
process.StandardOutput.BaseStream.CopyTo(pipeServer);
process.WaitForExit();
}
}
}
}
当我启动此可执行文件时,它会按预期在pipeServer.WaitForConnection();
处阻止。然后我打开cmd.exe
并运行type \\.\pipe\testpipe
,尝试从命名管道[1]中读取。
这会导致以下错误(在cmd会话中):
All pipe instances are busy.
此外,在C#程序中,pipeServer.WaitForConnection
完成,执行进行到...CopyTo(pipeServer)
,其爆炸为:
Unhandled Exception: System.IO.IOException: Pipe is broken.
我不明白为什么会发生All pipe instances are busy.
错误。
根据我的理解,有一个服务器(在C#程序中实例化)将写入命名管道。一旦执行到CopyTo
,数据将被传送到程序的单个被阻塞线程上的命名管道服务器。
还有一个命名的管道客户端(type \\.\pipe\testpipe
进程),它将减轻服务器尝试写入的数据的命名管道。
那么为什么会出现“所有管道实例都忙”错误?
我已经尝试将new NamedPipeServerStream(pipeName, PipeDirection.Out)
调整为new NamedPipeServerStream(pipeName, PipeDirection.Out, 2)
以及其他调整,但没有真正了解问题是什么或如何解决问题。有人可以像我五岁那样解释一下吗?
[1]:目标是模拟UNIX shell中可用的process substitution功能,因此我必须能够从\\.\pipe\<some file name>
读取,而不是使用C ++或.NET来实例化管道的客户。
答案 0 :(得分:2)
在cmd中使用type <some_file_name>
时,首先为此GetFileAttributes
<some_file_name>
GetFileAttributes
内部(内部内核)临时打开文件,用于查询它的属性(实际上 - 需要查询文件系统设备以及发送查询请求 - 需要打开文件)。
对于命名管道文件,这会产生致命的副作用 - 服务器端连接(打开文件)并且只是断开连接(关闭时)。
仅在此cmd(再次)打开文件
之后但您的管道服务器已经没有监听(断开连接后)。结果cmd通常收到STATUS_PIPE_NOT_AVAILABLE
错误 - 在侦听状态下找不到命名管道的实例。 - 它转换为win32错误ERROR_PIPE_BUSY
- 所有管道实例正忙着
作为单独的注释 - 3种不同的状态错误:
STATUS_INSTANCE_NOT_AVAILABLE
(已达到最大命名管道实例数。)
STATUS_PIPE_NOT_AVAILABLE
(在侦听状态下无法找到命名管道的实例。)
和STATUS_PIPE_BUSY
转换为相同的单个win32错误ERROR_PIPE_BUSY
。但在您的情况下,原始错误恰好是STATUS_PIPE_NOT_AVAILABLE
结论 - cmd type
命令不设计与管道交互。或者您需要创建最小2个管道在同一管道名称上的结束方式。
答案 1 :(得分:-2)
您无法通过Windows命名管道的命令行界面进行访问。有关详细信息,请参阅http://en.wikipedia.org/wiki/Named_pipe