好的,所以我有一个用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#代码的片段......
ProcessStartInfo info = new ProcessStartInfo("CTest.exe");
info.CreateNoWindow = true;
info.UseShellExecute = false;
info.RedirectStandardOutput = true;
info.RedirectStandardInput = true;
pro = new Process();
pro.StartInfo = info;
pro.Start();
StreamWriter sw = pro.StandardInput;
sw.AutoFlush = true;
pro.BeginOutputReadLine();
pro.OutputDataReceived += new DataReceivedEventHandler(pro_OutputDataReceived);
sw.WriteLine("Q");
C程序自行执行,但是当C#程序运行它时,它永远不会达到“Hit Detected”。我还将s.WriteLine(“Q”)延迟了几秒钟以查看它是否是一个计时问题而且仍然无效。
理想情况下,我希望C程序能够自行运行,或者由C#程序运行,但即使你不能自己运行C程序,也不会那么糟糕。
我尝试过的一件事就是让C#程序只写一个文件,让C程序只用fopen进行轮询直到它成功打开它,但这个C程序的主要目的之一就是写入数据到磁盘真的很快,我担心轮询磁盘可能会减慢速度。
另一件有用的事情就是关闭这个过程。但这很麻烦,因为C程序需要在关闭之前清理一些东西(除非有一些方法让C程序在关闭之前执行一些代码,但我不确定你是否可以这样做。)
完成这项工作的其他方法是套接字,管道等,但对于一位信号来说似乎需要做很多工作。此外,我可以找到关于如何做到这一切的所有例子似乎都是如何让两个C#程序进行通信或如何让两个C程序进行通信,而不是两种不同语言的两个不同程序。
所以,首先,有没有办法让这个stdin重定向工作正常?如果没有,告诉C进程需要退出的最简单的解决方案是什么?
答案 0 :(得分:1)
我遇到了同样的问题,并且能够使用SendKeys让它工作。如果您有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);
将CreatNoWindow
设置为false的原因是您可以在Spy ++中找到Window。弹出窗口后,ProcessWindowStyle.Hidden
会隐藏窗口。
RedirectStatndardInput
必须为false,因为我们使用SendKeys来模拟隐藏窗口的键盘输入。
使用SendKeys.waitSend("command{ENTER}");
我能够向使用_kbhit()
和getc()
输入的控制台应用发送命令。
答案 1 :(得分:0)
您是否尝试过查看C程序在编写文件时是否更快?
还有其他方法(在Windows中)进行进程间通信。
就TCP / IP而言,它不限于使用相同的语言和工具进行软件构建。您的C程序将是TCP服务器,您的C#程序将是TCP客户端。如果你知道如何用你能得到答案的任何一种语言来做这件事。
答案 2 :(得分:0)
您可以使用Process对象来终止衍生进程: (假设C程序在收到“CloseMainWindow()”信号后有一个处理程序来进行清理)
/// <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);
}
}