【问题标题】:How to WriteConsoleInput to the a child app waiting at ReadConsoleInput?如何向在 ReadConsoleInput 等待的子应用程序写入控制台输入?
【发布时间】:2013-07-11 05:29:36
【问题描述】:

所以我一直在尝试从 Pianobar(控制台 Pandora 播放器)STDIN 和 STDOUT 读取和写入,以从另一个应用程序中控制它。

但是,对于某些从 STDOUT 读取时,它会完全阻塞在最后一行(显示歌曲时间的位置)。

我以为我做错了什么(可能仍然是),但我下载了演示项目,用于通过几个句柄向另一个应用程序 STDIN/STDOUT 发送/接收输入。

所以我深入研究了 Pianobar 代码,并在所有地方都输入了 printf 命令以跟踪块发生的位置(块是正确的词吗?)无论如何,我终于得到了一段似乎循环的代码作为子进程创建时速度极快,并且还会阻止 STDOUT。

来自 Pianobar,ui_readline.c BarReadline 替换

/*  readline replacement
 *  @param buffer
 *  @param buffer size
 *  @param accept these characters
 *  @param input fds
 *  @param flags
 *  @param timeout (seconds) or -1 (no timeout)
 *  @return number of bytes read from stdin
 */
size_t BarReadline (char *buf, const size_t bufSize, const char *mask,
        BarReadlineFds_t *input, const BarReadlineFlags_t flags, int timeout)
{
// took out some extra code from here ...
printf("In BarReadline 005\n");
fflush(stdout);
while (true) {
    Sleep(400); // added this to stop it from doing 100% on a core
    printf("In BarReadline 006\n");
    fflush(stdout);
    if (timeout != INFINITE) {
        DWORD now = GetTickCount ();
        printf("In BarReadline 007\n");
        fflush(stdout);
        if ((int)(now - timeStamp) < timeout) {
            timeout -= (int)(now - timeStamp);
            timeStamp = now;
        }
        else
            timeout = 150; // KYLE changed from 0
    }
    printf("Current timeout: %d\n",timeout);
    printf("In BarReadline 008\n");
    fflush(stdout);
    waitResult = WaitForSingleObject (handle, timeout);

    printf("In BarReadline 009\n");
    fflush(stdout);
    if (WAIT_OBJECT_0 == waitResult) {
        INPUT_RECORD inputRecords[8];
        INPUT_RECORD* record;
        DWORD recordsRead, i;

        printf("In BarReadline 010\n");
        fflush(stdout);
        successConsole = ReadConsoleInput (handle, inputRecords, sizeof(inputRecords) / sizeof(*inputRecords), &recordsRead);
        if(successConsole != 0) {
            printf("We read from console\n");
        }

        printf("In BarReadline 011\n");
        fflush(stdout);
        for (i = 0, record = inputRecords; i < recordsRead; ++i, ++record) {
            int codePoint, keyCode;

            printf("In BarReadline 012\n");
            fflush(stdout);

上面的代码打印出来了:

In BarReadLine 005
In BarReadline 006
In BarReadline 007
Current timeout: 150
In BarReadline 008
In BarReadline 009
In BarReadline 010
In BarReadline 011
In BarReadline 006
In BarReadline 007
Current timeout: 150
In BarReadline 008
In BarReadline 009
In BarReadline 010
In BarReadline 011 

无论如何,我可以在重定向演示应用程序上使用一个不需要任何特殊的已知键来敲击“输入”键,它只是在该循环中不断旋转并且似乎没有捕捉到它,这对我来说听起来喜欢两件事之一;我们无法访问 INPUT 函数,因为它被 STDOUT 的读取阻止,或者 ReadConsoleInput 无法识别我们从 Redirect Demo 发送的内容。

这是我需要通过某种类型的异步 I/O 进程发送的东西吗?为什么使用“cmd”并打开常规命令提示符不会导致阻塞,但这样做呢?

更新 1: 我设法构建了一个 INPUT_RECORD 以发送到 Pianobar(子控制台)内的 ReadConsoleInput。但是,我发现当我尝试发送 WriteConsoleInput(m_hStdinWrite, inputRecords, sizeof(inputRecords) / sizeof(*inputRecords), &amp;dwWritten);

时,我的父应用程序正在返回“无效句柄”

儿童控制台 STDIN 是否有不同类型的句柄?使用 WriteFile 有效,但我无法以这种方式发送 INPUT_RECORD。

Redirect Demo App

Pianobar Windows Binaries

Pianobar Windows Build Environment

已帮助,但不确定导致无效句柄的原因: Low Level Console Input and Redirection

【问题讨论】:

    标签: c++ c winapi stdio


    【解决方案1】:

    我相信这是因为程序使用的是 ReadConsoleInput 而不是 ReadFile。 ReadConsoleInput 需要控制台句柄。

    您需要创建一个控制台并传递它的句柄。然后您需要将控制台输入事件写入其中。

    如果你能把其他程序改成只使用 ReadFile 会更好,如果你能做到的话。

    This seems to be the MSDN reference for consoles.

    【讨论】:

    • 好吧,Pianobar 是开源的,我一直在构建它......即使它只是一个概念证明,可能会让我在这个过程中更进一步。
    猜你喜欢
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 2011-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-13
    相关资源
    最近更新 更多