2001-07 : I had just started working for the Fund, but the OMM sys-admins had a request. When the OMM system crashed, the debug spew in the console window was important for debugging but required a manual step to copy to a file. It often was not included in crash reports. The sys-admins were trying to write some scripts that would automatically handle a crash, but they couldn't write a fully automatic script if they had to manually copy the console.

I knew that the Win32 API allowed reading from the console, so it was easy enough to write a little tool that would read the current console and write it to a file.

My first suprise was that the read-console API would fail with an out-of-memory error if you tried to read too big of a chunk at once. That was easy enough to work around.

Next, the sys admins told me that being able to save the current console was helpful, but sometimes it was not possible to run a command in the console that the crashed process was in. (Pressing Ctrl-C would cause the console to exit, etc.) They needed to be able to read any console.

I searched through the API docs, but everything refered to the current console. Even looking though the exports of NTDLL didn't show anything usable. I tried some experiments and wasn't able to turn up anything useful. As far as I can tell, it is absolutely not possible to access a console unless it was inheritted or created by the current process.

Well, if you can't get mohamed to come to the mountain, you must bring the mountain to mohamed. I decided to take the dirtiest approach I could think of, and the only one left. I decided to write the console saving code into the address space of the process whose console we wanted, and execute it there. And it frickin' worked!

Then the sys-admins came back again! Geeze, will these guys ever be satisfied? They could not save the console of an app that was started by the task scheduler. These apps were running as LOCALSYSTEM. I couldn't get sufficient access to the process handle. This didn't make sense to me, because ADMINISTRATOR should be able to do anything. Well, after learning a lot about permissions and privileges I was able to solve the problem. It turns out you have to specifically enable your administrative superpowers so you don't use accidently them when you don't want to.


SaveConsole { <pid> | '-' } <filename>
  <pid> - save the console being used by process <pid> (hex ok)
  '-'   - save the current console
  <filename> - file to save to

You can get the source via anonymous CVS at

  • cvs -d co 2001/SaveConsole

    Note: This code only runs when compiled in debug mode because of the way it determines the length of the snippet to be injected.

    Due to popular demand, you can download the binary executable as well: SaveConsole.exe.

    C o m m e n t s :    
    (nothing yet)