Windows 没有tty的Acessing CONIN$
我试图访问从控制台接收输入的文件描述符。我目前正在使用Windows 没有tty的Acessing CONIN$,windows,cmd,libuv,Windows,Cmd,Libuv,我试图访问从控制台接收输入的文件描述符。我目前正在使用 HANDLE fd = CreateFile( "CONIN$", GENERIC_READ | GENERIC_WRITE, TRUE, 0, OPEN_EXISTING, 0, 0); SetConsoleMode(fd, ENABLE_WINDOW_INPUT); 以及将fd返回到从控制台读取(基于libuv)输入的程序 当进程在控制台中执行时,这可以正常工作,但是当我将输入导
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。处理这个文件句柄的代码可以在这里找到
它本质上调用了这里的uv\u tty\u init
带有
Error:read EBADF
,syscall:read的流错误查看节点存储库显然new\u TTY(fd,true)
需要一个C文件描述符,但您正在传递一个Win32句柄
该函数从句柄创建文件描述符
所以,你应该试试
var t = new _TTY(_open_osfhandle(fd), true);
(正如注释中所讨论的,只有在与libuv共享C运行时时时,这才有效。)
理想情况下,您可以使用libuv的open函数,但不幸的是,其中存在一个bug:
这是它决定请求哪些访问权限的地方。文件\通用\写入和文件\通用\读取,顾名思义,是特定于文件的,不能用于打开CONIN$。应该是
case _O_RDWR:
access = GENERIC_READ | GENERIC_WRITE;
这将适用于文件和其他类型的对象,如控制台输入和输出。(我在一个简单的C程序中复制了这一点;在我的系统上,使用文件*权限肯定会阻止您打开CONIN$)如果您没有,应该为您创建一个。
inputProgram
是控制台应用程序吗?CreateFile
是否失败,如果失败,返回什么错误代码?如果没有,到底什么地方出了问题,什么时候出了问题?如果有帮助,inputProgram是一个node.js进程,如果我正确理解这意味着什么,它应该是一个控制台应用程序。CreateFile不会失败,但将文件句柄传递给libuv以从文件句柄创建readstream会导致应用程序刚刚退出,可能是segfault。我怀疑控制台输入没有引用父cmd窗口的输入。您应该继承父cmd窗口的控制台。如果只是针对句柄发出一个ReadFile
,会发生什么?我担心实际的问题深深地嵌入到libuv中,而我对libuv并不熟悉-您有源代码吗?您是否能够在调试器中运行它,以便查看实际失败的位置?如果我检查管道类型,它返回为未知。类型检查在这里-createfile中有一些可能是问题的附加选项,inherit敲响了警钟。我注意到opentty.cc
中的代码没有检查调用createfile
是否成功?我尝试了这个。C文件描述符与此场景中的句柄相同,即句柄为3,返回的_open_osfhandle(fd,_O_RDWR)也返回3。数字相同的事实是一个巧合-请注意,这不是一个特别奇怪的数字,因为它们都从0开始计数。这意味着在代码中的这一点上,句柄的数量与文件描述符的数量相同。。。。或者可能不是,Win32句柄确实出现了一些奇怪的情况;可能与cmd.exe如何设置继承的句柄有关,或者与控制台模式应用程序如何初始化有关,我不确定。为了记录在案,根据chat中的讨论,我怀疑这不起作用,因为libuv代码与OPs代码不共享同一个运行时库实例,因此,其中一个中生成的文件描述符在另一个中无效。然而,这并不完全清楚。这应该说,用uv\u fs\u open
调用libuv也无法打开CONIN$
case _O_RDWR:
access = GENERIC_READ | GENERIC_WRITE;