如何开始开发Internet Explorer扩展?

| 这里有没有人有/可以开发可以共享其知识的IE扩展的经验?这将包括代码示例,或指向好的示例的链接,或有关过程的文档,或任何内容。 我真的很想这样做,但是我却遇到了糟糕的文档,糟糕的代码/示例代码/缺少它。您可以提供的任何帮助/资源将不胜感激。 具体来说,我想先介绍如何从IE扩展中访问/操作DOM。 编辑,更多详细信息: 理想情况下,我想植入一个工具栏按钮,单击该工具栏按钮时,会弹出一个包含指向外部站点的链接的菜单。我还想访问DOM并根据某些条件在页面上植入JavaScript。 在IE扩展中保留信息的最佳方法是什么?在Firefox / Chrome /大多数现代浏览器中,您都使用
window.localStorage
,但显然对于IE8 / IE7,这不是一个选择。也许是SQLite数据库或类似的?可以假设将.NET 4.0安装在用户的计算机上吗? 我不想使用Spice IE,因为我也想构建一个与IE9兼容的。我也向这个问题添加了C ++标记,因为如果最好在C ++中构建一个,则可以这样做。     
已邀请:
[更新]我正在更新此答案,以用于带有Visual Studio 2017社区的Windows 10 x64中的Internet Explorer 11。 此答案的先前版本(对于Internet Explorer 8,在Windows 7 x64和Visual Studio 2010中)在此答案的底部。 创建有效的Internet Explorer 11加载项 我正在使用Visual Studio 2017社区,C#、. Net Framework 4.6.1,因此其中一些步骤可能对您略有不同。 您需要以管理员身份打开Visual Studio来构建解决方案,以便构建后脚本可以注册BHO(需要注册表访问)。 首先创建一个类库。 我叫我InternetExplorerExtension。 将这些引用添加到项目中: Interop.SHDocVw:“ COM”选项卡/搜索“ 1” Microsoft.mshtml:“程序集”选项卡/搜索“ 2” 注意:尽管可以在“添加引用”窗口中找到MSHTML,但仍未在我的系统中注册它。这在构建时导致错误:   找不到类型库“ MSHTML”的包装程序集 该修补程序可以在http://techninotes.blogspot.com/2016/08/fixing-cannot-find-wrapper-assembly-for.html上找到 或者,您可以运行以下批处理脚本:
\"%ProgramFiles(x86)%\\Microsoft Visual Studio\\2017\\Community\\Common7\\Tools\\VsDevCmd.bat\"
cd \"%ProgramFiles(x86)%\\Microsoft Visual Studio\\2017\\Community\\Common7\\IDE\\PublicAssemblies\"
regasm Microsoft.mshtml.dll
gacutil /i Microsoft.mshtml.dll
创建以下文件: IEAddon.cs
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Microsoft.Win32;
using mshtml;
using SHDocVw;

namespace InternetExplorerExtension
{
    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.None)]
    [Guid(\"D40C654D-7C51-4EB3-95B2-1E23905C2A2D\")]
    [ProgId(\"MyBHO.WordHighlighter\")]
    public class WordHighlighterBHO : IObjectWithSite, IOleCommandTarget
    {
        const string DefaultTextToHighlight = \"browser\";

        IWebBrowser2 browser;
        private object site;

        #region Highlight Text
        void OnDocumentComplete(object pDisp, ref object URL)
        {
            try
            {
                // @Eric Stob: Thanks for this hint!
                // This was used to prevent this method being executed more than once in IE8... but now it seems to not work anymore.
                //if (pDisp != this.site)
                //    return;

                var document2 = browser.Document as IHTMLDocument2;
                var document3 = browser.Document as IHTMLDocument3;

                var window = document2.parentWindow;
                window.execScript(@\"function FncAddedByAddon() { alert(\'Message added by addon.\'); }\");

                Queue<IHTMLDOMNode> queue = new Queue<IHTMLDOMNode>();
                foreach (IHTMLDOMNode eachChild in document3.childNodes)
                    queue.Enqueue(eachChild);

                while (queue.Count > 0)
                {
                    // replacing desired text with a highlighted version of it
                    var domNode = queue.Dequeue();

                    var textNode = domNode as IHTMLDOMTextNode;
                    if (textNode != null)
                    {
                        if (textNode.data.Contains(TextToHighlight))
                        {
                            var newText = textNode.data.Replace(TextToHighlight, \"<span style=\'background-color: yellow; cursor: hand;\' onclick=\'javascript:FncAddedByAddon()\' title=\'Click to open script based alert window.\'>\" + TextToHighlight + \"</span>\");
                            var newNode = document2.createElement(\"span\");
                            newNode.innerHTML = newText;
                            domNode.replaceNode((IHTMLDOMNode)newNode);
                        }
                    }
                    else
                    {
                        // adding children to collection
                        var x = (IHTMLDOMChildrenCollection)(domNode.childNodes);
                        foreach (IHTMLDOMNode eachChild in x)
                        {
                            if (eachChild is mshtml.IHTMLScriptElement)
                                continue;
                            if (eachChild is mshtml.IHTMLStyleElement)
                                continue;

                            queue.Enqueue(eachChild);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        #endregion
        #region Load and Save Data
        static string TextToHighlight = DefaultTextToHighlight;
        public static string RegData = \"Software\\\\MyIEExtension\";

        [DllImport(\"ieframe.dll\")]
        public static extern int IEGetWriteableHKCU(ref IntPtr phKey);

        private static void SaveOptions()
        {
            // In IE 7,8,9,(desktop)10 tabs run in Protected Mode
            // which prohibits writes to HKLM, HKCU.
            // Must ask IE for \"Writable\" registry section pointer
            // which will be something like HKU/S-1-7***/Software/AppDataLow/
            // In \"metro\" IE 10 mode, tabs run in \"Enhanced Protected Mode\"
            // where BHOs are not allowed to run, except in edge cases.
            // see http://blogs.msdn.com/b/ieinternals/archive/2012/03/23/understanding-ie10-enhanced-protected-mode-network-security-addons-cookies-metro-desktop.aspx
            IntPtr phKey = new IntPtr();
            var answer = IEGetWriteableHKCU(ref phKey);
            RegistryKey writeable_registry = RegistryKey.FromHandle(
                new Microsoft.Win32.SafeHandles.SafeRegistryHandle(phKey, true)
            );
            RegistryKey registryKey = writeable_registry.OpenSubKey(RegData, true);

            if (registryKey == null)
                registryKey = writeable_registry.CreateSubKey(RegData);
            registryKey.SetValue(\"Data\", TextToHighlight);

            writeable_registry.Close();
        }
        private static void LoadOptions()
        {
            // In IE 7,8,9,(desktop)10 tabs run in Protected Mode
            // which prohibits writes to HKLM, HKCU.
            // Must ask IE for \"Writable\" registry section pointer
            // which will be something like HKU/S-1-7***/Software/AppDataLow/
            // In \"metro\" IE 10 mode, tabs run in \"Enhanced Protected Mode\"
            // where BHOs are not allowed to run, except in edge cases.
            // see http://blogs.msdn.com/b/ieinternals/archive/2012/03/23/understanding-ie10-enhanced-protected-mode-network-security-addons-cookies-metro-desktop.aspx
            IntPtr phKey = new IntPtr();
            var answer = IEGetWriteableHKCU(ref phKey);
            RegistryKey writeable_registry = RegistryKey.FromHandle(
                new Microsoft.Win32.SafeHandles.SafeRegistryHandle(phKey, true)
            );
            RegistryKey registryKey = writeable_registry.OpenSubKey(RegData, true);

            if (registryKey == null)
                registryKey = writeable_registry.CreateSubKey(RegData);
            registryKey.SetValue(\"Data\", TextToHighlight);

            if (registryKey == null)
            {
                TextToHighlight = DefaultTextToHighlight;
            }
            else
            {
                TextToHighlight = (string)registryKey.GetValue(\"Data\");
            }
            writeable_registry.Close();
        }
        #endregion

        [Guid(\"6D5140C1-7436-11CE-8034-00AA006009FA\")]
        [InterfaceType(1)]
        public interface IServiceProvider
        {
            int QueryService(ref Guid guidService, ref Guid riid, out IntPtr ppvObject);
        }

        #region Implementation of IObjectWithSite
        int IObjectWithSite.SetSite(object site)
        {
            this.site = site;

            if (site != null)
            {
                LoadOptions();

                var serviceProv = (IServiceProvider)this.site;
                var guidIWebBrowserApp = Marshal.GenerateGuidForType(typeof(IWebBrowserApp)); // new Guid(\"0002DF05-0000-0000-C000-000000000046\");
                var guidIWebBrowser2 = Marshal.GenerateGuidForType(typeof(IWebBrowser2)); // new Guid(\"D30C1661-CDAF-11D0-8A3E-00C04FC9E26E\");
                IntPtr intPtr;
                serviceProv.QueryService(ref guidIWebBrowserApp, ref guidIWebBrowser2, out intPtr);

                browser = (IWebBrowser2)Marshal.GetObjectForIUnknown(intPtr);

                ((DWebBrowserEvents2_Event)browser).DocumentComplete +=
                    new DWebBrowserEvents2_DocumentCompleteEventHandler(this.OnDocumentComplete);
            }
            else
            {
                ((DWebBrowserEvents2_Event)browser).DocumentComplete -=
                    new DWebBrowserEvents2_DocumentCompleteEventHandler(this.OnDocumentComplete);
                browser = null;
            }
            return 0;
        }
        int IObjectWithSite.GetSite(ref Guid guid, out IntPtr ppvSite)
        {
            IntPtr punk = Marshal.GetIUnknownForObject(browser);
            int hr = Marshal.QueryInterface(punk, ref guid, out ppvSite);
            Marshal.Release(punk);
            return hr;
        }
        #endregion
        #region Implementation of IOleCommandTarget
        int IOleCommandTarget.QueryStatus(IntPtr pguidCmdGroup, uint cCmds, ref OLECMD prgCmds, IntPtr pCmdText)
        {
            return 0;
        }
        int IOleCommandTarget.Exec(IntPtr pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            try
            {
                // Accessing the document from the command-bar.
                var document = browser.Document as IHTMLDocument2;
                var window = document.parentWindow;
                var result = window.execScript(@\"alert(\'You will now be allowed to configure the text to highlight...\');\");

                var form = new HighlighterOptionsForm();
                form.InputText = TextToHighlight;
                if (form.ShowDialog() != DialogResult.Cancel)
                {
                    TextToHighlight = form.InputText;
                    SaveOptions();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

            return 0;
        }
        #endregion

        #region Registering with regasm
        public static string RegBHO = \"Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Explorer\\\\Browser Helper Objects\";
        public static string RegCmd = \"Software\\\\Microsoft\\\\Internet Explorer\\\\Extensions\";

        [ComRegisterFunction]
        public static void RegisterBHO(Type type)
        {
            string guid = type.GUID.ToString(\"B\");

            // BHO
            {
                RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(RegBHO, true);
                if (registryKey == null)
                    registryKey = Registry.LocalMachine.CreateSubKey(RegBHO);
                RegistryKey key = registryKey.OpenSubKey(guid);
                if (key == null)
                    key = registryKey.CreateSubKey(guid);
                key.SetValue(\"Alright\", 1);
                registryKey.Close();
                key.Close();
            }

            // Command
            {
                RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(RegCmd, true);
                if (registryKey == null)
                    registryKey = Registry.LocalMachine.CreateSubKey(RegCmd);
                RegistryKey key = registryKey.OpenSubKey(guid);
                if (key == null)
                    key = registryKey.CreateSubKey(guid);
                key.SetValue(\"ButtonText\", \"Highlighter options\");
                key.SetValue(\"CLSID\", \"{1FBA04EE-3024-11d2-8F1F-0000F87ABD16}\");
                key.SetValue(\"ClsidExtension\", guid);
                key.SetValue(\"Icon\", \"\");
                key.SetValue(\"HotIcon\", \"\");
                key.SetValue(\"Default Visible\", \"Yes\");
                key.SetValue(\"MenuText\", \"&Highlighter options\");
                key.SetValue(\"ToolTip\", \"Highlighter options\");
                //key.SetValue(\"KeyPath\", \"no\");
                registryKey.Close();
                key.Close();
            }
        }

        [ComUnregisterFunction]
        public static void UnregisterBHO(Type type)
        {
            string guid = type.GUID.ToString(\"B\");
            // BHO
            {
                RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(RegBHO, true);
                if (registryKey != null)
                    registryKey.DeleteSubKey(guid, false);
            }
            // Command
            {
                RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(RegCmd, true);
                if (registryKey != null)
                    registryKey.DeleteSubKey(guid, false);
            }
        }
        #endregion
    }
}
互操作
using System;
using System.Runtime.InteropServices;
namespace InternetExplorerExtension
{
    [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, [MarshalAs(UnmanagedType.IUnknown)]out IntPtr ppvSite);
    }


    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct OLECMDTEXT
    {
        public uint cmdtextf;
        public uint cwActual;
        public uint cwBuf;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
        public char rgwz;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct OLECMD
    {
        public uint cmdID;
        public uint cmdf;
    }

    [ComImport(), ComVisible(true),
    Guid(\"B722BCCB-4E68-101B-A2BC-00AA00404770\"),
    InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IOleCommandTarget
    {

        [return: MarshalAs(UnmanagedType.I4)]
        [PreserveSig]
        int QueryStatus(
            [In] IntPtr pguidCmdGroup,
            [In, MarshalAs(UnmanagedType.U4)] uint cCmds,
            [In, Out, MarshalAs(UnmanagedType.Struct)] ref OLECMD prgCmds,
            //This parameter must be IntPtr, as it can be null
            [In, Out] IntPtr pCmdText);

        [return: MarshalAs(UnmanagedType.I4)]
        [PreserveSig]
        int Exec(
            //[In] ref Guid pguidCmdGroup,
            //have to be IntPtr, since null values are unacceptable
            //and null is used as default group!
            [In] IntPtr pguidCmdGroup,
            [In, MarshalAs(UnmanagedType.U4)] uint nCmdID,
            [In, MarshalAs(UnmanagedType.U4)] uint nCmdexecopt,
            [In] IntPtr pvaIn,
            [In, Out] IntPtr pvaOut);
    }
}
最后是表格,我们将使用它来配置选项。在此表格中放置
TextBox
和Ok
Button
。将按钮的DialogResult设置为Ok。将此代码放在表单代码中:
using System.Windows.Forms;
namespace InternetExplorerExtension
{
    public partial class HighlighterOptionsForm : Form
    {
        public HighlighterOptionsForm()
        {
            InitializeComponent();
        }

        public string InputText
        {
            get { return this.textBox1.Text; }
            set { this.textBox1.Text = value; }
        }
    }
}
在项目属性中,执行以下操作: 用强力钥匙在组件上签名; 在“调试”选项卡中,将“启动外部程序”设置为“ 9”。 在“调试”选项卡中,将“命令行参数”设置为“ 10” 在“构建事件”选项卡中,将“构建后事件”命令行设置为: \“%ProgramFiles(x86)%\\ Microsoft SDKs \\ Windows \\ v10.0A \\ bin \\ NETFX 4.6.1 Tools \\ gacutil.exe \” / f / i \“ $(TargetDir)$(TargetFileName )\“ \“%windir%\\ Microsoft.NET \\ Framework \\ v4.0.30319 \\ RegAsm.exe \” /取消注册\“ $(TargetDir)$(TargetFileName)\” \“%windir%\\ Microsoft.NET \\ Framework \\ v4.0.30319 \\ RegAsm.exe \” \“ $(TargetDir)$(TargetFileName)\” 注意:即使我的计算机是x64,我也使用了非x64
gacutil.exe
的路径,并且可以正常工作... x64的专用路径是: C:\\ Program Files(x86)\\ Microsoft SDKs \\ Windows \\ v10.0A \\ bin \\ NETFX 4.6.1 Tools \\ x64 \\ gacutil.exe 64位IE需要64位编译和64位注册的BHO。尽管我只能使用32位IE11进行调试,但是32位注册扩展也可以通过运行64位IE11来工作。 这个答案似乎对此有一些附加信息:https://stackoverflow.com/a/23004613/195417 如果需要,可以使用64位重装: %windir%\\ Microsoft.NET \\ Framework64 \\ v4.0.30319 \\ RegAsm.exe 此加载项如何工作 我没有更改加载项的行为。。。下面介绍一下IE8部分。 ## IE8的先前答案 伙计...这是很多工作! 我很好奇如何做到这一点,以至于我自己做了。 首先...信誉不全是我的。这是我在以下网站上发现的内容的汇总: CodeProject文章,如何制作BHO; 15秒,但不是15秒,大约花了7个小时; Microsoft教程,帮助我添加了命令按钮。 这个social.msdn主题帮助我弄清楚该程序集必须位于GAC中。 此MSDN博客文章包含一个完整的示例 许多其他网站,在发现过程中... 当然,我希望我的答案具有您要求的功能: DOM遍历以查找某些内容; 显示窗口的按钮(以我为例进行设置) 保留配置(我将为此使用注册表) 最后执行javascript。 我将逐步介绍它,以及如何在Windows 7 x64中与Internet Explorer 8一起使用的方法。请注意,我无法在其他配置中进行测试。希望你理解=) 创建有效的Internet Explorer 8加载项 我使用的是Visual Studio 2010,C#4,.Net Framework 4,因此其中一些步骤可能对您略有不同。 创建了一个类库。我叫我InternetExplorerExtension。 将这些引用添加到项目中: 互操作 Microsoft.mshtml 注意:这些参考可能在每台计算机的不同位置。 这是我在csproj中的参考部分包含的内容:
<Reference Include=\"Interop.SHDocVw, Version=1.1.0.0, Culture=neutral, PublicKeyToken=90ba9c70f846762e, processorArchitecture=MSIL\">
  <SpecificVersion>False</SpecificVersion>
  <EmbedInteropTypes>True</EmbedInteropTypes>
  <HintPath>C:\\Program Files (x86)\\Microsoft Visual Studio 9.0\\Common7\\IDE\\PrivateAssemblies\\Interop.SHDocVw.dll</HintPath>
</Reference>
<Reference Include=\"Microsoft.CSharp\" />
<Reference Include=\"Microsoft.mshtml, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">
  <EmbedInteropTypes>True</EmbedInteropTypes>
</Reference>
<Reference Include=\"System\" />
<Reference Include=\"System.Data\" />
<Reference Include=\"System.Drawing\" />
<Reference Include=\"System.Windows.Forms\" />
<Reference Include=\"System.Xml\" />
创建文件的方式与更新IE11文件的方式相同。 IEAddon.cs 您可以取消注释IE11版本中的以下几行:
...
// @Eric Stob: Thanks for this hint!
// This was used to prevent this method being executed more than once in IE8... but now it seems to not work anymore.
if (pDisp != this.site)
    return;
...
互操作 与IE11版本相同。 最后是表格,我们将使用它来配置选项。在此表格中放置
TextBox
和Ok
Button
。将按钮的DialogResult设置为Ok。该代码与IE11插件相同。 在项目属性中,执行以下操作: 用强力钥匙在组件上签名; 在“调试”选项卡中,将“启动外部程序”设置为“ 9”。 在“调试”选项卡中,将“命令行参数”设置为“ 10” 在“构建事件”选项卡中,将“构建后事件”命令行设置为: \“ C:\\ Program Files(x86)\\ Microsoft SDKs \\ Windows \\ v7.0A \\ Bin \\ NETFX 4.0 Tools \\ x64 \\ gacutil.exe \” / f / i \“ $(TargetDir )$(TargetFileName)\“ \“ C:\\ Windows \\ Microsoft.NET \\ Framework \\ v4.0.30319 \\ RegAsm.exe \” /取消注册\“ $(TargetDir)$(TargetFileName)\” \“ C:\\ Windows \\ Microsoft.NET \\ Framework \\ v4.0.30319 \\ RegAsm.exe \” \“ $(TargetDir)$(TargetFileName)\” 注意:由于我的计算机是x64,因此我的计算机上gacutil可执行文件的路径中有一个特定的x64,可能与您的不同。 64位IE需要64位编译和64位注册的BHO。使用64位RegAsm.exe(通常位于C:\\ Windows \\ Microsoft.NET \\ Framework64 \\ v4.0.30319 \\ RegAsm.exe中) 此加载项如何工作 它遍历所有DOM树,用黄色背景本身替换使用按钮配置的文本。如果单击发黄的文本,它将调用动态插入页面的javascript函数。默认单词是“浏览器”,因此它与很多单词匹配! 编辑:更改要突出显示的字符串后,您必须单击URL框,然后按Enter键。F5将不起作用,我认为这是因为F5被视为\'navigation \',并且需要收听导航事件(也许)。我稍后会尝试解决。 现在,该走了。我很累。 随便问问题...也许因为我要去旅行而无法回答...三天后我会回来,但我会同时尝试到这里来。     
另一个很酷的方法是签出: http://www.crossrider.org 它是基于带有jQuery的JS的框架,可让您使用一个通用的JS代码为IE,FF和Chrome开发浏览器扩展。 基本上,该框架可以完成所有麻烦的工作,您只需编写应用程序代码即可。     
IE扩展的状态实际上是很难过的。您拥有IE5浏览器帮助器对象的旧模型(是的,那些臭名昭著的BHO,今天每个人都想阻止它),工具栏和IE的新加速器。 即使那样,兼容性有时也会中断。我曾经为IE6保留了与IE7无关的扩展,所以有些事情发生了变化。就我所知,大部分时间(多年以来我都没有接触过BHO),您仍然需要使用Active Template Libraries(类似于Microsoft COM的STL)对它们进行编码。对于C ++。 您可以使用C#进行COM互操作,而不必使用C#进行操作,但是对于它的价值来说可能太难了。 无论如何,如果您有兴趣为IE编写自己的扩展名(如果您希望所有主要浏览器中都提供扩展名,那么这是有道理的),这里是官方的Microsoft资源。 http://msdn.microsoft.com/zh-CN/library/aa753587(v=vs.85).aspx 对于IE8中的新加速器,您可以检查一下。 http://msdn.microsoft.com/zh-CN/library/cc289775(v=vs.85).aspx 我同意文档太糟糕了,而且API已经过时了。我仍然希望这会有所帮助。 编辑:我想我可以在这里抛出最后一个信息来源。当我从事BHO时,我正在翻阅我的背书。这是让我开始使用它们的文章。它有点旧,但是对使用IE BHO(例如IObjectWithSite)时将使用的ATL接口有很好的解释。我认为这很好地解释了当时的情况,并为我提供了很多帮助。 http://msdn.microsoft.com/en-us/library/bb250436.aspx 我还检查了GregC发布的示例。它至少可以与IE8一起使用,并且与VS 2010兼容,因此,如果您要使用C#,可以从那里开始并看一下Jon Skeet的书。 (第2版的C#)第13章提供了有关C#4中新功能的大量信息,您可以使用这些信息使与COM的交互更好。 (我仍然建议您使用C ++进行加载)     
开发C#BHO是一个痛苦的过程。它涉及许多棘手的COM代码和p / invoke调用。 我这里的C#BHO基本完成,您可以随意使用源代码。我说“大部分”是因为我从未想过如何在IE保护模式下保存应用程序数据。     
我使用IE \的Web浏览器控件已有多年了,在整个过程中,一个有用的帖子反复出现一个名字:Igor Tandetnik 如果我正在开发扩展程序,我将定位到BHO,并开始搜索以下内容: BHO伊戈尔·坦德尼克(Igor Tandetnik) 要么 浏览器助手对象Igor Tandetnik 他的帖子通常非常详细,并且他知道自己在说什么。 您将在COM和ATL编程中耳熟能详。 有关示例演练,请查看: http://msdn.microsoft.com/en-us/library/ms976373.aspx     

bab

我同意Robert Harvey的观点,C#4.0的功能改进了COM互操作。这是一些较旧的C#代码,非常需要重新编写。 http://www.codeproject.com/KB/cs/Attach_BHO_with_C_.aspx 这是通过避免ATL并使用Spartan COM来简化事情的尝试: C ++和COM推动BHO的发展     
如果您不想重新发明轮子,则可以尝试使用IE的Add In Express。我已经将该产品用于VSTO的东西,它相当不错。他们也有一个有用的论坛和快速支持。     
它显然已经解决了,但是对于其他用户,我建议使用SpicIE框架。我已经基于它做了自己的扩展。它仅支持Internet Explorer 7/8正式版,但我在Internet Explorer 6-10(从Windows XP到Windows 8 Consumer Preview)上进行了测试,并且工作正常。 不幸的是,最新版本中存在一些错误,因此我必须修复它们并制作自己的版本: http://archive.msdn.microsoft.com/SpicIE/Thread/View.aspx?ThreadId=5251     
我热烈建议您在2002年发表这篇帕维尔·佐尔尼科夫的帖子! http://www.codeproject.com/Articles/2219/Extending-Explorer-with-Band-Objects-using-NET-and 它基于Band对象的使用,并使用.Net 2.0进行编译。 提供了源代码,并且可以使用Visual Studio 2013很好地打开和编译源代码。 正如您将在帖子评论中阅读的那样,它非常适合IE 11以及Windows 7和Windows 10。 在Windows 7 + SP1和IE 11上,它对我来说效果很好 请享用!     
  在“构建事件”选项卡中,将“构建后事件”命令行设置为:(x64)在下面列出
\"C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\Bin\\NETFX 4.0 Tools\\x64\\gacutil.exe\" /if \"$(TargetDir)$(TargetFileName)\"    
\"C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\RegAsm.exe\" /u \"$(TargetDir)$(TargetFileName)\"    
\"C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\RegAsm.exe\" \"$(TargetDir)$(TargetFileName)\"
  我想要“构建事件”选项卡,将“构建后事件”命令行设置为(32位操作系统)
\"C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Bin\\gacutil.exe\" /if \"$(TargetDir)$(TargetFileName)\"    
\"C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\RegAsm.exe\" /u \"$(TargetDir)$(TargetFileName)\"    
\"C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\RegAsm.exe\" \"$(TargetDir)$(TargetFileName)\"
    

要回复问题请先登录注册