消息循环阻止应用程序

时间:2014-01-27 21:51:09

标签: c# download popup webbrowser-control message-loop

我需要在Web浏览器控件中关闭下载弹出窗口(禁止用户下载文件)。 我怎么能做到这一点?

我发现了这个: How to block downloads in .NET WebBrowser control?

我用了第二个答案。它工作但我有问题。看来,调用创建对象的GetText会阻塞整个线程。我没有任何解决方案。

private static void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
    if (idObject == 0 && idChild == 0)
    {
        if(eventType == EVENT_OBJECT_CREATE)
        {
            string text = GetText(hwnd);
            if (text.Contains("File Download"))
                SendMessage(hwnd, 0x0010, IntPtr.Zero, IntPtr.Zero); //close window
        }
    }
}

public static string GetText(IntPtr hWnd)
{
    int length = GetWindowTextLength(hWnd); //my app is freezing here - i think it's because i'm calling it from message loop.
    StringBuilder sb = new StringBuilder(length + 1);
    GetWindowText(hWnd, sb, sb.Capacity);
    return sb.ToString();
}

//修改

好的,谢谢@sgorozco的建议。现在我正在使用SetWindowsHookEx和WH_CBT。然后在消息循环中我正在捕获HCBT_CREATEWND事件。但我从lparm获取CBT_CREATEWND时遇到问题。我得到“托管调试助手'FatalExecutionEngineError'”异常。

这是我目前的代码:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public struct CREATESTRUCT
        {
            public IntPtr lpCreateParams;
            public IntPtr hInstance;
            public IntPtr hMenu;
            public IntPtr hwndParent;
            public int cy;
            public int cx;
            public int y;
            public int x;
            public int style;
            public string lpszName;
            public string lpszClass;
            public int dwExStyle;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public struct CBT_CREATEWND
        {
            public IntPtr lpcs;
            public IntPtr hwndInsertAfter;

        }

private static IntPtr MessageLoopFuctnion(int code, IntPtr wParam, IntPtr lParam)
        {
            if (code < 0)
            {
                return CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
            }

            if(code == 3)
            {
                CBT_CREATEWND info;
                info = (CBT_CREATEWND)Marshal.PtrToStructure(lParam, typeof(CBT_CREATEWND));

                CREATESTRUCT info1;
                info1 = (CREATESTRUCT)Marshal.PtrToStructure(info.lpcs, typeof(CREATESTRUCT)); //here exception is throwing

                if (info1.lpszName != null && info1.lpszName.Contains("File Download")))
                    SendMessage(wParam, 0x0010, IntPtr.Zero, IntPtr.Zero); //close popup

                //Marshal.FreeHGlobal(info.lpcs); //error, why?
                //Marshal.FreeHGlobal((IntPtr)lParam.ToUInt64());
            }


            return CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
        }

//set hook
            IntPtr hWinEventHook = SetWindowsHookEx(5, myCallbackDelegate, user32DLL, 0);

//编辑2

以下是我的定义:

 private delegate IntPtr HookProc(int code, IntPtr wParam, IntPtr lParam);
        private static HookProc myCallbackDelegate = new HookProc(MessageLoopFuctnion);

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr SetWindowsHookEx(int hookType, HookProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll")]
        static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

我的myCallbackDelegate是一个静态字段,所以它不是GC收集的。 临时我每隔500毫秒枚举所有窗口并查找包含文本“文件下载”的对话框。但这是一个丑陋的解决方案。

1 个答案:

答案 0 :(得分:0)

FatalExecutionEngineError的原因是CREATESTRUCT中的字符串。用IntPtr替换它们,你不会有任何例外。

[StructLayout(LayoutKind.Sequential)]
public struct CREATESTRUCT {
   public IntPtr lpCreateParams;
   public IntPtr hInstance;
   public IntPtr hMenu;
   public IntPtr hwndParent;
   public int cy;
   public int cx;
   public int y;
   public int x;
   public int style;
   public IntPtr lpszName;
   public IntPtr lpszClass;
   public int dwExStyle;
}

(也许您可以使用GetClassName和GetWindowText作为解决方法。未经过测试