向无窗口命令行进程发送命令(从C#应用程序启动)

向无窗口命令行进程发送命令(从C#应用程序启动),c#,command-line,C#,Command Line,我有一个命令行应用程序,可以启动并执行一些工作。在此期间,它会侦听击键(s=>showstatus)。它不是典型的命令提示符,你按下“s”键,它是一种一旦按下键就会做出反应的类型,状态就会显示出来 现在,我正试图通过发送击键,从一个奇特的GUI应用程序“控制”该命令行应用程序。我尝试了更为传统的方法来编写流程的标准输入,但这似乎根本没有效果。另外,由于实际进程没有窗口(它是以CreateNoWindow=true启动的),我无法尝试使用Win32 API向窗口发送击键 还有其他方法吗?奇特的控制

我有一个命令行应用程序,可以启动并执行一些工作。在此期间,它会侦听击键(s=>showstatus)。它不是典型的命令提示符,你按下“s”键,它是一种一旦按下键就会做出反应的类型,状态就会显示出来

现在,我正试图通过发送击键,从一个奇特的GUI应用程序“控制”该命令行应用程序。我尝试了更为传统的方法来编写流程的标准输入,但这似乎根本没有效果。另外,由于实际进程没有窗口(它是以CreateNoWindow=true启动的),我无法尝试使用Win32 API向窗口发送击键


还有其他方法吗?

奇特的控制台应用程序存在问题

他们倾向于直接读取键盘输入,而不是通过标准输入。他们也倾向于直接控制他们的控制台,而不是通过stdout

抱歉,没有办法通过编程控制这些应用程序。如果你真的,真的需要,我会探索一些类似于在私人电脑上控制应用程序的东西(AHK使用虚拟键盘/鼠标驱动程序)。不过,我不确定你会如何从控制台上读取结果;可以创建一个中间控制台应用程序,该应用程序由您的程序(在专用桌面中)启动并启动目标应用程序。然后,中间应用程序将与目标应用程序一起使用以检测更改


或者,你可以根据自己的意愿调整目标应用程序。

嗯,我似乎已经找到了我自己问题的答案。 这是一个真正的“拼凑在一起”的解决方案,但它是有效的——对于我正在构建的应用程序的所有意图和目的来说,这并不重要


所以,我使用了两个WinAPI函数

static extern bool ShowWindow(IntPtr WindowHandle, int nCmdShow);
static extern bool SetForegroundWindow(IntPtr WindowHandle);
第一个可以通过将nCmdShow分别更改为1和0来显示/隐藏窗口。另一个将窗口(由WindowHandle确定)放在前面。将这两者结合在一起,我可以通过编程将控制台窗口提前,执行一个简单的SendKeys.Send();操作,然后再次隐藏它

// Use a WIN API command to bring the command line to front
SetForegroundWindow(workerProcess.MainWindowHandle);
// Send a keystore to re-display the STATUS of the worker
SendKeys.Send("s");
// Hide the window again.
ShowWindow(workerProcess.MainWindowHandle, 0); 
现在,这真是一项艰难的工作,但它完成了任务。一个潜在的陷阱是,如果用户正在使用计算机做其他事情,当窗口以“q”激活时,会在10000000分钟内锁定1,这将退出worker程序。但该应用程序打算在专用机器上使用,这些机器很可能连显示器、键盘或鼠标都没有,所以不会有问题


感谢所有回答的人,因为你这样做了——以这样或那样的方式,引导我走向正确的解决方案。

我找到了一种更好的方法来实现功能,而不会在理论上带来同时用户输入和窗口切换问题的风险


诀窍是使用名为PostMessage的WinAPI函数向执行相同操作的进程发送up KeyDown(或KeyUp)消息。无需将进程窗口放在前面,然后立即隐藏它

我正在发送键“S”作为参数的键向下命令:

        // 0x0100 - VM_KEYDOWN
        // 0x0101 - VM_KEYUP
        // 0x53 - S-key
        PostMessage(workerProcess.MainWindowHandle, 0x0100, 0x53, 0);
        PostMessage(workerProcess.MainWindowHandle, 0x0101, 0x53, 0);

命令行应用程序是您编写的吗(或者至少有源代码)?如果是这样的话,我会将你想要重用的部分重构到一个单独的库中,GUI和命令行工具都使用这个库。你确保在使用流程的StandardInput时刷新流了吗?@JonSkeet:Heh,如果我有足够的源代码,我不会问这样的问题:P我会改变应用程序使其工作得更好。是的,我确实通过调用FLUSH()命令刷新了流。没有帮助。您可以创建带有隐藏窗口(wShowWindow=SW_HIDE)的控制台应用程序,然后向其发送按键吗?谢谢您的回答。事实上,我可以很容易地阅读。只发送输入似乎是个问题。我会检查这两件事,看看是否有任何一件有效。编辑:非常奇怪的是,发送击键(就像是在键盘上键入的一样)并不像向标准输入那样标准。实际上,这是一场军备竞赛。一方面是那些真正想从真正的键盘上阅读的应用程序,另一方面是那些真正想伪造这些应用程序的应用程序
WM_KEYUP
/
WM_KEYDOWN
keybd_事件
SendInput
SendKeys
),等等。我曾经签约编写一个虚拟键盘驱动程序,因为有一个程序拒绝虚拟化。在军备竞赛中,虚拟化总是获胜在使用TPM之前:(PostMessage?它来自哪里?WinAPI函数