How to suppress a dialog box displayed by code that I can't change?

前端 未结 2 1136
一个人的身影
一个人的身影 2020-11-28 15:36

I have a Inproc COM Server from a 3rd party. One of the functions I call will display a error message dialog box if it traps a specific type of error. The issue is I am tryi

2条回答
  •  攒了一身酷
    2020-11-28 16:05

    A message box pumps a message loop. That's something you can take advantage of, it allows you to inject code with Control.BeginInvoke() that runs as soon as the message box appears. You can then use that code to find the dialog window and close it. Add a new class to your project and paste this code:

    using System;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    public class DialogCloser : IDisposable {
        public DialogCloser() {
            if (Application.OpenForms.Count == 0) throw new InvalidOperationException();
            Application.OpenForms[0].BeginInvoke(new Action(() => {
                // Enumerate windows to find dialogs
                if (cancelled) return;
                EnumThreadWndProc callback = new EnumThreadWndProc(checkWindow);
                EnumThreadWindows(GetCurrentThreadId(), callback, IntPtr.Zero);
                GC.KeepAlive(callback);
            }));
        }
    
        public void Dispose() {
            cancelled = true;
        }
    
        private static bool checkWindow(IntPtr hWnd, IntPtr lp) {
            // Checks if  is a Windows dialog
            StringBuilder sb = new StringBuilder(260);
            GetClassName(hWnd, sb, sb.Capacity);
            if (sb.ToString() == "#32770") {
                // Close it by sending WM_CLOSE to the window
                SendMessage(hWnd, 0x0010, IntPtr.Zero, IntPtr.Zero);
            }
            return true;
        }
    
        private bool cancelled;
    
        // P/Invoke declarations
        private delegate bool EnumThreadWndProc(IntPtr hWnd, IntPtr lp);
        [DllImport("user32.dll")]
        private static extern bool EnumThreadWindows(int tid, EnumThreadWndProc callback, IntPtr lp);
        [DllImport("kernel32.dll")]
        private static extern int GetCurrentThreadId();
        [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);
    }
    

    Sample usage:

    private void button1_Click(object sender, EventArgs e) {
        using (new DialogCloser()) {
            // Replace this with the call to the COM server method:
            MessageBox.Show("you never see this");
        }
    }
    

提交回复
热议问题