如何禁止一个对话框显示的代码,我不能改变? [英] How to suppress a dialog box displayed by code that I can't change?

查看:461
本文介绍了如何禁止一个对话框显示的代码,我不能改变?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个来自第三方的Inproc COM服务器。如果调用的其中一个函数捕获特定类型的错误,将显示一个错误消息对话框。问题是我试图批量处理数据,我使用的数据源导致错误对话框弹出很多。这不会是一个问题,如果它生成1000个对话框,而是阻止和功能不返回,直到你按OK。

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 trying to process data in bulk, and the data source I am using is causing that error dialog to pop up a lot. This would not be a issue if it spawned 1000 dialog boxes, but instead it blocks and the function does not return until you press OK.

如何抑制对话框显示或以编程方式显示

How can I suppress the dialog from showing up, or programmatically press OK?

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

Here is a copy of the call stack as it is waiting for me to press OK


    [Managed to Native Transition]  
>   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) Line 1495 + 0x31 bytes    C#
    UniversalDataImporter.exe!UniversalDataImporter.Program.Main() Line 18 + 0x1d bytes C#
    [Native to Managed Transition]  
    [Managed to Native Transition]  
    mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence assemblySecurity, string[] args) Line 2023 + 0x18 bytes  C#
    Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() + 0x27 bytes  
    mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) Line 68 + 0x27 bytes   C#
    mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 581 + 0xd bytes  C#
    mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 530 + 0xd bytes  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() Line 105 + 0x20 bytes  C#
    [Native to Managed Transition]  

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

I doubt it will help (there are no options to disable the message box, events to subscribe to, or other overloads to the function) but here is the calling code.

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(),一旦消息框出现运行。然后,您可以使用该代码找到对话框窗口并关闭它。向您的项目添加一个新类,并粘贴此代码:

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

这篇关于如何禁止一个对话框显示的代码,我不能改变?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆