Capture OutputDebugString output


The OutputDebugString Windows API call allows applications to produce output which can be collected by an independent debugger process reading from a pipe. The OutputDebugString function itself is exposed by the win32api module in pywin32, and is simple enough to use. Capturing the messages which applications produce using this call requires a specific set of pipes and buffers.

Update: For a useful application of this see Ken McFadden's LogDbgView class

A thread on python-list started by Dan Brotherston led to some experimentation and eventually to the solution below, reproduced with Dan's permission although slightly modified by me. The crucial thing turned out to be creating the mmap buffer with ACCESS_WRITE (although we're not quite sure why).

# Original code by Dan Brotherston
import sys
import mmap
import struct
import win32event

buffer_ready = win32event.CreateEvent (
  None, 0, 0,
data_ready = win32event.CreateEvent (
  None, 0, 0, 
buffer = mmap.mmap (0, 4096, "DBWIN_BUFFER", mmap.ACCESS_WRITE)

while True:
  # Signal that we're ready to accept debug output
  win32event.SetEvent (buffer_ready)
  if win32event.WaitForSingleObject (data_ready, win32event.INFINITE) == win32event.WAIT_OBJECT_0: (0)
    # The first DWORD is the process id which generated the output
    process_id, = struct.unpack ("L", (4))
    data = (4092)
    if "\0" in data:
      string = data[:data.index ("\0")]
      string = data
    print "Process %d: %s" % (process_id, string)

To see it in action, run this snippet which will keep spawning processes to send debug output

import os, time

for i in range (10):
  os.system (
    'python -c "import os;import win32api;win32api.OutputDebugString ("""From %d""" % os.getpid ())"'
  time.sleep (0.5)