如何抑制由我​​无法更改的代码显示的对话框?

我有来自第三方的Inproc COM服务器。 如果它捕获特定类型的错误,我调用的函数之一将显示错误消息对话框。 问题是我正在尝试批量处理数据,而我使用的数据源导致错误对话框弹出很多。 如果它产生1000个对话框,这不会是一个问题,而是它会阻塞,直到您按OK才会返回该function。

在此处输入图像描述

如何禁止显示对话框,或以编程方式按OK?

这是一个调用堆栈的副本,​​因为它正在等待我按OK

     [管理到原生过渡]  
 > System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(System.IntPtr dwComponentID,int reason,int pvLoopData)Line 2198 + 0x1e bytes C#
     System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason,System.Windows.Forms.ApplicationContext context)Line 3422 + 0x1b bytes C#
     System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason,System.Windows.Forms.ApplicationContext context)Line 3306 + 0xc bytes C#
     System.Windows.Forms.dll!System.Windows.Forms.Application.Run(System.Windows.Forms.Form mainForm)第1495行+ 0x31字节C#
     UniversalDataImporter.exe!UniversalDataImporter.Program.Main()第18行+ 0x1d字节C#
     [原生于管理过渡]  
     [管理到原生过渡]  
     mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile,System.Security.Policy.Evidence assemblySecurity,string [] args)2023行+ 0x18字节C#
     Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()+ 0x27 bytes  
     mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(对象状态)第68行+ 0x27字节C#
     mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext,System.Threading.ContextCallback callback,object state,bool preserveSyncCtx)581行+ 0xd字节C#
     mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext,System.Threading.ContextCallback callback,object state,bool preserveSyncCtx)第530行+ 0xd字节C#
     mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext,System.Threading.ContextCallback callback,object state)Line 519 + 0xe bytes C#
     mscorlib.dll!System.Threading.ThreadHelper.ThreadStart()第105行+ 0x20字节C#
     [原生于管理过渡]  

我怀疑它会有所帮助(没有选项可以禁用消息框,订阅事件或函数的其他重载)但这里是调用代码。

for (int i = 1; i <= recordCount; i++) { //If the dialog shows up the following line blocks till you press OK. var values = _comServer.GetValues(fileHandle, i); sqlDataConsumer.LoadRow(values); } 

消息框泵出消息循环。 这是你可以利用的东西,它允许你使用在消息框出现后立即运行的Control.BeginInvoke()注入代码。 然后,您可以使用该代码查找对话框窗口并将其关闭。 在项目中添加一个新类并粘贴以下代码:

 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); } 

样品用法:

 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"); } } 

首先,如果COM服务器本身可以在不让不需要的UI操作让调用者失效的情况下进入模式,那肯定会更好。 如果您无法更改第三方组件行为,您仍可以执行的操作是挂钩消息处理并强制关闭消息框。

在第三方服务器上执行调用之前,您可以使用SetWindowsHookExWH_CALLWNDPROC安装消息挂钩,并且您的回调将能够监视消息。 特别是你将能够发布消息,钩对话框的WindowProc等。包括消息框的肯定程序化关闭。