.NET 应用程序如何重定向其自己的标准输入流?
How does a .NET app redirect its own Standard Input stream?
我正在尝试仅使用标准输入流在 2 个 C# 应用程序之间进行双向通信 (IPC)。父应用程序使用 Process
启动子应用程序,其中 RedirectStandardInput = true
。所以父进程可以使用 childProc.StandardInput.WriteLine()
向子进程发送命令。我使用通过 Console.OpenStandardInput()
获取的流的 BeginRead()
和 EndRead()
异步捕获这些消息。亲子沟通效果很好。我能够异步发送和接收消息。
但是,当子项尝试使用相同的代码写入父项时,.NET 会抛出此错误:
StandardInput has not been redirected.
所以,简单来说,.NET 应用程序如何重定向它自己的标准输入流?然后我将重定向我父进程的标准输入流,所以子进程可以向它发送消息。
我的父进程是使用 .NET 4.0 x86 构建的 WinForms C# 应用程序。
编辑:这是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();
}
}
}
这里是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);
}
}
}
在父进程中:
// 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();
在子进程中:
ownerProcess = ....
Server = new IPCServer();
Server.OnCmdRecieved = GotCmd;
Server.Init();
Client = new IPCClient();
Client.Init(ownerProcess);
你可以用更方便的方式来做。只需让您的客户端应用程序对输入\输出重定向一无所知。
服务器应该关心重定向。
我已经使用您的技术实现了一个最简单的客户端-服务器应用程序,它演示了应该如何使用它。
客户
客户端是最简单的应用程序,当您输入 exit
:
时,它只是回显消息并关闭
static void Main(string[] args)
{
string str;
do
{
str = Console.ReadLine();
Console.WriteLine("Executed: " + str);
} while (str != "exit");
}
客户端对重定向一无所知,它只是像控制台应用程序一样工作,并在控制台中读取\写入。
服务器
服务器运行客户端进程并在其流中读取\写入。
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();
执行此代码后,res 包含以下文本:
Executed: a
Executed: b
Executed: c
Executed: d
Executed: exit
如果子进程仅在子进程的 StandardOutput 流上使用 BeginRead()
和 EndRead()
会怎样?那应该有用!
我正在尝试仅使用标准输入流在 2 个 C# 应用程序之间进行双向通信 (IPC)。父应用程序使用 Process
启动子应用程序,其中 RedirectStandardInput = true
。所以父进程可以使用 childProc.StandardInput.WriteLine()
向子进程发送命令。我使用通过 Console.OpenStandardInput()
获取的流的 BeginRead()
和 EndRead()
异步捕获这些消息。亲子沟通效果很好。我能够异步发送和接收消息。
但是,当子项尝试使用相同的代码写入父项时,.NET 会抛出此错误:
StandardInput has not been redirected.
所以,简单来说,.NET 应用程序如何重定向它自己的标准输入流?然后我将重定向我父进程的标准输入流,所以子进程可以向它发送消息。
我的父进程是使用 .NET 4.0 x86 构建的 WinForms C# 应用程序。
编辑:这是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();
}
}
}
这里是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);
}
}
}
在父进程中:
// 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();
在子进程中:
ownerProcess = ....
Server = new IPCServer();
Server.OnCmdRecieved = GotCmd;
Server.Init();
Client = new IPCClient();
Client.Init(ownerProcess);
你可以用更方便的方式来做。只需让您的客户端应用程序对输入\输出重定向一无所知。 服务器应该关心重定向。
我已经使用您的技术实现了一个最简单的客户端-服务器应用程序,它演示了应该如何使用它。
客户
客户端是最简单的应用程序,当您输入 exit
:
static void Main(string[] args)
{
string str;
do
{
str = Console.ReadLine();
Console.WriteLine("Executed: " + str);
} while (str != "exit");
}
客户端对重定向一无所知,它只是像控制台应用程序一样工作,并在控制台中读取\写入。
服务器
服务器运行客户端进程并在其流中读取\写入。
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();
执行此代码后,res 包含以下文本:
Executed: a
Executed: b
Executed: c
Executed: d
Executed: exit
如果子进程仅在子进程的 StandardOutput 流上使用 BeginRead()
和 EndRead()
会怎样?那应该有用!