2

我正在尝试访问从控制台接收输入的文件描述符。我目前正在使用

HANDLE fd = CreateFile(
    "CONIN$",
    GENERIC_READ | GENERIC_WRITE,
    TRUE,
    0,
    OPEN_EXISTING,
    0,
    0);
SetConsoleMode(fd, ENABLE_WINDOW_INPUT);

并将 fd 返回到从控制台读取(基于 libuv)输入的程序。

当进程在控制台中执行时,这工作正常,但是当我将输入管道输入到程序中时,从 fd 读取崩溃

echo hello | inputProgram

我怀疑没有与输入过程关联的控制台,但我不确定。以这种方式执行时,如何正确地将输入读入 cmd 窗口?


所以我在 Node.js 中绑定到这个 C++ 程序。我打电话

var ReadStream = require("tty").ReadStream();
var TTY = process.binding("tty_wrap").TTY;

module.exports = function () {
    var opentty = require("./bin/opentty.node") // program returns the fd int
    var fd = opentty();
    var t = new _TTY(fd, true);
    return new ReadStream(t);
}

opentty 在文件句柄的重定向输入模式下返回 3。处理这个文件句柄的代码可以在这里找到

https://github.com/joyent/node/blob/master/src/tty_wrap.cc#L185

本质上是uv_tty_init在这里找到的

https://github.com/joyent/node/blob/master/deps/uv/src/win/tty.c#L99

流错误Error: read EBADF,系统调用:读取

4

1 回答 1

1

查看 Node 存储库,似乎很清楚需要new _TTY(fd, true)一个 C 文件描述符,但您正在向它传递一个 Win32 句柄。

_open_osfhandle函数从句柄创建文件描述符。

所以,你应该试试

var t = new _TTY(_open_osfhandle(fd), true);

(正如评论中所讨论的,这仅在您与 libuv 共享 C 运行时才有效。)

理想情况下,您会使用 libuv 的 open 函数,但不幸的是fs__open中有一个错误:

  case _O_RDWR:
    access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;

这是它决定请求哪些访问权限的地方。FILE_GENERIC_WRITE 和 FILE_GENERIC_READ 顾名思义,是特定于文件的,不能用于打开 CONIN$。它应该是

  case _O_RDWR:
    access = GENERIC_READ | GENERIC_WRITE;

这将适用于文件和其他类型的对象,例如控制台输入和输出。(我在一个简单的 C 程序中复制了这一点;在我的系统上,使用 FILE_* 权限肯定会阻止您打开 CONIN$。)

于 2014-03-20T02:44:26.037 回答