How to get started with developing Internet Explorer extensions?
这里有没有人有开发能够分享他们知识的IE扩展的经验?这将包括代码示例,或者到好的示例的链接,或者流程的文档,或者任何东西。
我真的很想这样做,但是我正在用糟糕的文档、糟糕的代码/示例代码/缺少它们来打一堵巨大的墙。如果您能提供任何帮助/资源,我们将不胜感激。
具体来说,我想从如何在IE扩展中访问/操作DOM开始。
编辑,更多详细信息:
理想情况下,我希望安装一个工具栏按钮,单击它时,弹出一个菜单,其中包含指向外部站点的链接。我还想访问dom并在页面上安装javascript,这取决于某些条件。
在IE扩展中保存信息的最佳方法是什么?在firefox/chrome/大多数现代浏览器中,您使用
我不想使用spice ie,因为我想构建一个与ie9兼容的。我也将C++标签添加到这个问题中,因为如果在C++中构建一个更好,我可以做到。
[更新]我正在将此答案更新为使用Internet Explorer 11,在Windows 10 x64中使用Visual Studio 2017社区。此答案的早期版本(对于Internet Explorer 8,在Windows 7 x64和Visual Studio 2010中)位于此答案的底部。好的。创建可工作的Internet Explorer 11加载项
我正在使用Visual Studio 2017 Community、C、.NET Framework 4.6.1,因此这些步骤中的某些步骤可能与您稍有不同。好的。
您需要以管理员身份打开Visual Studio来构建解决方案,以便构建后脚本可以注册BHO(需要注册表访问)。好的。
从创建类库开始。我叫我的InternetExplorerTension。好的。
将这些引用添加到项目中:好的。
- interop.shdocvw:com选项卡/搜索
"Microsoft Internet Controls" - microsoft.mshtml:程序集选项卡/搜索
"Microsoft.mshtml" 。
注意:尽管在"添加引用"窗口中可以找到MSHTML,但是MSHTML并没有在我的系统中注册。这导致生成时出错:好的。
Cannot find wrapper assembly for type library"MSHTML"
Ok.
可以在http://techninotes.blogspot.com/2016/08/fixing-cannot-find-wrapper-assembly-for.html上找到修复程序。或者,可以运行此批处理脚本:好的。
1 2 3 4 | "%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 |
创建以下文件:好的。
IEADON.CS好的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 | 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 } } |
国际互联互通系统好的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | 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); } } |
最后是一个表单,我们将使用它来配置选项。在这种形式下,放置一个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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; } } } } |
在项目属性中,执行以下操作:好的。
- 用强键在组件上签名;
- 在"调试"选项卡中,将"启动外部程序"设置为
C:\Program Files (x86)\Internet Explorer\iexplore.exe 。 - 在"调试"选项卡中,将命令行参数设置为
http://msdn.microsoft.com/en-us/library/ms976373.aspx#bho_getintouch 。 在"生成事件"选项卡中,将"生成后事件"命令行设置为:好的。
1
2
3
4
5
6
7
8"%ProgramFiles(x86)%\Microsoft SDKs\Windows\v10.0A\bin
ETFX 4.6.1 Tools\gacutil.exe" /f /i"$(TargetDir)$(TargetFileName)"
"%windir%\Microsoft.NET\Framework\v4.0.30319
egAsm.exe" /unregister"$(TargetDir)$(TargetFileName)"
"%windir%\Microsoft.NET\Framework\v4.0.30319
egAsm.exe""$(TargetDir)$(TargetFileName)"
注意:虽然我的电脑是X64,但我还是使用了非X64
1 2 | C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin ETFX 4.6.1 Tools\x64\gacutil.exe |
64位IE需要64位编译和64位注册BHO。虽然我只能使用32位IE11进行调试,但32位注册扩展也可以通过运行64位IE11来工作。好的。
这个答案似乎有一些关于这个的附加信息:https://stackoverflow.com/a/23004613/195417好的。
如果需要,可以使用64位regasm:好的。
1 2 | %windir%\Microsoft.NET\Framework64\v4.0.30319 egAsm.exe |
这个附加组件的工作原理好的。
我没有改变附加组件的行为…请看下面的IE8部分了解相关说明。好的。##IE8以前的答案
男人…这是很多工作!我对如何做这件事很好奇,所以我自己做了。好的。
首先…信用不全是我的。这是我在这些网站上发现的资料汇编:好的。
- 代码项目文章,如何制作一个BHO;
- 15秒,但不是15秒,大约7小时;
- 微软教程,帮助我添加了命令按钮。
- 还有这个social.msdn主题,它帮助我了解到组装必须在GAC中。
- 此msdn博客文章包含一个完全有效的示例
- 在发现过程中的许多其他站点…
当然,我希望我的答案具有你所要求的特征:好的。
- dom遍历以查找某些内容;
- 显示窗口的按钮(在我的例子中是设置)
- 保留配置(我将为此使用注册表)
- 最后执行javascript。
我将一步一步地描述它,如何在Windows7x64中使用InternetExplorer8来完成它…请注意,我无法在其他配置中进行测试。希望你能理解=)好的。创建可工作的Internet Explorer 8加载项
我正在使用Visual Studio 2010、C_4和.NET Framework 4,因此这些步骤中的某些步骤可能与您稍有不同。好的。
创建了类库。我叫我的InternetExplorerTension。好的。
将这些引用添加到项目中:好的。
- 肖多夫
- 微软.mshtml
注意:这些引用可能在每台计算机的不同位置。好的。
这是我在csproj中的参考资料部分包含的内容:好的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <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文件相同的方式创建文件。好的。
IEADON.CS好的。
可以取消对IE11版本中以下行的注释:好的。
1 2 3 4 5 6 | ... // @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版本相同。好的。
最后是一个表单,我们将使用它来配置选项。在此表格中,放置一个
在项目属性中,执行以下操作:好的。
- 用强键在组件上签名;
- 在"调试"选项卡中,将"启动外部程序"设置为
C:\Program Files (x86)\Internet Explorer\iexplore.exe 。 - 在"调试"选项卡中,将命令行参数设置为
http://msdn.microsoft.com/en-us/library/ms976373.aspx#bho_getintouch 。 在"生成事件"选项卡中,将"生成后事件"命令行设置为:好的。
1
2
3
4
5
6
7
8"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin
ETFX 4.0 Tools\x64\gacutil.exe" /f /i"$(TargetDir)$(TargetFileName)"
"C:\Windows\Microsoft.NET\Framework\v4.0.30319
egAsm.exe" /unregister"$(TargetDir)$(TargetFileName)"
"C:\Windows\Microsoft.NET\Framework\v4.0.30319
egAsm.exe""$(TargetDir)$(TargetFileName)"
注意:由于我的计算机是x64,所以我的计算机上的gacutil可执行文件路径中有一个特定的x64,您的路径可能不同。好的。
64位IE需要64位编译和64位注册BHO。使用64位regasm.exe(通常位于c:windowsmicrosoft.netframework64v4.0.30319
egasm.exe中)好的。
这个附加组件的工作原理好的。
它遍历所有的DOM树,将使用按钮配置的文本替换为黄色背景。如果单击变黄的文本,它将调用动态插入页面的javascript函数。默认的词是"browser",因此它与许多词匹配!编辑:更改要突出显示的字符串后,必须单击URL框并按Enter…F5将不起作用,我认为这是因为F5被认为是"导航",它需要监听导航事件(可能)。我稍后会设法解决的。好的。
现在是时候走了。我很累。请随意提问…也许我不能回答,因为我要去旅行…三天后我就回来了,但我会尽量同时到这里来。好的。好啊。
另一个很酷的方法是检查:
网址:http://www.crossrider.org
它是一个基于JSwithjquery的框架,允许您使用一个通用的JS代码为IE、FF和Chrome开发浏览器扩展。基本上,框架完成了所有令人讨厌的工作,剩下的工作就是编写应用程序代码。
IE扩展的状态实际上很糟糕。你有IE5浏览器助手对象的旧模型(是的,那些臭名昭著的bhos,每个人都喜欢在一天之内阻止),工具栏和IE的新加速器。即使这样,兼容性有时也会中断。我以前一直保持IE6的扩展,它与IE7断开了,所以有些事情已经改变了。在大多数情况下,据我所知(多年来我没有接触BHOs),您仍然需要使用活动模板库来编写代码(类似于微软的COM的STL),而这仅是针对C++的。你可以用C做COM互操作,不用用C做,但这对于它的价值来说可能太难了。无论如何,如果您有兴趣为IE编写自己的扩展名(如果您希望在所有主要浏览器中都有自己的扩展名,这是合理的),下面是官方的微软资源。
http://msdn.microsoft.com/en-us/library/aa753587(v=vs.85).aspx
对于IE8中的新加速器,您可以检查这个。
http://msdn.microsoft.com/en-us/library/cc289775(v=vs.85).aspx
我同意文档太糟糕了,API已经过时了。不过,我还是希望这能有所帮助。
编辑:我想我可以把最后一个信息源扔到这里。当我在BHO工作时,我正在看我的笔记。这篇文章让我从他们开始。它有点旧,但是对您在使用IE BHOS时将使用的ATL接口有很好的解释(例如IObjectWithSite)。我认为这是很好的解释和帮助我当时很多。http://msdn.microsoft.com/en-us/library/bb250436.aspx我还查看了GregC发布的示例。它至少能与IE8一起工作,并且与Vs2010兼容,所以如果你想做C你可以从那里开始,看看乔恩·斯基特的书。(C第二版)第13章提供了大量关于C 4中新功能的信息,您可以使用这些信息来更好地与COM进行交互。(我还是建议你在C++中做你的插件)
开发C bhos是一种麻烦。它涉及许多恶心的COM代码和P/Invoke调用。
我这里有一个基本完成的C bho,你可以自由地使用源代码来做你想要的任何事情。我说"大部分",因为我从来没有弄清楚如何在IE保护模式下保存AppData。
多年来,我一直在与IE的Webbrowser Control合作,在这过程中,一个名字一次又一次地出现在有用的帖子中:igor tandetnik
如果我正在开发一个扩展,我将以BHO为目标,并开始搜索:
bho igor tandetnik公司
或
浏览器助手对象igor tandetnik
他的帖子通常很详细,他知道自己在说什么。
你会发现自己对COM和ATL编程非常感兴趣。对于示例演练,请查看:http://msdn.microsoft.com/en-us/library/ms976373.aspx
这显然是解决了,但对于其他用户,我建议使用spicie框架。我已经根据它做了自己的扩展。它只支持Internet Explorer 7/8 Officialy,但我在Internet Explorer 6-10(从Windows XP到Windows 8 Consumer Preview)上进行了测试,效果良好。不幸的是,最新版本中有一些bug,所以我必须修复它们并自己发布:http://archive.msdn.microsoft.com/spicie/thread/view.aspx?苏塞德=5251
如果你不想重新发明轮子,你可以尝试为IE添加Express。我用这个产品做VSTO的东西,它很好。他们还有一个有用的论坛和快速的支持。
我同意Robert Harvey的观点,C 4.0的功能改进了COM互操作。这里有一点旧的C代码,急需重新编写。
http://www.codeproject.com/kb/cs/attach_bho_with_c_u.aspx
这是一种通过避免ATL和使用斯巴达COM来简化事情的尝试:
C++与COM获取BHOs
我热情地推荐你这篇发表于2002年的帕维尔·佐尔尼科夫的文章!
http://www.codeproject.com/articles/2219/extending-explorer-with-band-objects-using-net-and
它基于带对象的使用,并使用.NET 2.0编译。提供了源代码,并与Visual Studio 2013一起打开和编译。正如您将在文章评论中看到的那样,它对于IE11、Windows7和Windows10都非常适用。它在Windows7+SP1和IE11上非常适合我享受!
In the Build Events tab, set Post-build events command line to: (x64) is listed below
1 2 3 4 5 6 | "C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin ETFX 4.0 Tools\x64\gacutil.exe" /if"$(TargetDir)$(TargetFileName)" "C:\Windows\Microsoft.NET\Framework64\v4.0.30319 egAsm.exe" /u"$(TargetDir)$(TargetFileName)" "C:\Windows\Microsoft.NET\Framework64\v4.0.30319 egAsm.exe""$(TargetDir)$(TargetFileName)" |
I want the Build Events tab , set Post-build events command line to (32 bit operating system)
1 2 3 4 5 | "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\gacutil.exe" /if"$(TargetDir)$(TargetFileName)" "C:\Windows\Microsoft.NET\Framework\v4.0.30319 egAsm.exe" /u"$(TargetDir)$(TargetFileName)" "C:\Windows\Microsoft.NET\Framework\v4.0.30319 egAsm.exe""$(TargetDir)$(TargetFileName)" |