WinAPI C ++客户端在读取之前检测到匿名管道上的写入 [英] WinAPI C++ client detect write on anonymous pipe before reading

查看:182
本文介绍了WinAPI C ++客户端在读取之前检测到匿名管道上的写入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个C ++(Windows)客户端控制台应用程序,该应用程序从STDIN上的匿名管道读取.我希望能够按如下方式使用我的程序:

I am writing a C++ (Windows) client console application which reads from an anonymous pipe on STDIN. I would like to be able to use my program as follows:

echo input text here | my_app.exe

,然后使用输入的文本在应用程序中执行

and do something in the app with the text that is piped in

OR

my_app.exe

,然后在应用程序内部使用一些默认文本,而不是管道中的输入.

and then use some default text inside of the app instead of the input from the pipe.

在第一种情况下,我目前拥有从STDIN上的管道成功读取的代码:

I currently have code that successfully reads from the pipe on STDIN given the first situation:

#include <Windows.h>
#include <iostream>
#include <string>

#define BUFSIZE 4096

int main(int argc, const char *argv[]) {
    char char_buffer[BUFSIZE]; 
    DWORD bytes_read;
    HANDLE stdin_handle;
    BOOL continue_reading;
    unsigned int required_size;
    bool read_successful = true;

    stdin_handle = GetStdHandle(STD_INPUT_HANDLE);

    if (stdin_handle == INVALID_HANDLE_VALUE) {
        std::cout << "Error: invalid handle value!\n\n";
    } else {
        continue_reading = true;

        while (continue_reading) { 
            continue_reading = ReadFile(stdin_handle, char_buffer, BUFSIZE,
                &bytes_read, NULL); 

            if (continue_reading) {
                if (bytes_read != 0) {
                    // Output what we have read so far
                    for (unsigned int i = 0; i < bytes_read; i++) {
                        std::cout << char_buffer[i];
                    }
                } else {
                    continue_reading = false;
                }
            }
        }
    }

    return 0;
}

我知道匿名管道的唯一选择是使用ReadFile进行阻止读取.如果我理解正确,关于我如何调用它,ReadFile将继续从STDIN上的缓冲区读取,直到它检测到管道另一端的写操作结束为止(也许读取某种写结束").令牌?).我想知道是否存在某种开始写入"令牌,如果正在管道传输某些内容,我可以在其中检查STDIN 之前,我将其称为ReadFile.如果是这种情况,我可以跳过调用ReadFile并使用一些默认文本的方法.

I know that my only option with anonymous pipes is to do a blocking read with ReadFile. If I understand correctly, in regard to how I am invoking it, ReadFile will continue to read from the buffer on STDIN until it detects an end of write operation on the other end of the pipe (perhapse reads some sort of "end of write" token??). I would like to know if there is some sort of "beginning write" token that will be in the buffer if something is being piped in which I can check on STDIN BEFORE I call ReadFile. If this were the case I could just skip calling ReadFile and use some default text.

如果没有办法,我总是可以传入一个命令行参数,该参数表示我不应该检查管道,而只是使用默认文本(或者相反),但是我更喜欢按照我指定的方式进行操作.

If there is not a way to do this, I can always pass in a command line argument that denotes that I should not check the pipe and just use the default text (or the other way around), but I would much prefer to do it the way that I specified.

推荐答案

您似乎真正要在此处执行的操作是确定是否具有控制台输入(使用默认值)与管道输入(您在哪里使用管道输入).

It looks like what you're really trying to do here is to determine whether you've got console input (where you use default value) vs pipe input (where you use input from the pipe).

建议直接测试而不是尝试检查是否已准备好输入:尝试嗅探管道中是否存在数据的问题是,如果源应用程序生成输出的速度很慢,则您的应用程序可能会做出错误的假设,仅仅是因为还没有可用的输入 . (由于提前输入,用户输入的字符可能已经准备好从控制台STDIN读取,然后您的应用程序才能检查输入是否可用.)

Suggest testing that directly instead of trying to check if there's input ready: the catch with trying to sniff whether there's data in the pipe is that if the source app is slow in generating output, your app might make an incorrect assumption just because there isn't input yet available. (It might also be possible that, due to typeahead, there's a user could have typed in characters that area ready to be read from console STDIN before your app gets around to checking if input is available.)

此外,请记住,允许您的应用与文件重定向一起使用,而不仅仅是管道,这可能很有用-例如:

Also, keep in mind that it might be useful to allow your app to be used with file redirection, not just pipes - eg:

myapp.exe < some_input_file

在unix上进行交互模式与重定向输入对比"测试的经典方法是使用isatty();.幸运的是,Windows CRT中有一个等效项-请参见函数_isatty() ;或使用 GetFileType()在GetStdHandle(STD_INPUT_HANDLE)上检查FILE_TYPE_CHAR-或像Remy一样使用说GetConsoleMode,只有在真正的控制台手柄上才能成功.

The classic way to do this "interactive mode, vs used with redirected input" test on unix is using isatty(); and luckily there's an equivalent in the Windows CRT - see function _isatty(); or use GetFileType() checking for FILE_TYPE_CHAR on GetStdHandle(STD_INPUT_HANDLE) - or use say GetConsoleMode as Remy does, which will only succeed on a real console handle.

这篇关于WinAPI C ++客户端在读取之前检测到匿名管道上的写入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆