【问题标题】:C# Get standard input/output/error of running, NOT child processC#获取标准输入/输出/运行错误,而不是子进程
【发布时间】:2015-04-16 22:52:07
【问题描述】:

我的问题很简单:如何获得未启动进程的标准输出/输入/错误?假设我有一些程序(不是我的)XYZ,它整天运行并将东西打印到标准输出。我希望能够启动我的 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 的建议,但大多数都声称不起作用,而且我也不太明白如何应用它们。

感谢您的建议!

【问题讨论】:

  • 难道没有针对此的安全原则吗?您可以通过这种方式转移任何进程的标准输入/标准输出,并模仿您想要的任何输入。我认为在没有流程帮助的情况下允许这样做对于任何安全操作系统来说都不是一个好主意。在 Linux 上,进程必须打开要连接的命名管道或 UNIX 套接字,这是有意所必需的。如果 Windows 需要相同的协作,我不会感到惊讶,但如果有人能证明我错了,我会很高兴学习如何做到这一点:)
  • 那么我能不能运行某种包装器/黑盒进程,使用上面的重定向技术启动 XYZ,然后将所有内容重定向到您提到的 Windows 等效套接字?即这个包装器可以提供我需要的任何协作?
  • @Roman 我的建议是您创建一个启动 XYZ 并进行重定向的中间过程,然后简单地开始发布重定向的结果(它可以简单地使用 ZeroMQ 之类的库来完成)。
  • 包装器会将您的问题转换为子进程的简单重定向。您已经在问题中显示了代码,因此您在那里有了答案。接下来,使用 user3473830 提出的 ZeroMQ 技术(这是一个好主意)使其可访问,或者将输出转储到文件中,这很昂贵并且需要适当的 文件滚动,否则你最终会得到一个完整的磁盘。

标签: c# winapi process


【解决方案1】:

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

这是我在 cmets 中建议的简单实现(通过中间过程发布数据)。

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

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);
            }
        }
    }
} 

【讨论】:

  • 这种方法似乎很合适。谢谢!
猜你喜欢
  • 2012-09-17
  • 1970-01-01
  • 2011-12-31
  • 1970-01-01
  • 2017-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多