我想使用除stdin,stdout和stderr之外的管道与子进程进行通信。我正在尝试为此使用Mono.Unix.UnixPipes.CreatePipes。但是,我找不到任何示例,我对如何使用它的最佳猜测不起作用。看来我用Process.Start创建的子进程无法写入继承的文件句柄。我想知道它是否实际上没有继承柄。这是我的(减少)代码:如何正确使用Mono.Unix.UnixPipes.CreatePipes?
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Threading;
using System.Collections.Generic;
using Mono.Unix;
class Program
{
static void Main(string[] args)
{
if (args.Length==0)
{
InvokeChildProcess(args);
}
else
{
RunAsChildProcess(args);
}
}
static int InvokeChildProcess(string[] aArgs)
{
var childToParentPipe = Mono.Unix.UnixPipes.CreatePipes();
var childToParentStream = childToParentPipe.Reading;
string childHandle = childToParentPipe.Writing.Handle.ToString();
var startInfo = new ProcessStartInfo(
System.Reflection.Assembly.GetExecutingAssembly().Location,
childHandle)
{
UseShellExecute = false,
};
Process childProcess = Process.Start(startInfo);
childToParentPipe.Writing.Close();
using (var reader = new StreamReader(childToParentStream))
{
Console.WriteLine("[PARENT] Waiting for child output...");
string output = reader.ReadToEnd();
Console.Write("[PARENT] Received output ({0} chars): ", output.Length);
Console.WriteLine(output);
Console.WriteLine("[PARENT] Waiting for child to exit...");
childProcess.WaitForExit();
Console.WriteLine("[PARENT] Saw child exit with code {0}.", childProcess.ExitCode);
return childProcess.ExitCode;
}
}
static void RunAsChildProcess(string[] args)
{
int handle=int.Parse(args[0]);
Console.WriteLine("[CHILD] Writing to file handle {0}.", handle);
var pipeToParent = new Mono.Unix.UnixStream(handle);
Thread.Sleep(2000);
using (var writer = new StreamWriter(pipeToParent))
{
writer.WriteLine("Message from child.");
writer.Flush();
Environment.Exit(123);
}
}
}
下面是输出在运行时:
[email protected]:~/dev$ mono MinimalPipeTest.exe
[PARENT] Waiting for child output...
[PARENT] Received output (0 chars):
[PARENT] Waiting for child to exit...
[CHILD] Writing to file handle 4.
Unhandled Exception: System.ArgumentException: Can not write to stream
at System.IO.StreamWriter..ctor (System.IO.Stream stream, System.Text.Encoding encoding, Int32 bufferSize) [0x00000] in <filename unknown>:0
at System.IO.StreamWriter..ctor (System.IO.Stream stream) [0x00000] in <filename unknown>:0
at (wrapper remoting-invoke-with-check) System.IO.StreamWriter:.ctor (System.IO.Stream)
at Program.RunAsChildProcess (System.String[] args) [0x00000] in <filename unknown>:0
at Program.Main (System.String[] args) [0x00000] in <filename unknown>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.ArgumentException: Can not write to stream
at System.IO.StreamWriter..ctor (System.IO.Stream stream, System.Text.Encoding encoding, Int32 bufferSize) [0x00000] in <filename unknown>:0
at System.IO.StreamWriter..ctor (System.IO.Stream stream) [0x00000] in <filename unknown>:0
at (wrapper remoting-invoke-with-check) System.IO.StreamWriter:.ctor (System.IO.Stream)
at Program.RunAsChildProcess (System.String[] args) [0x00000] in <filename unknown>:0
at Program.Main (System.String[] args) [0x00000] in <filename unknown>:0
[PARENT] Saw child exit with code 1.
[email protected]:~/dev$
这个例子是编译和单2.10运行分布式在Ubuntu解梦。
我在做什么错?我如何确保子进程能够写入管道?
编辑 - 它看起来像的Process.Start确实关闭所有的文件描述符,在子进程除0,1和2在这里看到的CreateProcess:
https://github.com/mono/mono/blob/master/mono/io-layer/processes.c#L988
for (i = getdtablesize() - 1; i > 2; i--) {
close (i);
}
我想这意味着我不能使用UnixPipes和Process.Start。有另一种方法吗?
这取决于你想达到什么。 Process.Start并不能保证新创建的进程是子进程,即使子进程的概念完全存在 - 毕竟它必须是跨平台的。您可以创建线程并使用未命名的管道进行通信,但这是您需要的吗? – 2012-01-16 16:21:17