简体   繁体   English

.NET应用程序如何重定向自己的标准输入流?

[英]How does a .NET app redirect its own Standard Input stream?

I am attempting bidirectional communication (IPC) between 2 C# Apps using only Standard Input streams. 我正在尝试仅使用标准输入流的2 C#应用之间的双向通信(IPC)。 The parent app launches the child app with a Process , where RedirectStandardInput = true . 父应用程序使用Process启动子应用Process ,其中RedirectStandardInput = true So the parent process is able to send commands to the child process using childProc.StandardInput.WriteLine() . 因此父进程能够使用childProc.StandardInput.WriteLine()将命令发送到子进程。 I am capturing these messages asynchronously using BeginRead() and EndRead() of the stream acquired with Console.OpenStandardInput() . 我使用Console.OpenStandardInput()获取的流的BeginRead()EndRead()异步捕获这些消息。 Parent to child communication is working great. 父母与孩子之间的沟通非常有效。 I am able to send and receive messages asynchronously. 我能够异步发送和接收消息。

But when the child attempts to write to the parent, using the same code, .NET throws this error: 但是当孩子尝试使用相同的代码写入父级时,.NET会抛出此错误:

StandardInput has not been redirected. StandardInput尚未重定向。

So, in simple terms, how does a .NET app redirect its own standard input stream? 因此,简单来说, .NET应用程序如何重定向自己的标准输入流? I will then redirect the standard input stream of my parent process, so the child can send messages to it. 然后,我将重定向父进程的标准输入流,以便子进程可以向其发送消息。

My parent process is a WinForms C# App built with .NET 4.0 x86. 我的父进程是使用.NET 4.0 x86构建的WinForms C#应用程序。


Edit: Here is the code of the IPC Server 编辑:这是IPC服务器的代码

internal class IPCServer {

    private Stream cmdStream;
    private byte[] cmdBuffer = new byte[4096];

    public IPCServer() {

        cmdStream = Console.OpenStandardInput(4096);

        GetNextCmd();
    }

    private void GetNextCmd() {

        // wait for next
        cmdStream.BeginRead(cmdBuffer, 0, cmdBuffer.Length, CmdRecived, null);
    }

    private void CmdRecived(IAsyncResult ar) {

        // input read asynchronously completed
        int bytesRead = 0;
        try {
            bytesRead = cmdStream.EndRead(ar);
        } catch (Exception) { }
        if (bytesRead > 0) {

            // accept cmd
            .........

            // wait for next
            GetNextCmd();
        }
    }


}

And here is the code of the IPC Client 这是IPC客户端的代码

internal class IPCClient {

    private Process appProc;

    public IPCClient(Process appProcess) {

        if (!appProcess.StartInfo.RedirectStandardInput) {
            //MessageBox.Show("IPCClient : StandardInput for process '" + appProcess.ProcessName + "' has not been 'redirected'!");
            return;
        }

        appProc = appProcess;

    }

    public void SendCmd(string cmd) {

        if (appProc != null) {
            appProc.StandardInput.WriteLine(cmd);
        }

    }

}

In the parent process: 在父进程中:

// open child app
ProcessStartInfo info = new ProcessStartInfo(childProcPath, args);
info.WorkingDirectory = childProcDir;
info.LoadUserProfile = true;
info.UseShellExecute = false;
info.RedirectStandardError = true;
info.RedirectStandardOutput = true;
info.RedirectStandardInput = true;

childProc = Process.Start(info);

// connect to app for IPC
Client = new IPCClient();
Client.Init(childProc);

// recieve cmds from app
Server = new IPCServer();
Server.OnCmdRecieved = GotCmd;
Server.Init();

In the child process: 在子进程中:

ownerProcess = ....

Server = new IPCServer();
Server.OnCmdRecieved = GotCmd;
Server.Init();

Client = new IPCClient();
Client.Init(ownerProcess);

You can do it in a more convenient way. 您可以以更方便的方式完成。 Just make your client application know nothing about input \\ output redirection. 只需让您的客户端应用程序对输入\\输出重定向一无所知。 Server should bother about redirection. 服务器应该打扰重定向。

I have implemented a simplest client-server application using your technique, which demonstrates how it should be used. 我使用您的技术实现了一个最简单的客户端 - 服务器应用程序,它演示了如何使用它。

Client 客户

Client is a simplest application, which simply echoes the message back and closes when you enter exit : 客户端是一个最简单的应用程序,只需回传消息并在您进入exit时关闭:

static void Main(string[] args)
{
    string str;

    do
    {
        str = Console.ReadLine();

        Console.WriteLine("Executed: " + str);
    } while (str != "exit");
}

The client knows nothing about redirection, it simply works like a console application and reads \\ writes into a console. 客户端对重定向一无所知,它只是像控制台应用程序一样工作,并在控制台中读取\\写入。

Server 服务器

Server runs client processes and reads \\ writes in its streams. 服务器运行客户端进程并在其流中读取\\写入。

Process p = new Process();

p.StartInfo.FileName = "ConsoleApplication1.exe";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;

p.Start();

p.StandardInput.WriteLine("a");
p.StandardInput.WriteLine("b");
p.StandardInput.WriteLine("c");
p.StandardInput.WriteLine("d");
p.StandardInput.WriteLine("exit");
p.StandardInput.WriteLine("f");

p.StandardInput.Close();

string res = p.StandardOutput.ReadToEnd();

After execution of this code, res contains the following text: 执行此代码后,res包含以下文本:

Executed: a
Executed: b
Executed: c
Executed: d
Executed: exit

What if the child process simply uses BeginRead() and EndRead() on the child process' StandardOutput stream. 如果子进程只是在子进程'StandardOutput流上使用BeginRead()EndRead() ,该怎么办? That should work! 这应该工作!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM