Today's Little Program logs the contents of every message box dialog, or anything that vaguely resembles a message box dialog. (Since there's no way for sure to know whether a dialog box is a message box or not.)

using System.Windows.Automation;

class Program
{
 [System.STAThread]
 public static void Main(string[] args)
 {
  Automation.AddAutomationEventHandler(
   WindowPattern.WindowOpenedEvent,
   AutomationElement.RootElement,
   TreeScope.Descendants,
   (sender, e) => {
    var element = sender as AutomationElement;
    if (element.GetCurrentPropertyValue(
     AutomationElement.ClassNameProperty) as string != "#32770") {
     return;
    }

    var text = element.FindFirst(TreeScope.Children,
     new PropertyCondition(AutomationElement.AutomationIdProperty, "65535"));
    if (text != null) {
     System.Console.WriteLine(text.Current.Name);
    }
   });
  System.Console.ReadLine();
  Automation.RemoveAllEventHandlers();
 }
}

This is the same pattern as the program we wrote last week, but with different guts when the window opens.

This time, we see if the class name is #32770, which UI Spy tells us is the class name for dialog boxes. (That this is the numerical value of WC_DIALOG is no coincidence.)

If we have a dialog, then we look for a child element whose automation ID is 65535, which UI Spy tells us is the automation ID for the text inside a message box dialog. (That the traditional control ID for static controls is -1 and 65535 is the the numerical value of (WORD)-1, is no coincidence.)

If so, then we print the text.

If we were cleverer, we could also confirm that the only buttons are OK, Cancel, and so on. Otherwise, we can get faked out by other dialog boxes that contain static text.