python-process.communicate和getche()失败

我正在尝试自动执行用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().如果您真的想让它对击键做出反应而不需要用户按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();
    }
}
上一篇:Python可执行文件到Linux列出具有大小的文件


下一篇:python-如何在子流程模块内的列表中使用索引?