C# WebBrowser控件无法导航到另一个页面。

5
我有一个控制台应用程序,我在其中定义了一个WebBrowser。 首先,我导航到一个页面并填写登录表单,然后调用提交按钮进行登录。
之后,我想使用同一WebBrowser转到同一站点的另一个页面,但它没有导航到该页面。相反,它导航到登录后重定向的页面。
以下是我的代码以进行澄清;此代码给出了www.websiteiwanttogo.com/default.aspx的源代码,而不是product.aspx。这里有什么问题?
static WebBrowser wb = new WebBrowser();

    [STAThread]
    static void Main(string[] args)
    {
        wb.AllowNavigation = true;
        wb.Navigate("https://www.thewebsiteiwanttogo.com/login.aspx");
        wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(wb_DocumentCompleted);
        Application.Run();


    }

    static void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        if (wb.Url.ToString().IndexOf("login.aspx") > -1)
        {
            wb.Document.GetElementById("txtnumber").SetAttribute("value", "000001");
            wb.Document.GetElementById("txtUserName").SetAttribute("value", "myusername");
            wb.Document.GetElementById("txtPassword").SetAttribute("value", "mypassword");
            wb.Document.GetElementById("btnLogin").InvokeMember("click");


        }
        else
        {
            //wb.Document.Body  you are logged in do whatever you want here.
            wb.Navigate("https://www.thewebsiteiwanttogo.com/product.aspx");

            Console.WriteLine(wb.DocumentText);
            Console.ReadLine();
            Application.Exit();

        }
    }

感谢您提出这样一个精彩的问题。在看到这个问题和答案后,我可以得出一些收获。 - NANDAKUMAR THANGAVELU
1个回答

6
有许多不同的方法可以实现此功能。然而,我的猜测是:
1. 要么导航到下一页的调用发生得太快了,要么 2. 登录后Document.Completed事件没有正确触发(如果目标文档包含动态脚本,则这种情况很常见)
我已经完成了许多网页自动化(从一个链接导航到另一个链接,然后执行一些操作,然后导航到另一个链接等),您应该考虑使用异步进程。原则上,在处理webBrowser对象时,使用异步进程可能总是最好的选择,因为有许多情况需要在执行其他功能时运行一个进程。
不详细介绍,请查看此问题的答案并学习代码:Flow of WebBrowser Navigate and InvokeScript 但是,在尝试该实现之前,您可以尝试在尝试导航到页面之前添加异步等待。(异步等待类似于Thread.Sleep(),但实际上不会停止页面的加载,即“线程”)。

你以前从未听说过异步进程吗?请查看MSDN上的这个教程

首先试试这个:

static void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    if (wb.Url.ToString().IndexOf("login.aspx") > -1)
    {
        wb.Document.GetElementById("txtnumber").SetAttribute("value", "000001");
        wb.Document.GetElementById("txtUserName").SetAttribute("value", "myusername");
        wb.Document.GetElementById("txtPassword").SetAttribute("value", "mypassword");
        wb.Document.GetElementById("btnLogin").InvokeMember("click");


    }
    else
    {
        //wb.Document.Body  you are logged in do whatever you want here.
        await Task.Delay(1000); //wait for 1 second just to let the WB catch up
        wb.Navigate("https://www.thewebsiteiwanttogo.com/product.aspx");

        Console.WriteLine(wb.DocumentText);
        Console.ReadLine();
        Application.Exit();

    }
}

如果这不起作用,请考虑上面的链接,并尝试使用异步进程实现更强大的导航序列。
如果仍然不行,并且您想要帮助浏览或等待动态页面加载,请尝试阅读此文章:如何使用.NET的WebBrowser或mshtml.HTMLDocument动态生成HTML代码?我多次使用了这个代码技术,效果非常好。
希望这些方法中的一个能够帮到您!让我知道,我可以帮您生成一些更具体的代码片段。
编辑:

仔细看后,我猜测Console.ReadLine()会冻结wb.Navigate("https://www.thewebsiteiwanttogo.com/product.aspx");的导航,因为它不会立即发生。您可能需要在Document.Completed处理程序中添加另一个if语句,以允许wb.Navigate("https://www.thewebsiteiwanttogo.com/product.aspx");完成导航后再尝试抓取wb.DocumentText。例如:

static void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    if (wb.Url.ToString().IndexOf("login.aspx") > -1)
    {
        wb.Document.GetElementById("txtnumber").SetAttribute("value", "000001");
        wb.Document.GetElementById("txtUserName").SetAttribute("value", "myusername");
        wb.Document.GetElementById("txtPassword").SetAttribute("value", "mypassword");
        wb.Document.GetElementById("btnLogin").InvokeMember("click");
    }
    else if(wb.Url.ToString().IndexOf("product.aspx") > -1)
    {
        Console.WriteLine(wb.DocumentText);
        Console.ReadLine();
        Application.Exit();
    }
    else
    {
        //wb.Document.Body  you are logged in do whatever you want here.
        await Task.Delay(1000); //wait for 1 second just to let the WB catch up
        wb.Navigate("https://www.thewebsiteiwanttogo.com/product.aspx");
    }
}

谢谢你的回答,Ben!我会尝试你在编辑后添加的代码示例,但似乎我必须升级到VS2012才能使用它,因为我无法在2010中使用"await",Microsoft.Bcl.Async和Async CTP也都不起作用。我会在应用你的解决方案后进行编辑。 - ismail senonder
我会先尝试不使用 await,看看是否可行。如果不行,你肯定要使用异步方法。 - Ben Holland
是的,你是对的。没有使用 await 命令也可以工作。但是它会出现一些脚本错误,并询问我是否要继续工作。如果我想让程序继续运行,就必须点击“是”。我能自动化这个过程吗? - ismail senonder
2
好的,我解决了。我按照这个问题中的建议禁用了脚本错误。我将把你的答案标记为解决方案。非常感谢! - ismail senonder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接