WebBrowser控件使用技巧分享

简介: 原文:WebBrowser控件使用技巧分享   在发布“淘宝登货员”时发现不少朋友对WebBrowser控件比较感兴趣,故在此分享一下使用心得。 首先分享一个WebBrowser的扩展类(此类所需的dll将在文章末尾提供下载),大家最好都使用这个类来替代.Net框架中的WebBrowser类,它提供了两个扩展功能: 1.屏蔽错误脚本提示。
原文: WebBrowser控件使用技巧分享

 

在发布“淘宝登货员”时发现不少朋友对WebBrowser控件比较感兴趣,故在此分享一下使用心得。

首先分享一个WebBrowser的扩展类(此类所需的dll将在文章末尾提供下载),大家最好都使用这个类来替代.Net框架中的WebBrowser类,它提供了两个扩展功能:

1.屏蔽错误脚本提示。修正了WebBrowser控件本身屏蔽错误不全的问题,由启明提出,原文:http://www.cnblogs.com/hobe/archive/2007/01/14/619906.html

2.扩展NewWindow事件。修正了WebBrowser控件本身的NewWindow事件不提供新窗口Url的问题,通过新增的BeforeNewWindow事件予以支持,由佳文转载并整理,原文:http://www.cnblogs.com/yjwgood/archive/2009/02/09/1386789.html

整合后的代码如下:

public class ExWebBrowser : System.Windows.Forms.WebBrowser

{

    private SHDocVw.IWebBrowser2 Iwb2;

 

    protected override void AttachInterfaces(object nativeActiveXObject)

    {

        Iwb2 = (SHDocVw.IWebBrowser2)nativeActiveXObject;

        Iwb2.Silent = true;

        base.AttachInterfaces(nativeActiveXObject);

    }

 

    protected override void DetachInterfaces()

    {

        Iwb2 = null;

        base.DetachInterfaces();

    }

 

    System.Windows.Forms.AxHost.ConnectionPointCookie cookie;

    WebBrowserExtendedEvents events;

 

    //This method will be called to give you a chance to create your own event sink

    protected override void CreateSink()

    {

        //MAKE SURE TO CALL THE BASE or the normal events won't fire

        base.CreateSink();

        events = new WebBrowserExtendedEvents(this);

        cookie = new System.Windows.Forms.AxHost.ConnectionPointCookie(this.ActiveXInstance, events, typeof(DWebBrowserEvents2));

    }

 

    protected override void DetachSink()

    {

        if (null != cookie)

        {

            cookie.Disconnect();

            cookie = null;

        }

        base.DetachSink();

    }

 

    //This new event will fire when the page is navigating

    public event EventHandler BeforeNavigate;

    /// <summary>

    /// 可用于替代原来的NewWindow事件,新增了事件的Url参数支持。

    /// </summary>

    [CategoryAttribute("操作"), DescriptionAttribute("经过扩展的NewWindow事件,使用继承后的WebBrowserExtendedNavigatingEventArgs类型参数实现Url参数支持")]

    public event EventHandler BeforeNewWindow;

 

    protected void OnBeforeNewWindow(string url, out bool cancel)

    {

        EventHandler h = BeforeNewWindow;

        WebBrowserExtendedNavigatingEventArgs args = new WebBrowserExtendedNavigatingEventArgs(url, null);

        if (null != h)

        {

            h(this, args);

        }

        cancel = args.Cancel;

    }

 

    protected void OnBeforeNavigate(string url, string frame, out bool cancel)

    {

        EventHandler h = BeforeNavigate;

        WebBrowserExtendedNavigatingEventArgs args = new WebBrowserExtendedNavigatingEventArgs(url, frame);

        if (null != h)

        {

            h(this, args);

        }

        //Pass the cancellation chosen back out to the events

        cancel = args.Cancel;

    }

 

    //This class will capture events from the WebBrowser

    class WebBrowserExtendedEvents : System.Runtime.InteropServices.StandardOleMarshalObject, DWebBrowserEvents2

    {

        ExWebBrowser _Browser;

        public WebBrowserExtendedEvents(ExWebBrowser browser) { _Browser = browser; }

 

        //Implement whichever events you wish

        public void BeforeNavigate2(object pDisp, ref object URL, ref object flags, ref object targetFrameName, ref object postData, ref object headers, ref bool cancel)

        {

            _Browser.OnBeforeNavigate((string)URL, (string)targetFrameName, out cancel);

        }

 

        public void NewWindow3(object pDisp, ref bool cancel, ref object flags, ref object URLContext, ref object URL)

        {

            _Browser.OnBeforeNewWindow((string)URL, out cancel);

        }

 

    }

 

    [System.Runtime.InteropServices.ComImport(), System.Runtime.InteropServices.Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D"),

    System.Runtime.InteropServices.InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIDispatch),

    System.Runtime.InteropServices.TypeLibType(System.Runtime.InteropServices.TypeLibTypeFlags.FHidden)]

    public interface DWebBrowserEvents2

    {

 

        [System.Runtime.InteropServices.DispId(250)]

        void BeforeNavigate2(

            [System.Runtime.InteropServices.In,

            System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.IDispatch)] object pDisp,

            [System.Runtime.InteropServices.In] ref object URL,

            [System.Runtime.InteropServices.In] ref object flags,

            [System.Runtime.InteropServices.In] ref object targetFrameName, [System.Runtime.InteropServices.In] ref object postData,

            [System.Runtime.InteropServices.In] ref object headers,

            [System.Runtime.InteropServices.In,

            System.Runtime.InteropServices.Out] ref bool cancel);

        [System.Runtime.InteropServices.DispId(273)]

        void NewWindow3(

            [System.Runtime.InteropServices.In,

            System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.IDispatch)] object pDisp,

            [System.Runtime.InteropServices.In, System.Runtime.InteropServices.Out] ref bool cancel,

            [System.Runtime.InteropServices.In] ref object flags,

            [System.Runtime.InteropServices.In] ref object URLContext,

            [System.Runtime.InteropServices.In] ref object URL);

    }

}

 

public class WebBrowserExtendedNavigatingEventArgs : CancelEventArgs

{

    private string _Url;

    public string Url

    {

        get { return _Url; }

    }

 

    private string _Frame;

    public string Frame

    {

        get { return _Frame; }

    }

 

    public WebBrowserExtendedNavigatingEventArgs(string url, string frame)

        : base()

    {

        _Url = url;

        _Frame = frame;

    }

}

技巧1:在当前窗口内打开目标为新窗口的超链接

通过上述的扩展类支持得以实现,增加BeforeNewWindow事件的处理函数以进行处理:

void webBrowser1_BeforeNewWindow(object sender, EventArgs e)

{

    WebBrowserExtendedNavigatingEventArgs eventArgs = e as WebBrowserExtendedNavigatingEventArgs;

    if (eventArgs.Url.ToLower() != "about:blank")

        webBrowser1.Navigate(eventArgs.Url);

    eventArgs.Cancel = true;

}

这种方法的弊病在于可能会错误地转向到网站的弹窗广告,为了规避此问题,可以强制取消一切弹出窗口,采取另一种方法实现当前窗口内打开新窗口超链接,增加DocumentCompleted事件的处理函数以进行处理:

void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)

{

    if (webBrowser1.ReadyState > WebBrowserReadyState.Interactive)

    {

        foreach (HtmlElement f in webBrowser1.Document.Links)

        {

            var s = f.GetAttribute("target");

            if (s != null && s.ToLower() == "_blank") f.SetAttribute("target", "_self");

        }

    }

}

此方法将遍历所有<a>元素,修改其目标为当前窗口,但是此方法又会引发新的问题,即如果页面中某些元素长时间都未加载完成时,此事件将迟迟不会被引发,也就是说用户必须要等到页面完完全全加载完毕之后才可能在当前窗口内打开新窗口超链接。

根据一些人的经验,DocumentCompleted事件会在每次加载网页的过程中触发两次,第一次触发时WebBrowser控件的ReadyState属性应为Interactive,第二次则为Complete,根据注释来看,Interactive应该是代表页面加载初步完成,已具有基本交互能力的状态,这时应当是理想的编辑状态,但我尝试将代码中的if (webBrowser1.ReadyState > WebBrowserReadyState.Interactive)修改为if (webBrowser1.ReadyState >= WebBrowserReadyState.Interactive),并没有什么明显效果,页面上的超链接还是要等待全部加载之后才会被修改。

为此我还尝试过在Navigated事件中进行处理,也不起作用。希望高人能对此给出完美的解决方案

技巧2:获取状态栏信息

增加StatusTextChanged事件处理函数进行处理:

void webBrowser1_StatusTextChanged(object sender, EventArgs e)

{

    label1.Text = webBrowser1.StatusText;

}

技巧3:页面转向后改变地址栏地址

Navigated事件处理函数中改变地址栏地址是最恰当的:

private void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)

{

    textBox1.Text = webBrowser1.Url.ToString();

}

技巧4:正确设置单选框的方法

建议使用执行单击事件的方式来设置单选框,而不是修改属性:

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

技巧5:正确设置联动型下拉列表的方法

比较常见的联动型多级下拉列表就是省/市县选择了,这种情况下直接设置选择项的属性不会触发联动,需要在最后执行触发事件函数才能正常工作:

foreach (HtmlElement f in s.GetElementsByTagName("option"))

{

    if (f.InnerText == "北京")

    {

        f.SetAttribute("selected", "selected");

    }

    else

    {

        f.SetAttribute("selected", "");

    }

}

s.RaiseEvent("onchange");

此方法来源于:http://topic.csdn.net/u/20070309/11/aef46651-a15a-4777-b832-e71b09a7b9e0.html

技巧6:使用延迟等待服务器交互

有时会遇到联动型下拉列表需要同服务器交互的情况,如果只在一个函数里连续进行设置,往往会失败,因为代码执行速度很快,这期间页面还没有从服务器得到并装载数据。

这时候应当通过使用Timer等方法设置延迟间隔,再进行更改,需注意的是,不应当使用Sleep方法停止当前线程的执行以求达到延迟目的,因为WebBrowser控件也处于当前线程内,Sleep会同时暂停WebBrowser控件的运作。

还有一点需要注意,就是如果程序内用到多个Timer的话,有可能引发不可预料的错乱,详情及解决办法可参看我的前一篇文章

尚未解决的问题

有一个问题一直困扰我,始终也没找到相关的资料:

我现在可以通过WebBrowser实现对各种Html元素的操控,唯独无法控制Html的上传控件,即:

<input type="file" size="50"/>

应当是出于安全原因,JS代码无法访问和设置此控件所选择的文件路径,这是符合情理的,但是WebBrowser中也没能找到相关的支持,这样就无法实现自动上传等功能,希望有高手能指出解决办法。

还有一个似乎是无解的问题,就是读取和操作页面内的框架页或内嵌页的问题,很多人发出疑问,但始终没找到解决方法,此方面最典型的应用就是自动点嵌入式广告功能了,而现在不但无法点击,甚至都无法获取框架页的代码等信息。

其他相关技术资料

ExtendedWebBrowser的再扩展:http://hi.baidu.com/tanjian/blog/item/d46b83021772a10f4afb511c.html

C#利用WebBrowser操作HTMLhttp://hi.baidu.com/lightrock/blog/item/c4a61d2bf6dde5fce7cd40fb.html

关于C#.netWebBrowser如何处理多框架结构页面下载完成问题:http://blog1.poco.cn/myBlogDetail-htx-id-381745-userid-7940008-pri--n-0.shtml

利用webBrowser获取框架内Html页面内容:http://www.cnblogs.com/tishifu/archive/2007/12/10/990071.html

WebBrowser控件的简单应用2http://www.cnblogs.com/dlwang2002/archive/2007/04/11/709078.html

WebBrowser控件应用:弹出新窗体和关闭窗口:http://www.cnblogs.com/dlwang2002/archive/2007/04/14/713499.html

.Net 2.0实例学习:WebBrowser页面与WinForm交互技巧:http://smalldust.cnblogs.com/archive/2006/03/08/345561.html

WebBrowser控件禁用超链接转向、脚本错误提示、默认右键菜单和快捷键:http://www.zu14.cn/2008/11/19/webbrowser/

 

下载Interop.SHDocVw.dll:http://cid-0612298d2255e149.skydrive.live.com/self.aspx/.Public/%e6%96%87%e6%a1%a3/Interop.SHDocVw.zip

下载本文的PDF版本: http://cid-0612298d2255e149.skydrive.live.com/self.aspx/.Public/%e6%96%87%e6%a1%a3/WebBrowser%e6%8e%a7%e4%bb%b6%e4%bd%bf%e7%94%a8%e6%8a%80%e5%b7%a7%e5%88%86%e4%ba%ab.pdf

 

目录
相关文章
|
网络协议 Java 测试技术
配置中心原理和选型:Disconf、Apollo、Spring Cloud Config 和 Nacos
学完注册中心,再看配置中心这块,感觉简单很多,因为很多知识原理是相辅相成的
9058 0
配置中心原理和选型:Disconf、Apollo、Spring Cloud Config 和 Nacos
|
3天前
|
人工智能 自然语言处理 JavaScript
2026年Windows+Ollama本地部署OpenClaw保姆级教程:本地AI Agent+阿里云上快速搭建
2026年OpenClaw凭借本地部署、私有化运行的特性,成为打造个人智能体的核心工具,而Ollama作为轻量级本地大模型管理工具,能让OpenClaw摆脱对云端大模型的依赖,实现**本地推理、数据不泄露、全流程私有化**的智能体验。本文基于Windows 11系统,从硬件环境准备、Ollama安装与模型定制、OpenClaw部署配置、技能扩展到常见问题排查,打造保姆级本地部署教程,同时补充阿里云OpenClaw(Clawdbot)快速部署步骤,兼顾本地私有化需求与云端7×24小时运行需求,文中所有代码命令均可直接复制执行,确保零基础用户也能快速搭建属于自己的本地智能体。
5063 26
|
10天前
|
存储 人工智能 负载均衡
阿里云OpenClaw多Agent实战宝典:从极速部署到AI团队搭建,一个人=一支高效军团
在AI自动化时代,单一Agent的“全能模式”早已无法满足复杂任务需求——记忆臃肿导致响应迟缓、上下文污染引发逻辑冲突、无关信息加载造成Token浪费,这些痛点让OpenClaw的潜力大打折扣。而多Agent架构的出现,彻底改变了这一现状:通过“单Gateway+多分身”模式,让一个Bot在不同场景下切换独立“大脑”,如同组建一支分工明确的AI团队,实现创意、写作、编码、数据分析等任务的高效协同。
4128 29
|
14天前
|
人工智能 自然语言处理 监控
OpenClaw skills重构量化交易逻辑:部署+AI全自动炒股指南(2026终极版)
2026年,AI Agent领域最震撼的突破来自OpenClaw(原Clawdbot)——这个能自主规划、执行任务的智能体,用50美元启动资金创造了48小时滚雪球至2980美元的奇迹,收益率高达5860%。其核心逻辑堪称教科书级:每10分钟扫描Polymarket近千个预测市场,借助Claude API深度推理,交叉验证NOAA天气数据、体育伤病报告、加密货币链上情绪等多维度信息,捕捉8%以上的定价偏差,再通过凯利准则将单仓位严格控制在总资金6%以内,实现低风险高频套利。
7600 66
|
4天前
|
人工智能 JSON JavaScript
手把手教你用 OpenClaw + 飞书,打造专属 AI 机器人
手把手教你用 OpenClaw(v2026.2.22-2)+ 飞书,10分钟零代码搭建专属AI机器人!内置飞书插件,无需额外安装;支持Claude等主流模型,命令行一键配置。告别复杂开发,像聊同事一样自然对话。
2007 6
手把手教你用 OpenClaw + 飞书,打造专属 AI 机器人
|
4天前
|
人工智能 运维 安全
OpenClaw极速部署:ZeroNews 远程管理OpenClaw Gateway Dashboard指南+常见错误解决
OpenClaw作为高性能AI智能体网关平台,其Gateway Dashboard是管理模型调用、渠道集成、技能插件的核心操作界面,但默认仅支持本地局域网访问。官方推荐的Tailscale、VPN等远程访问方案在国内网络环境中体验不佳,而ZeroNews凭借轻量化部署、专属域名映射、多重安全防护的特性,成为适配国内网络的最优远程管理解决方案。
1441 2
|
5天前
|
存储 人工智能 BI
2026年OpenClaw(Clawdbot)极简部署:接入小红书全自动运营,一个人=一支团队
2026年的小红书运营赛道,AI自动化工具已成为核心竞争力。OpenClaw(原Clawdbot)凭借“Skill插件化集成、全流程自动化、跨平台联动”的核心优势,彻底颠覆传统运营模式——从热点追踪、文案创作、封面设计到自动发布、账号互动,仅需一句自然语言指令,即可实现全链路闭环。而阿里云作为OpenClaw官方推荐的云端部署载体,2026年推出专属秒级部署方案,预装全套运行环境与小红书运营插件,让零基础用户也能10分钟完成部署,轻松拥有7×24小时在线的“专属运营团队”。
1599 6
|
9天前
|
人工智能 自然语言处理 安全
2026年OpenClaw Skills安装指南:Top20必装清单+阿里云上部署实操(附代码命令)
OpenClaw(原Clawdbot)的强大之处,不仅在于其开源免费的AI执行引擎核心,更在于其庞大的Skills生态——截至2026年2月,官方技能市场ClawHub已收录1700+各类技能插件,覆盖办公自动化、智能交互、生活服务等全场景。但对新手而言,面对海量技能往往无从下手,盲目安装不仅导致功能冗余,还可能引发权限冲突与安全风险。
2351 9
|
1月前
|
人工智能 自然语言处理 Shell
🦞 如何在 OpenClaw (Clawdbot/Moltbot) 配置阿里云百炼 API
本教程指导用户在开源AI助手Clawdbot中集成阿里云百炼API,涵盖安装Clawdbot、获取百炼API Key、配置环境变量与模型参数、验证调用等完整流程,支持Qwen3-max thinking (Qwen3-Max-2026-01-23)/Qwen - Plus等主流模型,助力本地化智能自动化。
47021 160
🦞 如何在 OpenClaw (Clawdbot/Moltbot) 配置阿里云百炼 API

热门文章

最新文章