C#-C进程间通信

C#-C进程间通信,c#,c,interprocess,C#,C,Interprocess,好的,我有一个用c语言编写的程序,它启动一个运行另一个程序的进程,这个程序是用c语言编写的。现在我已经解决了从c语言程序重定向stdout并从c语言端获取它的问题,效果非常好。但是我需要一种方法让C程序告诉C程序结束。我的第一个想法是,由于C程序最初是通过测试conio.h中的kbhit来控制的,所以我可以重定向stdin并流写一些东西,它会检测到一个键命中,但这不起作用(我猜kbhit不适合重定向),所以我四处搜索,很多人一直在建议PeekConsoleInput(),因为我专门为window

好的,我有一个用c语言编写的程序,它启动一个运行另一个程序的进程,这个程序是用c语言编写的。现在我已经解决了从c语言程序重定向stdout并从c语言端获取它的问题,效果非常好。但是我需要一种方法让C程序告诉C程序结束。我的第一个想法是,由于C程序最初是通过测试conio.h中的kbhit来控制的,所以我可以重定向stdin并流写一些东西,它会检测到一个键命中,但这不起作用(我猜kbhit不适合重定向),所以我四处搜索,很多人一直在建议PeekConsoleInput(),因为我专门为windows(实际上是一台特定的机器)编写这个程序。所以我将c程序改为使用PeekConsoleInput而不是kbhit,并重定向了stdin,它仍然没有检测到我发送给它的任何内容。例如在C

#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)
  • 内存映射文件(这里可能是一个不错的选择-类似于 (其他有效的实验)
  • TCP/IP(如您所建议的)

  • 就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);
        }
    }