[英]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 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 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.