zoukankan      html  css  js  c++  java
  • C# BHO 上海

    BHO(Browser Help Objects)是实现了特定接口(IObjectWithSite)的COM组件。开发好的BHO插件除了要在注册表中注册为COM Server外,还必须将它的CLSID在HKLMSOFTWARE…Browser Helper Objects下注册为子键。每当浏览器[1]启动时,首先会在上述注册表位置查看是否有注册的BHO CLSID,如果有则分别创建一个实例,并对BHO实例进行初始化。BHO实例运行在浏览器的地址空间内,能对可访问的对象(如窗口、模块等等)执行任何操作,且因为它依附于浏览器的主窗口,所以其生命周期与浏览器实例的生命周期一致。下图演示了BHO的创建过程:


    下面就来介绍一下如何开发BHO插件。首先创建一个C#项目,类型为Class Library。然后将Class1.cs改名为IObjectWithSite.cs,还要给IObjectWithSite添加两个功能:GetSite和SetSite。


    Public Interface Iobjectwithsite
    {
        [Preservesig]
        Int Setsite([Marshalas(Unmanagedtype.Iunknown)]Object Site);
        [Preservesig]
        Int Getsite(Ref Guid Guid, Out Intptr Ppvsite);
    }

    添加一个cs文件UrlTrack.cs,并且实现IObjectWithSite接口。使用BHO还需要添加两个引用SHDocVw.dll和MSHTML.dll,可以在WindowsSystem32目录下找到。


    在IObjectWithSite.cs中,还需要为我们的程序指出IE的GUID,使得它可以挂接(attach)到IE上
    [
    ComVisible(true),
    InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
    Guid("FC4801A3-2BA9-11CF-A229-00AA003D7352")
    ]

    另外,还需要给BHO程序分配一个GUID,这个可以通过System.Guid.NewGuid()方法得到
    [
    ComVisible(true),
    Guid("e90da13b-117a-4178-8111-0f712da09ff9"),
    ClassInterface(ClassInterfaceType.None)
    ]

    在UrlTrack.cs中,我们还需要写两个方法用来DLL注册和移除注册


    public static string BHOKEYNAME = @"SOFTWARE…Browser Helper Objects";

    [ComRegisterFunction]
    public static void RegisterBHO(Type type)
    {
        RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(BHO_KEY_NAME, true);
        if (registryKey == null)
        {
            registryKey = Registry.LocalMachine.CreateSubKey(BHO_KEY_NAME);
        }

        string guid = type.GUID.ToString("B");
        RegistryKey bhoKey = registryKey.OpenSubKey(guid, true);
        if (bhoKey == null)
        {
            bhoKey = registryKey.CreateSubKey(guid);
        }
        // NoExplorer: dword = 1 prevents the BHO to be loaded by Explorer.exe
        bhoKey.SetValue("NoExplorer", 1);
        bhoKey.Close();

        registryKey.Close();
    }

    [ComUnregisterFunction]
    public static void UnregisterBHO(Type type)
    {
        RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(BHO_KEY_NAME, true);
        string guid = type.GUID.ToString("B");

        if (registryKey != null)
            registryKey.DeleteSubKey(guid, false);
    }

    接下来就是实现具体的统计功能了。考虑一下,当输入网址后,我们需要记录下网址以及当前的时间;当在同一浏览窗口中切换网址时,不仅需要记录下网址和当前时间,还要设置前一个浏览记录的结束时间;并且在关闭浏览器时,也要记下结束时间。所以在SetSite中需要挂载 NavigateComplete2和OnQuit事件。


    private void NavigateComplete2(object pDisp, ref object URL)
    {
        string url = URL as string;
        if (url.IndexOf("about:blank") >= 0)
        {
            return;
        }
        if (visitHists.Count > 0)
        {
            VisitHist currentHist = visitHists[visitHists.Count - 1];
            if (currentHist.VisitUrl != url)
            {
                currentHist.EndTime = System.DateTime.Now;
            }
            else
            {
                return;
            }
        }
        VisitHist newHist = new VisitHist();
        newHist.StartTime = System.DateTime.Now;
        newHist.VisitUrl = url;
        visitHists.Add(newHist);
    }

    private void OnQuit()
    {
        if (visitHists.Count > 0)
        {
            VisitHist currentHist = visitHists[visitHists.Count - 1];
            currentHist.EndTime = System.DateTime.Now;
        }

        // 输出统计记录
        …
    }

    开始编译,然后就可以在bin目录下找到项目的dll文件了。在Console中使用regasm /codebase "UrlTrack.dll"注册dll。打开注册表,在HKLMSOFTWARE…Browser Helper Object可以看到多出了一个子项{E90DA13B-117A-4178-8111-0F712DA09FF9}。

    需要注意的是,需要将AssemblyInfo.cs文件中的ComVisible属性设为true,否则在注册BHO时会得到这样的信息:
    RegAsm : warning RA0000 : No types were registered.

  • 相关阅读:
    Angular--ui-router的使用
    一个简单的俄罗斯方块游戏脚本
    c中使用gets() 提示warning: this program uses gets(), which is unsafe.
    最短路径之Floyd算法
    动态规划求最大子序列
    Mac上编译C++报错
    nginx location匹配规则
    nginx配置入门
    拿什么守护你的Node.JS进程: Node出错崩溃了怎么办? foreverjs, 文摘随笔
    ASP.NET 上的 Async/Await 简介
  • 原文地址:https://www.cnblogs.com/luozhai714/p/2161813.html
Copyright © 2011-2022 走看看