监听 C# Process 标准输出的更新答案

作者: 分类: 编程代码 时间:1970-01-01

监听 C# Process 标准输出的更新答案

Listen for updates to standard output of C# Process监听 C# Process 标准输出的更新

我正在使用 C# 进程通过 java 命令运行以下 Java 代码:

public class Test {
    public static void main(String[] args) throws Exception {
        Thread.sleep(2000);
        System.out.print("Hello worl\nd 1!");
        Thread.sleep(2000);
        System.out.println("Hello world 2!");
    }
}

我正在使用以下代码来收听输出:

run.OutputDataReceived += (_, args) => { /* handle output */ };
run.Start();
run.BeginOutputReadLine();

理想情况下,OutputDataReceived 应该被触发两次,对应的值为args.Data

<1234564> <1234563>"Hello worl\nd 1!"<1234563>"Hello world 2!\n"

相反,换行符用于确定何时触发OutputDataReceived。这最终对事件进行了 3 次调用,对应的值为 args.Data

<1234564> <1234563>"Hello worl"<1234563>"d 1!Hello world 2!"<1234563>null

我将如何根据我的第一个场景(每次更新 stdout)而不是当前发生的情况/第二个场景(每当 stdout 收到新行时)运行代码来处理输出?此外,我将如何为 stderr 做同样的事情?

【问题讨论】:

标签: c# .net-core


【解决方案1】:

我认为你想要的是不可能的,这是设计使然。

这些文本流不是由离散的消息组成的,它是一个非常类似于 TCP 套接字的连续字节流。

如果您同时控制流的生产端和消费端,则可以通过在该流之上实现一些帧协议来解决问题。一种对您来说可能已经足够好的简单方法 - 用双换行符分隔消息。这样,在 C# 端,您可以编写代码来读取缓冲区中累积的行,搜索双换行符,当找到或结束流时引发事件以处理完整的消​​息,除非流结束移动剩余部分缓冲区到缓冲区的开头。

另一种解决方法是使用其他 IPC 机制而不是标准输出。在 Windows 上,命名管道支持 PIPE_TYPE_MESSAGE 标志,这会导致管道保留消息边界。同样,Linux 内核支持SOCK_DGRAM 用于 Unix 域套接字。在这两种情况下,常见的设计模式如下所示: 1. 在父 C# 进程中生成唯一的管道/套接字名称,例如通过生成新的 GUID 并打印该 GUID。 2. 创建该名称的管道或套接字。 3. 通过命令行参数或环境变量将该名称传递给子 Java 进程。 4. 在 Java 进程中,通过名称连接管道/套接字,然后您的两个进程之间就有了一个面向消息的双向通信通道。

【讨论】:

    <1234563>
    我找不到任何内置解决方案。我做了一个很多更多挖掘并偶然发现this answer,这就像一个魅力。
【解决方案2】:

对于遇到此问题的其他人,您可以使用this answer 中描述的此解决方案来获取实时输出。

【讨论】: