创建控制台

系统启动控制台进程时会创建一个新的控制台,该进程是字符模式进程,其入口点为主函数。 例如,当系统启动命令处理程序 cmd.exe时,将创建一个新的控制台。 命令处理程序启动新的控制台进程时,用户可以指定系统是为新进程创建新的控制台,还是继承该命令处理程序的控制台。

进程可以使用以下方法之一创建控制台:

  • 图形用户界面 (GUI) 或控制台进程可以将 CreateProcess 函数与 CREATE_NEW_CONSOLE 一起使用,以创建控制台进程以及新的控制台。 (默认情况下,控制台进程会继承其父进程的控制台,并且无法保证输入由其预期的进程所接收。)
  • 当前未附加到控制台的 GUI 或控制台进程可以使用 AllocConsole 函数来创建新的控制台。 (GUI 进程在创建时不会附加到控制台。如果控制台进程是使用 CreateProcess 和 DETACHED_PROCESS 创建的,则这些进程不会附加到控制台。)

通常,当发生需要与用户交互的错误时,进程使用 AllocConsole 来创建控制台。 例如,GUI 进程可以在发生错误而无法使用其常规图形界面时创建控制台,或者通常不与用户交互的控制台进程可以创建控制台以显示错误。

进程还可以通过在对 CreateProcess 的调用中指定 CREATE_NEW_CONSOLE 标志来创建控制台。 此方法会创建一个新的控制台,子进程可以访问该控制台,但父进程无法访问。 通过使用单独的控制台,使父进程和子进程均可与用户进行交互,而不会发生冲突。 如果在创建控制台进程时未指定此标志,则这两个进程都将附加到同一控制台上,并且无法保证输入由其预期的正确进程所接收。 应用程序可以通过以下方法避免混乱:创建不继承输入缓冲区句柄的子进程,或者一次仅让一个子进程可以继承输入缓冲区句柄,同时在子进程完成前阻止父进程读取控制台输入。

创建新的控制台会生成一个新的控制台窗口,以及用于屏幕输出用户输入的独立 I/O 缓冲区。 与新控制台关联的进程使用 GetStdHandle 函数获取新控制台的输入和屏幕缓冲区的句柄。 这些句柄使进程能够访问控制台。

当进程使用 CreateProcess 时,它可以指定 STARTUPINFO 结构,该结构的各部分控制为子进程创建的第一个新控制台(如果有)的特性。 如果已指定 CREATE_NEW_CONSOLE 标志,则在对 CreateProcess 的调用中指定的 STARTUPINFO 结构会影响创建的控制台。 如果子进程随后使用 AllocConsole,则它也会影响创建的控制台。 可以指定以下控制台特性:

  • 新控制台窗口的大小(以字符单元格表示)
  • 新控制台窗口的位置(以屏幕像素坐标表示)
  • 新控制台屏幕缓冲区的大小(以字符单元格表示)
  • 新控制台屏幕缓冲区的文本和背景色属性
  • 新控制台窗口标题栏的显示名称

如果未指定 STARTUPINFO 值,系统将使用默认值。 子进程可以使用 GetStartupInfo 函数来确定其 STARTUPINFO 结构中的值

进程无法更改其控制台窗口在屏幕上的位置,但以下控制台函数可用于设置或检索在 STARTUPINFO 结构中指定的其他属性

函数 说明
GetConsoleScreenBufferInfo 检索窗口大小、屏幕缓冲区大小和颜色属性。
SetConsoleWindowInfo 更改控制台窗口的大小。
SetConsoleScreenBufferSize 更改控制台屏幕缓冲区的大小。
SetConsoleTextAttribute 设置颜色属性。
SetConsoleTitle 设置控制台窗口标题。
GetConsoleTitle 检索控制台窗口标题。

进程可以使用 FreeConsole 函数将自己从继承的控制台或由 AllocConsole 创建的控制台中分离

进程在使用 FreeConsole 从其自己的会话中分离后(或者如果没有附加的会话),可以使用 AttachConsole 函数将其自身附加到另一个现有的控制台会话