Capturing console I/O in Win32

You've come to this page because you've asked a question similar to

I am writing a Win32 program to run on Windows NT (4, 2000, or XP), and I want to capture the output to the console of a DOS or a Win32 console application that I spawn from my program, and control its input. How do I do this ?

This is the Frequently Given Answer to that question.

(You can find the same answer, formatted slightly differently, on J.M. Hart's Critical Comments page.)

Because of a programming tradition on Microsoft operating systems that goes all of the way back to the earliest versions of MS-DOS, there is no one single way to capture the output or control the input of a textual application.

First of all, there is no distinction between DOS and Win32 console applications here. On Windows NT, the case of DOS applications is actually a subset of the more general case of "console mode" applications, because DOS applications run as coroutines within a Win32 process (NTVDM) that translates their I/O to Win32 equivalents.

There are two classes of console mode applications. The important difference between the two is whether they read from and write to their standard input and standard output in "glass TTY" fashion using ReadFile() and WriteFile() (what Win32 terms high-level console I/O), or whether they use "random access" APIs such as WriteConsoleOutput() (what Win32 terms low-level console I/O). Translating this to DOS terms: DOS programs that use INT 21h to read from and write to their standard input and standard output are in the former class; and DOS programs that use INT 10h or that write directly to video memory are in the latter class.

It is difficult to combine the two mechanisms into one for capturing output, and practically impossible to combine them for controlling input. So really one must know ahead of time the type of textual application that is going to be run, i.e. whether it is going to be using high-level or low-level console I/O, and select the appropriate mechanism accordingly.

The only perfect solution that would cope with both sorts of programs simultaneously would be for Win32 to provide functionality akin to what in the UNIX world is known as a pseudo-TTY. Win32 would need to provide some means of for a monitoring process to hook into the "back" of a console instead of the "front" as seen in normal use. The monitor process would write data to the back of the console and the console would turn those data into keystrokes that applications reading from the front of the console, by either means, would see as input. All output written to the console, by either means, would be translated into a single encoded bytestream that the monitor process could then read from the back of the console, in sequence, without needing to poll, and without missing any data.

Alas, Windows has no such mechanism.

© Copyright 2000–2001 Jonathan de Boyne Pollard. "Moral" rights asserted.
Permission is hereby granted to copy and to distribute this web page in its original, unmodified form as long as its last modification datestamp is preserved.