ReadConsoleInput 在按 Enter 后只读第一个符号

Posted

技术标签:

【中文标题】ReadConsoleInput 在按 Enter 后只读第一个符号【英文标题】:ReadConsoleInput read only first symbol after press Enter 【发布时间】:2017-04-28 23:09:35 【问题描述】:

对不起,我的英语不好,但我无法解决问题。现在我正在编写远程控制台。它使用 QTcpSocket 和函数与 Windows 控制台一起工作。几乎可以完美运行,但是当我尝试从控制台读取时,我需要先按 Enter,然后才会读取我的第一个字母。如果我想输入第二个字母,我需要再次按 Enter。我怎样才能读懂我写的每封信? 这是我的构造函数:

FreeConsole();

    dwProcessId = 0 ;
    dwErrorId = 0;
    std::wstring path = L"cmd.exe";

    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory(&si, sizeof(si));
    ZeroMemory(&pi, sizeof(pi));

    si.cb = sizeof(si);

    SECURITY_ATTRIBUTES security = 
       sizeof(security), NULL, TRUE
     ;

    if(CreateProcess(NULL, (LPWSTR)path.c_str(), NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi))
    
        dwProcessId = pi.dwProcessId;
    
    else
    
        dwErrorId = GetLastError();
        printf("CreateProcess failed (%d).\n", dwErrorId);
        return;
    

    Sleep(1000);

    if(!AttachConsole(pi.dwProcessId))
    
        dwErrorId = GetLastError();
        printf( "AttachConsole failed (%d).\n", dwErrorId);
        return;
    

在这里我有问题的功能:

int Console::readInputFromConsole(DataIn& data)

    data.inputRecords.resize(40);

    HANDLE inputHandle = GetStdHandle(STD_INPUT_HANDLE);
    DWORD events = 0;
    DWORD unread = 0;

    DWORD fdwMode = ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT;
    //fdwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
    BOOL bMode = SetConsoleMode(inputHandle, fdwMode);
    if(!bMode)
    
        std::runtime_error("error with mode");
    

    Sleep(20);
    BOOL statusUnread = TRUE;
    statusUnread = GetNumberOfConsoleInputEvents(inputHandle, &unread);
    if(!statusUnread)
        throw std::runtime_error("GetNumberOfConsoleInputEvents failed.");

    data.inputRecords.resize(unread);

    BOOL statusRead = TRUE;
    statusRead = ReadConsoleInput(inputHandle, &data.inputRecords[0], unread, &events);
    if(!statusRead)
        throw std::runtime_error("ReadConsoleInput failed.");

    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &data.consoleScreenBufferInfo);

    return 0;

【问题讨论】:

在阅读之前更改控制台模式无法正常工作,为时已晚。您必须在 main() 函数中更改它。对于您不拥有的控制台,这会打击执行此操作的选项。根本问题是您有 两个 进程试图从控制台读取。您的代码只会使第二个进程随机失败。没有简单的解决方案,您必须重新考虑这一点。 ....你为什么还要从本地控制台读取输入?我不确定我是否理解您的情况。 我需要它来模拟控制台输入和输出。例如,我可以使用 far.exe,使用我的程序(显然在未来)。它必须如何在本地控制台工作,但在另一台计算机上执行命令。但我现在没有其他方法可以做到这一点,我的导师只向我展示了这种方式。 如果该程序在本地计算机上运行,​​从用户那里获取输入并(最终)将该输入传递给远程计算机以运行,您为什么要启动 cmd.exe 的副本? cmd.exe 进程打算做什么? 是的,在客户端 cmd.exe 是不必要的,但在服务器端我需要执行我的命令:“dir”、“chcp”、“cd”或其他。为此,我创建了进程“cmd.exe”并在此进程中传递命令。在我读取所有输出并将其发送到客户端之后。 【参考方案1】:

我解决了问题。我刚刚在客户端计算机上创建了不必要的进程。这很愚蠢,但是我只是尝试在新窗口中启动进程。

【讨论】:

以上是关于ReadConsoleInput 在按 Enter 后只读第一个符号的主要内容,如果未能解决你的问题,请参考以下文章

WPF:一个文本框,它具有在按下 Enter 键时触发的事件

我可以知道在按 Enter 之前按下了哪个键盘键吗

即使 std::cout 用于给定代码中的每个字符/在给定代码中的每个字符之后,如何在按 ENTER 之后显示字符串?

按下 ENTER 时禁用 Textarea 中的新行

在 Enter 键上提交登录信息 [重复]

C++ ReadConsoleInput 不适用于 boost::thread