2

I need to close a download popup in web browser control (disallow user to downloading file). How i can achieve this?

I found this: How to block downloads in .NET WebBrowser control?

And i used second answer. It's working but i have problem with it. It's seems that calling GetText of the created object is blocking a whole thread. I don't have any solution for it.

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

//edit

Ok, thanks @sgorozco for suggestion. Now i'm using SetWindowsHookEx and WH_CBT. Then in message loop i'm catching HCBT_CREATEWND events. But i have problem with getting CBT_CREATEWND from lparm. I'm getting "Managed Debugging Assistant 'FatalExecutionEngineError'" exception.

Here is my current code:

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

//edit 2

Here are my definitions:

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

My myCallbackDelegate is a static field so it's not GC collected for sure. Temporary i'm enumerating all windows every 500ms and look for dialog which contains text "File Download". But it is an ugly solution.

9
  • I am not 100% sure, but the reason the call may be blocking could be that at the stage that the hook intercepts the call, the window is about to be created, so there's no window text to retrieve yet. Maybe if you hook to the CBT_ACTIVATE event rather than HCBT_CREATEWND, you could still accomplish what you desire (the hook will be called many more times, but at least at that point the windows are guaranteed to have been created). Good Luck! Commented Jan 28, 2014 at 1:51
  • 1
    @sgorozco, if you posted your comment as an answer, I'd up-vote it. The OP still can access the window text via CBT_CREATEWND/CREATESTRUCT inside CBTProc, no need to call GetText for that. Commented Jan 28, 2014 at 5:15
  • @Yozer. It's strange - I don't see any evident problems in the code, the struct definitions seem to be right as well as the Marshal.PtrToStructure() calls. Can you post the complete declaration of myCallbackDelegate (including the delegate definition) as well as the code that links the MessageLoopFunction() to the myCallbackDelegate parameter? I suspect some Interop decorations are missing for the delegate declaration and maybe that could be the reason why the lparam is not receiving a valid pointer in the first place. Commented Jan 28, 2014 at 18:03
  • @Yozer, make sure you keep the reference to myCallbackDelegate in the field of the class (i.e., this.myCallbackDelegate), otherwise it most likely gets freed by GC after the SetWindowsHookEx call. Commented Jan 29, 2014 at 2:40
  • @Yozer, Hi! Could you please try adding the following attribute to your HookProc delegate and try again? Commented Jan 29, 2014 at 19:45

1 Answer 1

0

The reason for the FatalExecutionEngineError are the strings in CREATESTRUCT. Replace these with a IntPtr and you will get no exception.

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

(Maybe you can use GetClassName and GetWindowText instead as workaround. not tested)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.