0

所以我一直在尝试从 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 无法识别我们从重定向演示发送的内容。

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

更新 1:我设法构建了一个 INPUT_RECORD 以发送到 Pianobar(子控制台)内的 ReadConsoleInput。但是,我发现我的父应用程序在我尝试发送时返回“无效句柄”WriteConsoleInput(m_hStdinWrite, inputRecords, sizeof(inputRecords) / sizeof(*inputRecords), &dwWritten);

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

重定向演示应用

Pianobar Windows 二进制文件

Pianobar Windows 构建环境

帮助,但不确定导致无效句柄的原因: 低级控制台输入和重定向

4

1 回答 1

1

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

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

如果您可以将其他程序更改为仅使用 ReadFile 会更好,如果您可以做到的话。

这似乎是控制台的 MSDN 参考。

于 2013-07-11T05:51:55.437 回答