C# 获取 运行 的标准 input/output/error,不是子进程
C# Get standard input/output/error of running, NOT child process
我的问题很简单:如何获得我未启动的进程的标准 output/input/error?假设我有一些程序(不是我的)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,我需要重新启动后能够"reattach"。
我看到了一些使用 Get/SetStdHandle 的建议,但大多数都声称不起作用,而且我也不太明白如何应用它们。
感谢任何建议!
It is worth noting that (if it helps) I can start XYZ myself (with those redirection parameters). It's just that my lifecycle needs to be completely independent of XYZ, and I need to be able to "reattach" after I relaunch.
这是我在评论中建议的一个简单实现(通过中间过程发布数据)。
样本基本上由3个主要部分组成
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);
}
}
}
}
我的问题很简单:如何获得我未启动的进程的标准 output/input/error?假设我有一些程序(不是我的)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,我需要重新启动后能够"reattach"。
我看到了一些使用 Get/SetStdHandle 的建议,但大多数都声称不起作用,而且我也不太明白如何应用它们。
感谢任何建议!
It is worth noting that (if it helps) I can start XYZ myself (with those redirection parameters). It's just that my lifecycle needs to be completely independent of XYZ, and I need to be able to "reattach" after I relaunch.
这是我在评论中建议的一个简单实现(通过中间过程发布数据)。
样本基本上由3个主要部分组成
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);
}
}
}
}