【问题标题】:How to avoid "is not recognized as an internal or external command, operable program or batch file" when entering text in attached console?在附加控制台中输入文本时如何避免“不被识别为内部或外部命令、可运行程序或批处理文件”?
【发布时间】:2026-02-08 22:50:01
【问题描述】:

我附上了现有的控制台表单 C++ 程序。输出工作正常,但是当我尝试在控制台中输入一些输入时,最初在那里运行的终端会尝试处理它。 程序代码在这里:

#include <iostream>
#include "windows.h"

int main(int argc, char **argv)
{
    pid_t pid = atoi(argv[1]);
    BOOL fret = FreeConsole();
    if  (!fret)
    {
        std::cerr << "ERR" << GetLastError() << std::endl;
    }

    BOOL aret = AttachConsole(pid);

    if  (!aret)
    {
        std::cerr << "ERR" << GetLastError() << std::endl;
    }

    SetConsoleTitleA("TTTTTTTT");

    for (int ii = 0; ii < 10; ii++)
    {
        std::cout << "ii " << ii << std::endl;
    }

    int kk;
    std::cin >> kk;

    std::cerr << "kk " << kk << std::endl;

    return 0;
}

当我运行cmd,找出PID,运行我的程序然后写例如12回车,结果是这样的:

C:\>ii 0
ii 1
ii 2
ii 3
ii 4
ii 5
ii 6
ii 7
ii 8
ii 9
12
'12' is not recognized as an internal or external command,
operable program or batch file.

当我再次尝试写 12 时,效果更好(但仍然有 C:>)

C:\>12
kk 12
C:\>

编辑:我需要将 stdin、stdout 和 stderr 重定向到控制台,我可以运行其他东西然后 cmd 或向 cmd 发送一些命令。

【问题讨论】:

  • 你依附于别人的控制台,期待奇怪的事情发生。 cmd.exe 通过读取控制台屏幕缓冲区中的字符而不是标准输入来获取输入在技术上是合法的,这很疯狂但合法。

标签: c++ windows winapi cmd


【解决方案1】:

"不被识别为内部或外部命令, 可运行的程序或批处理文件。”是标准的 cmd.exe 错误消息。当您执行 AttachConsole 时,cmd.exe 已经在等待输入,因此第一个输入被发送到 cmd.exe,这就是您收到该错误消息的原因。用dir之类的命令替换第一个数字输入,你会看到这个输入被cmd.exe接收到了。

第二次成功了,但大多是偶然的。 cmd.exe 可能正忙于其他事情,因此您的应用程序在 cmd.exe 能够再次“收听”标准输入之前获得输入。 cmd.exe 打印提示符(“路径”+&gt;),因为这是在执行每个命令后它所做的。

cmd.exe 不希望与其他任何人共享控制台,其正常操作模式是:

  1. stdin 读取并解析一行。
  2. 执行。如果命令是内部命令或外部控制台应用程序,请等待操作完成。它不等待 GUI 应用程序。
  3. 打印 %PROMPT%。
  4. 转到 1。

即使您可以说服 cmd.exe 与您共存,您所做的也可能是未定义的行为,因为您将低级本机 Windows 控制台函数 (AttachConsole) 与高级 C++ I/O 函数 ( std::cout & std::cin)。假设您使用的是 Microsoft CRT,您可以使用 _open_osfhandle + _dup2 正确分配本机控制台句柄,但您仍然会遇到 cmd.exe 问题并且无法解决它。

【讨论】:

  • 如果 cmd.exe 不希望与任何人共享控制台,那么 AttachConsole(pid) 应该如何工作?我需要将 stdin、stdout 和 stderr 重定向到控制台,我可以运行其他东西然后 cmd 或向 cmd 发送一些命令。
  • cmd.exe 不是 控制台,它只是一个程序。可能还有其他场景非常适合 AttachConsole,但事实并非如此。如果您只需要一个控制台,您可以分配(打开)您自己的控制台。如果您控制 cmd.exe 的启动方式,那么您也许可以运行 cmd.exe /c pause
最近更新 更多