首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >process.communicate和getche()失败

process.communicate和getche()失败
EN

Stack Overflow用户
提问于 2011-11-14 03:41:07
回答 2查看 663关注 0票数 4

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

当启动时,二进制文件等待字母S、Q或P(状态、退出或暂停)。它使用一个非标准的msvcrt函数"getche“来获取键笔画(例如,get()),而不需要用户点击enter。

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

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

代码语言:javascript
复制
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"

这是两个双星。这是我能与之沟通的第一个:

代码语言:javascript
复制
#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;
}

这个我无法与之沟通:

代码语言:javascript
复制
#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上监听,可能会侦听某种键盘事件。有人知道怎么处理这事吗?

编辑:我还应该提到我发现了使用should捕获输入的方法。我没有编写我试图自动化的原始二进制文件。它是一个封闭的源代码工具,所以我没有办法重写它如何接受输入而不修补二进制文件。

我真的选择了一个很疯狂的解决方案。我非常了解pydbg,并且似乎附加到流程并通过流程工具调用我所需要的函数是有效的。这完全是过火,但我可以脱离这个过程之后。让它正常运行。

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

EN

回答 2

Stack Overflow用户

发布于 2011-11-14 05:06:52

如果您可以修改被调用程序的行为,则的回答是一种明智的方法。否则,如果确实需要写入控制台输入缓冲区,请尝试PyWin32 32的win32console模块。尽管如此,我不知道如何使字符回显部分正常工作时,stdout是管道。它最终打印到线的开始。

C:

代码语言:javascript
复制
#include <stdio.h>

int main(int argc, char *argv[]) {
    int response;
    printf("Enter \"a\": ");
    response = getche();
    printf("\nYou entered \"%c\" ", response);
    return 0;
}

/* gcc test_getch.c -o test_getch.exe */

Python:

代码语言:javascript
复制
import subprocess
import win32console

def make_buf(c):
    buf = win32console.PyINPUT_RECORDType(win32console.KEY_EVENT)
    buf.KeyDown = 1
    buf.RepeatCount = 1
    buf.Char = c
    return buf

con_in = win32console.GetStdHandle(win32console.STD_INPUT_HANDLE)

cmd = ["test_getch.exe"]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE)

buf = make_buf('a')
con_in.WriteConsoleInput([buf])
票数 3
EN

Stack Overflow用户

发布于 2011-11-14 04:04:40

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

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

我建议您只重写程序,使其只从标准输入中读取,而不是使用getche()。如果您真的想让它在不要求用户按Enter的情况下对击键作出反应,那么我建议让它根据标准输入是否来自终端而改变其行为。如果是,使用getche,如果不是,只需直接从stdin读取即可。您可以使用_isatty (或者POSIX -等效的isatty;出于某种原因,微软已经决定在运行时取消POSIX名称)来测试它。例如:

代码语言:javascript
复制
int ReadChar()
{
    if(_isatty(0))
    {
        // stdin is a terminal
        return _getche();
    }
    else
    {
        // stdin is not a terminal
        return getchar();
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8117055

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档