Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何抑制由代码显示的对话框,我可以';你不会变吗?_C#_.net_.net 4.0_Com_Messagebox - Fatal编程技术网

C# 如何抑制由代码显示的对话框,我可以';你不会变吗?

C# 如何抑制由代码显示的对话框,我可以';你不会变吗?,c#,.net,.net-4.0,com,messagebox,C#,.net,.net 4.0,Com,Messagebox,我有一个来自第三方的Inproc COM服务器。我调用的其中一个函数将显示一个错误消息对话框,如果它捕获特定类型的错误。问题是我试图批量处理数据,而我使用的数据源导致错误对话框大量弹出。如果生成了1000个对话框,则这不会是一个问题,但它会阻塞,并且函数在您按OK之前不会返回 如何禁止显示该对话框,或以编程方式按OK 这是调用堆栈的副本,因为它正在等待我按OK [Managed to Native Transition] > System.Windows.Forms.dll!Syste

我有一个来自第三方的Inproc COM服务器。我调用的其中一个函数将显示一个错误消息对话框,如果它捕获特定类型的错误。问题是我试图批量处理数据,而我使用的数据源导致错误对话框大量弹出。如果生成了1000个对话框,则这不会是一个问题,但它会阻塞,并且函数在您按OK之前不会返回

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

这是调用堆栈的副本,因为它正在等待我按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] [管理到本机转换] >System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafentiveMethods.IMsoComponentManager.FPushMessageLoop(System.IntPtr dwComponentID、int reason、int pvLoopData)行2198+0x1e字节C# System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason,System.Windows.Forms.ApplicationContext上下文)行3422+0x1b字节C# System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason,System.Windows.Forms.ApplicationContext上下文)第3306行+0xc字节# 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字节 mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_上下文(对象状态)第68行+0x27字节C# mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext ExecutionContext,System.Threading.ContextCallback回调,对象状态,bool preserveSyncCtx)行581+0xd字节C# mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext ExecutionContext,System.Threading.ContextCallback回调,对象状态,bool preserveSyncCtx)第530行+0xd字节C# mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext ExecutionContext,System.Threading.ContextCallback回调,对象状态)行519+0xe字节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);
}

for(int i=1;i首先,如果COM服务器本身能够在不让调用者失望的情况下使用不需要的UI操作,那么将其转换为模式肯定会更好。如果您不能改变第三方组件的行为,那么您仍然可以做的是挂接消息处理并强制关闭消息框


在第三方服务器上进行调用之前,您可以使用
SetWindowsHookEx
WH_CALLWNDPROC
安装消息钩子,您的回调将能够监视消息。特别是,您将能够发布消息、钩子对话框的WindowProc等,当然包括以编程方式关闭消息框

消息框会产生一个消息循环。这是您可以利用的,它允许您使用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 <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);
}

我从来没有在消息挂钩方面做过很多工作,我同意这是一个解决方案,但我不知道如何实现它,你能提供一些示例代码来说明我将如何设置它吗?(它不需要符合我的示例,我可以自己弄清楚,我只需要走上正确的轨道)我有C++代码,通过改变标准消息框来做这件事——添加“不显示”复选框,并实现自动关闭超时-我将很快将其联机。这里解释了类似的内容:COM服务器未在UI线程上调用,这是一个长时间运行的进程,因此我在后台任务中启动它,这是否是此解决方案的问题?是的,这将是一个问题。Control.BeginInvoke()无法工作,因为辅助进程未泵送消息循环。和GetCurrentThreadId()返回错误的线程ID。消息框很可能是在COM创建的单独线程上创建的,COM创建该线程是为了给服务器一个主线程,大多数COM组件都需要一个STA线程。您需要类似的东西:谢谢,我不得不稍微检查一下,我遇到了一些问题(例如,现在它正在用取消的事件淹没消息泵)然而,我知道如何自己解决这些问题,我只是必须首先克服关闭窗口的障碍。我会在24小时内,当它允许我时,奖励我。如果你想看到我的实现,我在后续问题中发布了它的大部分,并使用(new DialogCloser()){MessageBox.Show(“你永远看不到这个”);MessageBox.Show(“您永远不会看到这个”);}将显示第二个框
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");
    }
}