IE浏览器插件开发

前言

最近需要开发一个新的项目,对接客户的浏览器,拦截他的登录信息,但是只能使用IE浏览器,所以就准备开发一款IE插件。但是网上对chrome的开发教程比较多,IE的教程很少,所以我把我的开发过程记录下来,希望能够给需要的同学一些帮助。这里我们使用的开发语言是C#

Ie的插件有以下几种方式:

  • ActiveX:这种必须在网页内嵌入object对象,本身就已经存在于网页内才能使用,如果网站是自己开发的,可以使用这种方式。

  • BHO:全名浏览器辅助对象,这个是编写独立运行的扩展,和chrome的扩展差不多。

  • 注册表:这种方式可以绑定脚本到IE的右键菜单里,像迅雷或旋风在IE右键里加的“用**下载”就是这种方式

先上效果图:

文件目录结构:

一、开发代码

创建一个包类型的项目,继承Com类实现自己的业务代码,这里省略具体的代码,只需要关注步骤就行

  • 编写代码

    using System;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Runtime.InteropServices.Expando;
    using Microsoft.Win32;
    using SHDocVw;
    using MSHTML;
    namespace TrandeIeExtension
    {
      [ComVisible(true), InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
       Guid("FC4801A3-2BA9-11CF-A229-00AA003D7352")]
      public interface IObjectWithSite
      {
          [PreserveSig]
          int SetSite([MarshalAs(UnmanagedType.IUnknown)] object site);
    
          [PreserveSig]
          int GetSite(ref Guid guid, out IntPtr ppvSite);
      }
    
      public class TradeIeExtension : IObjectWithSite
      {
          public const string BHO_REGISTRY_KEY_NAME =
              "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Browser Helper Objects";
          private WebBrowser webBrowser;
    
          public int SetSite(object site){
              // 如果网页为空卸载委托事件
              if (site == null){
                  this.webBrowser.DocumentComplete -= this.OnDocumentComplete;
                  this.webBrowser                  =  null;
              }
              // 网页不为空挂载委托事件
              else{
                  webBrowser                  =  (WebBrowser) site;
                  webBrowser.DocumentComplete += this.OnDocumentComplete;
              }
              return 0;
          }
    
          public void OnDocumentComplete(object pDisp, ref object URL){
              HTMLDocument document = (HTMLDocument) this.webBrowser.Document;
              HTMLHeadElement head = (HTMLHeadElement) ((IHTMLElementCollection) document.all.tags("head")).item(null, 0);
              IHTMLScriptElement scriptObject = (IHTMLScriptElement) document.createElement("script");
              scriptObject.type = @"text/javascript";
              scriptObject.text = "alert(1)";
              head.appendChild((IHTMLDOMNode) scriptObject);
          }
    
          public int GetSite(ref Guid guid, out IntPtr ppvSite){
              IntPtr punk = Marshal.GetIUnknownForObject(this.webBrowser);
              int    hr   = Marshal.QueryInterface(punk, ref guid, out ppvSite);
              Marshal.Release(punk);
              return hr;
          }
    
          [ComRegisterFunction]
          public static void RegisterBHO(Type type){
              RegistryKey registryKey =
                  Registry.LocalMachine.OpenSubKey(BHO_REGISTRY_KEY_NAME, true);
              if (registryKey == null)
                  registryKey = Registry.LocalMachine.CreateSubKey(
                      BHO_REGISTRY_KEY_NAME);
              string      guid   = type.GUID.ToString("B");
              RegistryKey ourKey = registryKey.OpenSubKey(guid);
              if (ourKey == null){
                  ourKey = registryKey.CreateSubKey(guid);
              }
              ourKey.SetValue("NoExplorer", 1, RegistryValueKind.DWord);
              registryKey.Close();
              ourKey.Close();
          }
    
          [ComUnregisterFunction]
          public static void UnregisterBHO(Type type){
              RegistryKey registryKey =
                  Registry.LocalMachine.OpenSubKey(BHO_REGISTRY_KEY_NAME, true);
              string guid = type.GUID.ToString("B");
              if (registryKey != null)
                  registryKey.DeleteSubKey(guid, false);
          }
      }
    }
  • 编译dll

编译成dll,打开AssemblyInfo.cs中的Com可见,这个很重要,否则后面不能注册

[assembly: ComVisible(true)]

导入的系统依赖,比如SHDocVw,MSHTML请设置为编译时复制,否则插件可能不会执行。

二、强签名

生成的dll默认没有签名,系统认为是不安全的,我们要手动签名,主要会用到ilasm.exe和ildasm.exe这两个工具

  • Visual Studio

如果你使用的visual studio那么你可以直接在开始菜单打开Developer Command Prompt for VS xxxx控制台,就可以使用这两个工具

  • 系统自带

如果你没有visual studio环境,那可以使用系统自带的这两款工具,所在目录:

ildasm:C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\ildasm.exe
ilasm:C:\Windows\Microsoft.NET\Framework\v4.0.30319\ilasm.exe

  • 签名步骤

    这里使用的visual studio控制台,假设我们的dll文件叫main.dll

// 创建snk文件,名字自取
sn -k /your/path/main.snk

// 创建.il文件,请用绝对路径,名字自取
ildasm \your\path\main.dll /out:\your\path\main.il

// 使用snk签名dll并生成新dll,mainEx.dll是签名后新生成的dll名字
ilasm your\path\main.il /res:your\path\main.res /dll /key:your\path\main.snk /out:your\path\mainEx.dll

// 检查一下生成的新dll是否可用
sn -vf mainEx.dll

最终命令行会输出以下内容,表示签名成功

Resolving local member refs: 0 -> 0 defs, 0 refs, 0 unresolved
Writing PE file
Signing file with strong name
Operation completed successfully

三、注册组件

会使用到Regasm.exe这个工具

Regasm是系统自带比较老的Com注册工具,请进入它的目录再使用,所在目录径:

regasm:C:\Windows\Microsoft.NET\Framework\v4.0.30319

执行注册命令

Regasm /codebase your\path\mainEx.dll /u
Regasm /codebase your\path\mainEx.dll

命令行会输出以下内容,表示注册成功

Microsoft .NET Framework 程序集注册实用工具版本 4.7.3190.0
(适用于 Microsoft .NET Framework 版本 4.7.3190.0)
版权所有 (C) Microsoft Corporation。保留所有权利。

成功注册了类型

四、调试

打开IE浏览器,会提示是否加载新插件,点确定。随便访问一个网页,如果成功执行了我们的代码,说明插件运行成功

本作品采用《CC 协议》,转载必须注明作者和本文链接
失色天空
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 2

你好,我最近也是在做ie 插件,能否将代码分享下 614258364@qq.com,或者加微信一起探讨下, :pray:

2年前 评论
失色天空 (楼主) 2年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!