我有一个启动命令行应用程序并完成一些工作。在此期间,它会听取击键(s => show status)。这不是典型的命令提示符,您按下's'和< ENTER> - 按下按键后立即响应的类型显示状态。
现在,我正试图通过发送击键来从一个奇特的GUI应用程序“控制”该命令行应用程序。我已经尝试过更传统的方法来编写Process的StandardInput,但这似乎根本没有效果。此外,因为实际进程没有窗口(它以CreateNoWindow = true开头),我无法尝试使用Win32 API向窗口发送击键。
还有其他办法吗?
答案 0 :(得分:2)
花哨的控制台应用程序存在问题。
他们倾向于直接读取键盘输入,而不是通过stdin。他们也倾向于直接控制他们的控制台,而不是通过stdout。
AFAIK,无法以编程方式控制这些应用。如果你真的,真的需要,我会探索AutoHotKey
控制私有desktop上的应用程序(AHK使用虚拟键盘/鼠标驱动程序)。不过,我不确定如何从控制台读取结果; 可能可以创建一个由您的程序启动的中间控制台应用程序(在私有桌面中)并启动目标应用程序。然后,中间应用会share its console使用目标应用,并使用low-level I/O来检测更改。
或者您可以使用Detours根据您的意愿弯曲目标应用。
答案 1 :(得分:1)
好吧,我似乎找到了自己问题的答案。 这是一个真正的“混合在一起”的解决方案,但它的工作原理 - 对于我正在构建的应用程序的所有意图和目的,它并不重要。
所以,我所做的是使用两个名为
的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);
现在,这是一个真正的kludge工作,但它完成了工作。一个潜在的缺陷是,如果用户正在使用计算机进行其他操作,并且当窗口处于活动状态时使用'q'将在10000000时刻确定1 - 它将退出工作程序。但该应用程序旨在用于专用机器上,这些机器甚至不会连接监视器,键盘或鼠标,因此不会出现问题。
感谢所有回答的人,不管你做了什么 - 以这样或那样的方式,引导我走向正确的解决方案。
答案 2 :(得分:1)
我找到了一种更好的方法来实现功能,而没有引起同时用户输入和窗口切换问题的理论风险。
诀窍是使用名为PostMessage的WinAPI函数将KeyDown(或KeyUp)消息发送到执行相同操作的进程。无需将过程窗口置于前面并立即隐藏它!
我正在发送带有键'S'作为参数的按键命令:
// 0x0100 - VM_KEYDOWN
// 0x0101 - VM_KEYUP
// 0x53 - S-key
PostMessage(workerProcess.MainWindowHandle, 0x0100, 0x53, 0);
PostMessage(workerProcess.MainWindowHandle, 0x0101, 0x53, 0);