简体   繁体   中英

WebBrowser control not responding to InvokeMember(“click”)

After spending 5 days of my life, I'm about to give up on this, but am consulting the experts once before that.

I have a WebBrowser control that loads a webpage and I programmatically scrape its contents. Clicking a particular menu item in the page brings up File Open dialog when done in IE (or any other browser). But clicking the same button in WebBrowser control using InvokeMember() apparently doesn't do anything no matter what. I've gone through several SO questions such as Setting Browser Features to make sure my control behaves exactly like IE, but that hasn't succeeded.

I went as far as inspecting the actual javascript function that the button is executing behind the scene and calling it manually using HtmlDocument.InvokeScript() but couldn't do that because the underlying function takes an argument of MouseEvent type (the click event actually) and I'm not sure how can I create that object in C#.

Another approach was to set focus to that particular button and then try SendKeys , but that won't work because the WebBrowser control is not visible. It is just an in-memory instance. To be more specific, the WebBrowser

EDIT

On a reader's request, here's the simple code that I'm using to find the element:

var MyButton = WB.Document.GetElementById("processfilelink");

processfilelink is an anchor tag ( <a href='#' ... > ) and I have confirmed that this element actually exists in the body of the document. The webpage uses jQuery's delegate feature to bind this anchor's click event to the target function. After locating the button, I simply call InvokeMember() like this:

MyButton.InvokeMember("click");

Note: I also see bindings for mousedown, mouseup and focus events in the page code. I expect all these events to automatically fire when one invokes click , but just to be sure I added InvokeMember calls for these events too. Results are no better.

From the comments:

... load this page in full IE browser, use F12 Tools to debug it and execute button.click() in JavaScript console. Does it work as expected this way?

So, you've tried that, and the result is:

... now that's interesting. It doesn't work! But clicking on the item by hand does work flawlessly. What's going on here?

I suspected that as MyButton.InvokeMember("click") doesn't work. Apparently, the page handles this click by other means than via onclick event. Most likely, it uses onmousedown or onmouseup events. Study the page's scripting logic to verify if that's the case, use F12 debugger and put some break points.

Updated , if it turns out the page indeed uses onmousedown / onmouseup , you'd need to make your WebBrowser visible and automate it by posting WM_LBUTTONDOWN :

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WindowsFormsApplication_22979038
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            this.webBrowser.DocumentText = "<a id='goLink' href='javascript:alert(\"Hello!\"),undefined'>Go</a><script></script>";

            this.webBrowser.DocumentCompleted += webBrowser_DocumentCompleted;
        }

        void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            var element = this.webBrowser.Document.GetElementById("goLink");
            element.Focus();
            var hwnd = GetFocus();
            if (!IsChild(this.webBrowser.Handle, hwnd))
                throw new ApplicationException("Unexpected focused window.");

            var rect = GetElementRect(element);
            IntPtr wParam = (IntPtr)MK_LBUTTON;
            IntPtr lParam = (IntPtr)(rect.Left | rect.Top << 16);
            PostMessage(hwnd, WM_LBUTTONDOWN, wParam, lParam);
            PostMessage(hwnd, WM_LBUTTONUP, wParam, lParam);
        }

        // get the element rect in window client area coordinates
        static Rectangle GetElementRect(HtmlElement element)
        {
            var rect = element.OffsetRectangle;
            int left = 0, top = 0;
            var parent = element;
            while (true)
            {
                parent = parent.OffsetParent;
                if (parent == null)
                    return new Rectangle(rect.X + left, rect.Y + top, rect.Width, rect.Height);
                var parentRect = parent.OffsetRectangle;
                left += parentRect.Left;
                top += parentRect.Top;
            }
        }

        // interop

        const int MK_LBUTTON = 0x0001;
        const int WM_LBUTTONDOWN = 0x0201;
        const int WM_LBUTTONUP = 0x0202;

        [StructLayout(LayoutKind.Sequential)]
        public struct POINT
        {
            public int x;
            public int y;
        }

        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        static extern int PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);

        [DllImport("User32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
        static extern IntPtr GetFocus();

        [DllImport("User32.dll", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto)]
        static extern bool IsChild(IntPtr hWndParent, IntPtr hWnd);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM