¿Obteniendo el texto de un cuadro de diálogo que no usa un control de etiqueta?

Esta es una continuación de mi pregunta anterior.Cómo suprimir un cuadro de diálogo que muestra un servidor de COM Inproc.

Fondo:

Un resumen de mi situación: tengo un servidor COM Inproc escrito en Delphi de un tercero. Una de las funciones a las que llamo mostrará un cuadro de diálogo de mensaje de error si detecta un tipo de error específico. El problema es que estoy tratando de procesar los datos de forma masiva, y la fuente de datos que estoy usando hace que el cuadro de diálogo de error aparezca mucho (gracias a la respuesta de mi pregunta anterior, ahora se cierra automáticamente y pude ejecutarlo para finalizado, habría mostrado el cuadro de diálogo y requerido que alguien presione OK 9923 veces). El proceso se bloquea hasta que se cierra el cuadro de mensaje.

Pregunta:

Me gustaría tener un mejor registro de lo que dice el diálogo de error. Sin embargo, cualquier intento de obtener el texto del cuerpo del cuadro de diálogo ha fallado.

//Snip

private void StartWindowListener()
{
    //Queue the watcher on the message pump if we are not watching.
    if (_watcherRunning == false)
    {
        _watcherRunning = true;
        _dummyForm.BeginInvoke(new Action(() =>
        {
            _watcherRunning = false;

            //If we are not inside the com object don't enumerate.
            if (_insideCom == false) return;

            // Enumerate windows to find dialogs
            EnumThreadWndProc callback = new EnumThreadWndProc(CheckWindow);
            EnumThreadWindows(GetCurrentThreadId(), callback, IntPtr.Zero);
            GC.KeepAlive(callback);
        }));
    }
}

private bool CheckWindow(IntPtr hWnd, IntPtr lp)
{
    // Checks if hWnd is the expected dialog
    StringBuilder sb = new StringBuilder(260);
    GetClassName(hWnd, sb, sb.Capacity);
    if (sb.ToString() == "TMessageForm")
    {
        //This returns the dialog box's title
        GetWindowText(hWnd, sb, sb.Capacity);

        //This returns IntPtr.Zero
        var hDialogText = GetDlgItem(hWnd, 0xFFFF);
        if (hDialogText != IntPtr.Zero)
            GetWindowText(hDialogText, sb, sb.Capacity);

        //This returns a empty string
        GetDlgItemText(hWnd, 0xFFFF, sb, sb.Capacity);


        //Only sees the OK button.
        IntPtr hCtl = IntPtr.Zero;
        HashSet<IntPtr> seen = new HashSet<IntPtr>();
        while ((hCtl = GetNextDlgGroupItem(hWnd, hCtl, false)) != IntPtr.Zero)
        {
            //When we see the same control twice, break out of the loop.
            if (seen.Add(hCtl) == false)
                break;

            GetClassName(hCtl, sb, sb.Capacity);
            SendMessage(hCtl, WM_GETTEXT, sb.Capacity, sb)

            //Close the dialog by sending WM_CLOSE to the window
            SendMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
        }

         //Snip...
    }
    return true;
}

//Snip...

// P/Invoke declarations
const int WM_CLOSE = 0x0010;
private delegate bool EnumThreadWndProc(IntPtr hWnd, IntPtr lp);
[DllImport("user32.dll")]
private static extern bool EnumThreadWindows(int tid, EnumThreadWndProc callback, IntPtr lp);
[DllImport("user32.dll")]
private static extern int GetClassName(IntPtr hWnd, StringBuilder buffer, int buflen);
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
[DllImport("kernel32.dll")]
private static extern int GetCurrentThreadId();

Pensé que podría haber estado interrumpiendo el diálogo antes de agregarle el texto (aún no está completamente pintado cuando introduzco el código anterior). Sin embargo poniendo unApplication.DoEvents Dentro de StartWindowListener, antes de que comience, la enumeración permite que el cuadro de diálogo se pinte por completo, pero todavía obtengo los mismos resultados que publiqué con el código anterior.

Hacer un Ctrl-C funciona correctamente en el cuadro de diálogo, por lo que podría usarlo en caso de apuro, pero como tengo que repetir esto 9923 veces, me gustaría evitar usarlo programáticamente.

¿Hay otros métodos para intentar obtener el texto del cuadro de mensaje?

Respuestas a la pregunta(1)

Su respuesta a la pregunta