简体   繁体   中英

Programmatic button click in C# WebBrowser control

The documentation for the webbrowser in WinForms specifies you can invoke events like this:

webBrowser1.Document.GetElementById("signin").InvokeMember("click");

..but it doesn't work for me. I tried a hack:

HtmlElement element = webBrowser1.Document.CreateElement("script");
element.InnerText = "function SubmitForm() { document.getElementById('signin').click(); }";
webBrowser1.Document.Forms[0].AppendChild(element);
webBrowser1.Document.InvokeScript("SubmitForm");

..which didn't work either. However, another hack:

HtmlElement element = webBrowser1.Document.CreateElement("script");
element.InnerText = "function SubmitForm() { alert('Click me!'); 
    document.getElementById('signin').click(); }";
webBrowser1.Document.Forms[0].AppendChild(element);
webBrowser1.Document.InvokeScript("SubmitForm");

..worked perfectly. Except there is user intervention to click the alert box, which I don't want. Is this some kind of race condition? The code is executed in webBrowser1_DocumentCompleted so it should be fine. If you have a way to successfully trigger the event, please do tell.

@Jimi here's the code you requested:

private void Form1_Load(object sender, EventArgs e)
{
    string targetUrl = "https://banking.westpac.com.au/wbc/banking/handler?TAM_OP=login&URL=%2Fsecure%2Fbanking%2Foverview%2Fdashboard";
    webBrowser1.Navigate(targetUrl);
}

private void webBrowser1_DocumentCompleted_1(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    webBrowser1.DocumentCompleted -= webBrowser1_DocumentCompleted_1;
    webBrowser1.DocumentCompleted += webBrowser1_DocumentCompleted_2;

    webBrowser1.Document.GetElementById("fakeusername").InnerText = "andy";
    webBrowser1.Document.GetElementById("password").InnerText = "password";
    //webBrowser1.Document.GetElementById("signin").InvokeMember("click");

    HtmlElement element = webBrowser1.Document.CreateElement("script");
    element.InnerText = "function SubmitForm() { setTimeout(function() { document.getElementById('signin').click(); }, 5000); }";
    webBrowser1.Document.Forms[0].AppendChild(element);
    webBrowser1.Document.InvokeScript("SubmitForm");
}

The alert makes it work (so does setTimeout). It seems like the document is not really completed, but the browser thinks it is. Could JS on the page do that?

Based on your workarounds, I guess that it might be due to document not loaded yet, when you trying to execute code. In order to assure the page is loaded, you can subscribe to DocumentCompleted event and there execute your action. This worked for me:

public Form1()
{
    InitializeComponent();

    webBrowser1.DocumentCompleted += WebBrowser1_DocumentCompleted;
    string curDir = Directory.GetCurrentDirectory();
    webBrowser1.Navigate($"file://{curDir}/test.html");
}

private void WebBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    webBrowser1.Document.GetElementById("btn").InvokeMember("onclick");
}

Another issue I can see, you are using click member, since I am not sure what the element is (maybe a button ?), then try invoking onclick , like I did in the provided code.

Such snippet worked for me as well:

public Form1()
{
    InitializeComponent();

    webBrowser1.DocumentCompleted += WebBrowser1_DocumentCompleted;
    webBrowser1.Navigate(@"https://banking.westpac.com.au/wbc/banking/handler?TAM_OP=login&URL=%2Fsecure%2Fbanking%2Foverview%2Fdashboard");
}

private void WebBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    webBrowser1.Document.GetElementById("signin").InvokeMember("click");
}

My theory turned out to be correct, I finally found an answer:

StackOverflow: https://stackoverflow.com/questions/23680817/webbrowser-documentcompleted-is-useless-in-my-case

webBrowser1.Navigate(@"somesite.com");
while (WebBrowser1.ReadyState != WebBrowserReadyState.Complete)
{
    txtLoad.Text = WebBrowser1.ReadyState.ToString();
    Application.DoEvents();
    System.Threading.Thread.Sleep(1);
}
webBrowser1.Document.GetElementById("gwt-uid-126").InvokeMember("click");

Seems that the completed event doesn't wait for all scripts to stop executing.

Thanks all of you for your contributions.

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