C#-C进程间通信
好的,我有一个用c语言编写的程序,它启动一个运行另一个程序的进程,这个程序是用c语言编写的。现在我已经解决了从c语言程序重定向stdout并从c语言端获取它的问题,效果非常好。但是我需要一种方法让C程序告诉C程序结束。我的第一个想法是,由于C程序最初是通过测试conio.h中的kbhit来控制的,所以我可以重定向stdin并流写一些东西,它会检测到一个键命中,但这不起作用(我猜kbhit不适合重定向),所以我四处搜索,很多人一直在建议PeekConsoleInput(),因为我专门为windows(实际上是一台特定的机器)编写这个程序。所以我将c程序改为使用PeekConsoleInput而不是kbhit,并重定向了stdin,它仍然没有检测到我发送给它的任何内容。例如在CC#-C进程间通信,c#,c,interprocess,C#,C,Interprocess,好的,我有一个用c语言编写的程序,它启动一个运行另一个程序的进程,这个程序是用c语言编写的。现在我已经解决了从c语言程序重定向stdout并从c语言端获取它的问题,效果非常好。但是我需要一种方法让C程序告诉C程序结束。我的第一个想法是,由于C程序最初是通过测试conio.h中的kbhit来控制的,所以我可以重定向stdin并流写一些东西,它会检测到一个键命中,但这不起作用(我猜kbhit不适合重定向),所以我四处搜索,很多人一直在建议PeekConsoleInput(),因为我专门为window
#include <stdio.h>
#include <windows.h>
int main() {
BOOL peeked = 0;
HANDLE input_handle = GetStdHandle(STD_INPUT_HANDLE);
DWORD events = 0; // how many events took place
INPUT_RECORD input_record; // a record of input events
DWORD input_size = 1; // how many characters to read
printf("Hello World\n");
fflush(stdout);
while (1) {
FlushConsoleInputBuffer(input_handle);
peeked = PeekConsoleInput(input_handle, &input_record, input_size, &events);
if (peeked && events>0) {
break;
}
}
printf("Hit Detected\n");
return 0;
}
C程序自行执行,但当C#程序运行它时,它永远不会达到“命中检测”。我还将s.WriteLine(“Q”)延迟了几秒钟,看看这是否是一个时间问题,它仍然不起作用
理想情况下,我希望C程序能够自己运行,或者由C#程序运行,但即使你不能自己运行C程序,也不会那么糟糕
我尝试过的一件事是,让C#程序只写一个文件,让C程序用fopen的轮询,直到它成功打开它,但这个C程序的主要目的之一是非常快地将数据写入磁盘,我担心轮询磁盘可能会减慢速度
另一件有点奏效的事情是关闭流程。但这很麻烦,因为C程序需要在关闭前清理一些东西(除非有某种方法让C程序在关闭前执行一些代码,但我不确定你是否能做到)
其他方法可以通过插座、管道等来完成,但仅仅一个一位的信号就需要做很多工作。而且,我能找到的所有关于如何做到这一点的例子似乎都是如何让两个C#程序进行通信,或者如何让两个C程序进行通信,而不是用两种不同的语言编写两个不同的程序
那么,首先,有没有办法让这个stdin重定向工作?如果没有,告诉C进程它需要退出的最简单的解决方案是什么?您是否尝试过看看C程序是否以及在多大程度上写文件更快 还有其他方法(在Windows中)进行进程间通信
就TCP/IP而言,它不局限于使用相同的语言和工具进行软件构建。您的C程序将是TCP服务器,您的C#程序将是TCP客户端。如果你知道如何用这两种语言中的任何一种做这件事,你就会得到你的答案。我遇到了同样的问题,并且能够使用它来工作。如果您有WPF应用程序,只需添加对
System.Windows.Forms
的引用即可
对于我使用的流程StartInfo
newProcess.StartInfo.UserShellExecute = false;
newProcess.StartInfo.CreateNoWindow = false;
newProcess.StartInfo.RedirectStandardInput = false;
newProcess.StartInfo.RedirectStandardOutput = true;
newProcess.StartInfo.RedirectStatndardError = true;
newProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
newProcess.OutputDataReceived += new DataReceivedHandler(gotData);
将createnowindow
设置为false的原因是您可以在Spy++中找到该窗口ProcessWindowStyle.Hidden
在窗口弹出一小会儿后隐藏窗口
RedirectStatndardInput
必须为false,因为我们正在使用SendKeys模拟键盘输入到隐藏窗口
使用SendKeys.waitSend(“命令{ENTER}”)代码>我能够向控制台应用程序发送命令,该应用程序使用
\u kbhit()
和getc()
进行输入 您可以使用Process对象终止生成的进程:
(假设C程序在收到“CloseMainWindow()”信号后有一个处理程序来进行清理)
//
///关闭脱壳过程(如果有)
///
///为什么要关门?
公共静态无效外壳终止(字符串原因)
{
过程p=有壳过程;
尝试
{
if(p==null)
{
o3(原因+”。无脱壳过程。”);
}
否则,如果(p.已退出)
{
o3(原因+”。进程已退出。“);
}
其他的
{
//进程仍在运行。
//测试进程是否挂起。
如果(第页)
{
//进程正在响应;请关闭主窗口。
o3(原因+”。进程正在优雅地关闭。”);
如果(p.CloseMainWindow())
{
//进程没有响应;请强制关闭进程。
o3(原因+“。进程正在被终止。”);
p、 杀死();
p、 Close();
p=零;
}
}
如果(p!=null)
{
//进程没有响应;请强制关闭进程。
o3(原因+“。进程正在被终止。”);
p、 杀死();
}
p、 Close();
}
if(shellOut!=null)
{
shellOut.Close();
shellOut=null;
}
shelledProcess=null;
}
捕获(例外情况除外)
{
o(“shellTerminate中的异常:“+ex.Message”);
}
}
当C程序等待结束时,它在做什么?它正在处理数据吗?C程序通过USB从外部设备收集数据,将数据写入磁盘,向stdout写入它传输了多少数据,并检查它是否应该停止。除了(最初)检查kbhit,看看它是否应该停止,它对stdin没有任何作用。我应该提到的是,我已经找到了一个解决方法。我添加了一个命令行参数,指定
newProcess.StartInfo.UserShellExecute = false;
newProcess.StartInfo.CreateNoWindow = false;
newProcess.StartInfo.RedirectStandardInput = false;
newProcess.StartInfo.RedirectStandardOutput = true;
newProcess.StartInfo.RedirectStatndardError = true;
newProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
newProcess.OutputDataReceived += new DataReceivedHandler(gotData);
/// <summary>
/// Close the shelled process, if there is any
/// </summary>
/// <param name="reason">why closing?</param>
public static void shellTerminate(string reason)
{
Process p = shelledProcess;
try
{
if (p == null)
{
o3(reason + ". No shelled process.");
}
else if (p.HasExited)
{
o3(reason + ". Process has exited already.");
}
else
{
//Process is still running.
//Test to see if the process is hung up.
if (p.Responding)
{
//Process was responding; close the main window.
o3(reason + ". Process is being closed gracefully.");
if (p.CloseMainWindow())
{
//Process was not responding; force the process to close.
o3(reason + ". Process is being killed.");
p.Kill();
p.Close();
p = null;
}
}
if (p != null)
{
//Process was not responding; force the process to close.
o3(reason + ". Process is being killed.");
p.Kill();
}
p.Close();
}
if (shellOut != null)
{
shellOut.Close();
shellOut = null;
}
shelledProcess = null;
}
catch (Exception ex)
{
o("Exception in shellTerminate: " + ex.Message);
}
}