我试图自动执行以C++编写的交互式命令行工具。

启动后,二进制文件将等待字母S,Q或P(状态,退出或暂停)。它使用非标准的msvcrt函数“getche”来获取击键(例如,代替gets()),而无需用户按下Enter键。

我尝试以标准方式与进程进行通信(写入stdin并使用process.communicate []),但没有得到输入。经过几个小时的尝试,我在Visual Studio中创建了两个小示例项目来复制问题并确保我理智。

这是用于调用二进制文件的python脚本:

import subprocess
import time

cmd = ["test-getch.exe"]
process = subprocess.Popen(cmd, stderr = subprocess.PIPE, stdin = subprocess.PIPE, stdout = subprocess.PIPE)
i = process.stdin
#msvcrt.ungetch('s')
i.write("S\n")
print process.communicate()[0]
i.close()
time.sleep(3)
print "DONE"

这是两个二进制文件。我可以与之交流的第一个人:
#include "stdafx.h"
#include <conio.h>


int _tmain(int argc, _TCHAR* argv[])
{
    char response [2];
    printf("Enter \"s\":\n");
    gets(response);
    printf("You entered %s", response);
    return 0;
}

我无法与这个人交流:
#include "stdafx.h"
#include <conio.h>


int _tmain(int argc, _TCHAR* argv[])
{
    int response;
    printf("Enter \"a\":\n");
    response = getche();
    printf("You entered %c", response);
    return 0;
}

看来getche()不会在stdin上监听,并且可能在监听某种键盘事件。有人知道如何处理吗?

编辑:
我还应该提到我发现了使用IDA Pro捕获输入的方法。我没有编写要自动执行的原始二进制文件。这是一个封闭的源代码工具,因此我无法在不修补二进制文件的情况下重新编写它如何接受输入。

实际上,我已经选择了一个相当疯狂的解决方案,它可以工作...我对pydbg非常了解,而且似乎可以附加到流程并通过流程检测调用所需的函数。这完全是多余的,但是我以后可以脱离这个过程。并使其正常运行。

[1] Pydbg:http://pedram.redhive.com/PyDbg/docs/

最佳答案

getche从控制台读取,而不是从标准输入读取。如果您的Python进程正在控制台窗口中运行,那么您的子进程仍会尝试从同一控制台读取输入,而不是从作为标准输入传递的管道中读取输入。

可能可以创建另一个不可见的控制台窗口,将其附加到子进程中,并提供输入,但这非常复杂并且容易出错。

我建议改写您的程序以仅从标准输入读取,而不要使用getche()。如果您真的想让它对击键使用react而不需要用户按下Enter键,那么我建议让它根据标准输入是否来自终端来更改其行为。如果是,请使用getche,否则请直接从stdin读取。您可以使用 _isatty (或POSIX等效的isatty;由于某种原因,Microsoft已决定在其运行时中弃用POSIX名称)进行测试。例如:

int ReadChar()
{
    if(_isatty(0))
    {
        // stdin is a terminal
        return _getche();
    }
    else
    {
        // stdin is not a terminal
        return getchar();
    }
}

10-02 02:04