C#获取标准输入/输出/运行错误,NOT子进程

时间:2015-04-16 22:52:07

标签: c# winapi process

我的问题非常简单:如何获得我没有启动的进程的标准输出/输入/错误?假设我有一些程序(不是我的)XYZ全天运行并将内容打印到stdout。我希望能够启动我的C#应用​​程序并开始阅读XYZ的输出。然后关闭我的C#应用​​程序并在2小时后重新启动它并继续读取输出(不一定是我离开的地方,但这将是一个加号)。

我知道如果XYZ是我的儿童过程

,这可以实现
serverProcess = Process.Start(new ProcessStartInfo()
{
    RedirectStandardError = true,
    RedirectStandardInput = true,
    RedirectStandardOutput = true,
    WorkingDirectory = WorkingDir,
    Arguments = Args,
    FileName = "XYZ",
    UseShellExecute = false
});
serverProcess.OutputDataReceived += serverProcess_OutputDataReceived;
serverProcess.ErrorDataReceived += serverProcess_OutputDataReceived;
serverProcess.BeginOutputReadLine();
serverProcess.BeginErrorReadLine();

但事实并非如此,因为XYZ完全独立于我的应用程序,无论我对它做什么都需要继续运行。 值得注意的是(如果它有帮助)我可以自己启动XYZ(使用那些重定向参数)。只是我的生命周期需要完全独立于XYZ,我需要能够在重新启动后“重新连接”。

我已经看到一些使用Get / SetStdHandle的建议,但大多数声称不起作用,我还是不太明白如何应用它们。

感谢您的任何建议!

1 个答案:

答案 0 :(得分:2)

  

值得注意的是(如果它有帮助)我可以自己启动XYZ(使用那些重定向参数)。只是我的生命周期需要完全独立于XYZ,我需要能够在重新启动后“重新连接”。

以下是我在评论中建议的简单实现(通过中间流程发布数据)。

基本上,样本由3个主要部分组成

<强> 1。样本XYZ过程

在我们的例子中,是一个简单的控制台应用程序,它每秒从XYZ消息中释放一个Hello。

    class Program
    {
        static void Main(string[] args)
        {
           var count = 0;
           while (true)
           {
               Console.WriteLine("Hello from XYZ "+count);
               count++;
               Thread.Sleep(1000);
           }
       }
    }

<强> 2。中介流程

应启动XYZ并将其输出重定向到自身,然后将其发布。对于发布部分,我们在这里使用ZeroMQ库,可以从nuget轻松获得。

class Program
{
    private static Socket _pub;

    static void Main(string[] args)
    {
        using (var context = new Context())
        {
            _pub = context.Socket(SocketType.PUB);
            _pub.Bind("tcp://*:2550");

            StartXyz();

            Console.WriteLine("Press any key to close middle process...");
            Console.ReadKey();
        }
    }

    private static void StartXyz()
    {
         var serverProcess = Process.Start(new ProcessStartInfo
        {
            RedirectStandardError = true,
            RedirectStandardInput = true,
            RedirectStandardOutput = true,
            WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory,
            Arguments = string.Empty,
            FileName = "XYZ.exe",
            UseShellExecute = false
        });
        serverProcess.OutputDataReceived += serverProcess_OutputDataReceived;
        serverProcess.ErrorDataReceived += serverProcess_OutputDataReceived;
        serverProcess.BeginOutputReadLine();
        serverProcess.BeginErrorReadLine();
    }

    private static void serverProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
    {
        _pub.Send(e.Data, Encoding.UTF8);
        Console.WriteLine(e.Data + " pushed.");
    }
}

第3。消费者流程

最后我们有了我们的流程,它消耗了XYZ的重定向数据。

class Program
{
    static void Main(string[] args)
    {
        using (var context = new Context())
        {
            var sub = context.Socket(SocketType.SUB);
            sub.Connect("tcp://localhost:2550");
            sub.Subscribe(string.Empty, Encoding.UTF8);
            while (true)
            {
                var data = sub.Recv(Encoding.UTF8);
                Console.WriteLine(data);
            }
        }
    }
}