เริ่มต้นด้วยการพัฒนาส่วนขยายของ Internet Explorer อย่างไร


207

ใครบ้างที่นี่มีประสบการณ์กับ / ในการพัฒนาส่วนขยาย IE ที่สามารถแบ่งปันความรู้ของพวกเขา? ซึ่งจะรวมถึงตัวอย่างโค้ดหรือลิงค์ไปยังสิ่งที่ดีหรือเอกสารเกี่ยวกับกระบวนการหรืออะไรก็ตาม

ฉันต้องการทำสิ่งนี้จริงๆ แต่ฉันกำลังตีกำแพงยักษ์พร้อมกับเอกสารหมัดรหัสหมัด / ตัวอย่างโค้ด / การขาดมัน ความช่วยเหลือ / ทรัพยากรใด ๆ ที่คุณสามารถนำเสนอจะได้รับการชื่นชมอย่างมาก

โดยเฉพาะฉันต้องการเริ่มต้นด้วยวิธีการเข้าถึง / จัดการ DOM จากภายในส่วนขยาย IE

แก้ไขรายละเอียดเพิ่มเติม:

โดยหลักการแล้วฉันต้องการสร้างปุ่มแถบเครื่องมือที่เมื่อคลิกแล้วจะเปิดเมนูขึ้นซึ่งมีลิงก์ไปยังไซต์ภายนอก ฉันต้องการเข้าถึง DOM และ plant JavaScript บนหน้าขึ้นอยู่กับเงื่อนไขบางประการ

วิธีที่ดีที่สุดในการคงอยู่ของข้อมูลในส่วนขยาย IE คืออะไร? ใน Firefox / Chrome / เบราว์เซอร์ที่ทันสมัยที่สุดคุณใช้window.localStorageแต่เห็นได้ชัดกับ IE8 / IE7 นั่นไม่ใช่ตัวเลือก อาจเป็น SQLite DB หรืออย่างนั้น? ถือว่าโอเคที่จะติดตั้ง. NET 4.0 บนคอมพิวเตอร์ของผู้ใช้หรือไม่?

ฉันไม่ต้องการใช้ Spice IE เพราะฉันต้องการสร้างสิ่งที่เข้ากันได้กับ IE9 เช่นกัน ฉันได้เพิ่มแท็ก C ++ ลงในคำถามนี้ด้วยเช่นกันเพราะถ้าสร้างดีกว่าใน C ++ ฉันก็สามารถทำได้


1
IMHO IE 9 เป็นคำสั่งที่มีขนาดใหญ่กว่ารุ่นก่อนหน้า (ไม่ใช่ว่าฉันจะออกจาก Chrome สำหรับ IE แน่นอน ... ยังไม่ได้)
user541686

1
@Alex: คุณนึกภาพการใช้อะไรใน IE เพื่อที่เราจะเริ่มขุดในทิศทางทั่วไปที่ถูกต้อง?
GregC

@Alex: เพื่อที่จะแยกแยะปัญหานี้ออกเป็นส่วนที่จัดการได้ฉันจะต้องรู้สิ่งต่อไปนี้: เราสามารถสรุปได้ไหมว่าผู้ใช้ปลายทางจะใช้ IE9 และยินดีที่จะติดตั้ง dotNET 4.0 runtime หรือไม่?
GregC

ฉันเห็นด้วยกับ GregC ข้อมูลเพิ่มเติมบางอย่างจะช่วยได้ที่นี่ คุณกำลังคิดบางอย่างเช่นแถบเครื่องมือหรืออาจเป็นสิ่งที่จะประมวลผลสิ่งที่ผู้ใช้กำลังเรียกดูหรือสิ่งที่จะเชื่อมต่อกับบริการของบุคคลที่สาม
cloudraven

4
@ Alex, ดูที่Crossrider มันจะทำให้ชีวิตของคุณง่ายขึ้นมาก
shdev

คำตอบ:


229

[อัพเดท] ฉันกำลังอัปเดตคำตอบนี้เพื่อทำงานกับInternet Explorer 11ในWindows 10 x64กับชุมชน Visual Studio 2017ชุมชน รุ่นก่อนหน้าของคำตอบนี้ (สำหรับ Internet Explorer 8 ใน Windows 7 x64 และ Visual Studio 2010) อยู่ที่ด้านล่างของคำตอบนี้

การสร้าง Add-on ที่ทำงานกับ Internet Explorer 11

ฉันใช้ชุมชน Visual Studio 2017 , C # , .Net Framework 4.6.1ดังนั้นขั้นตอนเหล่านี้อาจแตกต่างกันเล็กน้อยสำหรับคุณ

คุณต้องเปิด Visual Studio ในฐานะผู้ดูแลระบบเพื่อสร้างโซลูชันเพื่อให้สคริปต์โพสต์บิลด์สามารถลงทะเบียน BHO (ต้องการการเข้าถึงรีจิสทรี)

เริ่มต้นด้วยการสร้างไลบรารีคลาส ผมเรียกว่าเหมืองInternetExplorerExtension

เพิ่มการอ้างอิงเหล่านี้ไปยังโครงการ:

  • Interop.SHDocVw: แท็บ COM / ค้นหา "Microsoft Internet Controls"
  • Microsoft.mshtml: แท็บชุดประกอบ / ค้นหา "Microsoft.mshtml"

หมายเหตุ:อย่างใด 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
    }
}

Interop.cs

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 Buttonตั้งDialogResultของปุ่มไปตกลง วางรหัสนี้ในรหัสแบบฟอร์ม:

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
  • ในแท็บ Debug ตั้งอาร์กิวเมนต์บรรทัดคำสั่งเป็นhttp://msdn.microsoft.com/en-us/library/ms976373.aspx#bho_getintouch
  • ในแท็บ Build Events ให้ตั้งค่าบรรทัดคำสั่ง Post-build eventsเป็น:

    "% 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 อยู่ที่:

SDK: \ Program Files (x86) \ Microsoft SDKs \ Windows \ v10.0A \ bin \ NETFX 4.6.1 Tools \ x64 \ gacutil.exe

64 บิต IEต้องการ BHO ที่คอมไพล์แล้ว 64 บิตและ 64 บิตที่ลงทะเบียนไว้ แม้ว่าฉันจะสามารถดีบักโดยใช้ 32 บิต IE11 เท่านั้นส่วนขยายที่ลงทะเบียน 32 บิตนั้นก็ทำงานได้ด้วยการรัน 64 บิต IE11

คำตอบนี้ดูเหมือนจะมีข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้: https://stackoverflow.com/a/23004613/195417

ถ้าคุณต้องการคุณสามารถใช้ 64 บิต regasm:

% windir% \ Microsoft.NET \ Framework 64 \ v4.0.30319 \ RegAsm.exe

วิธีการทำงานของ Add-on นี้

ฉันไม่ได้เปลี่ยนพฤติกรรมของแอดออน ... ลองดูที่ IE8 ส่วนต่อไปเพื่อดูคำอธิบาย


## คำตอบก่อนหน้าสำหรับ IE8

ชาย ... นี่มันทำงานเยอะมาก! ฉันอยากรู้เกี่ยวกับวิธีการทำเช่นนี้ว่าฉันทำมันเอง

ก่อนอื่น ... เครดิตไม่ได้เป็นของฉันทั้งหมด นี่คือการรวบรวมสิ่งที่ฉันพบในเว็บไซต์เหล่านี้:

และแน่นอนฉันต้องการคำตอบของฉันที่จะมีคุณสมบัติที่คุณถาม:

  • สำรวจเส้นทาง DOM เพื่อค้นหาบางสิ่งบางอย่าง
  • ปุ่มที่แสดงหน้าต่าง (ในกรณีของฉันเพื่อตั้งค่า)
  • ยังคงมีการกำหนดค่า (ฉันจะใช้รีจิสทรีเพื่อที่)
  • และในที่สุดก็รันจาวาสคริปต์

ฉันจะอธิบายทีละขั้นตอนวิธีที่ฉันจัดการเพื่อทำงานกับInternet Explorer 8ในWindows 7 x64 ... โปรดทราบว่าฉันไม่สามารถทดสอบในการกำหนดค่าอื่น ๆ หวังว่าคุณจะเข้าใจ =)

การสร้างโปรแกรมเสริม Internet Explorer 8 ทำงาน

ฉันใช้Visual Studio 2010 , C # 4 , .Net Framework 4ดังนั้นขั้นตอนเหล่านี้บางอย่างอาจแตกต่างกันเล็กน้อยสำหรับคุณ

สร้างไลบรารีคลาส ผมเรียกว่าเหมืองInternetExplorerExtension

เพิ่มการอ้างอิงเหล่านี้ไปยังโครงการ:

  • Interop.SHDocVw
  • 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;
...

Interop.cs

เหมือนกับเวอร์ชัน IE11

และในที่สุดก็เป็นรูปแบบที่เราจะใช้ในการกำหนดค่าตัวเลือก ในสถานที่แห่งนี้เป็นรูปแบบและตกลงTextBox Buttonตั้งDialogResultของปุ่มไปตกลง รหัสเหมือนกันสำหรับ add-on IE11

ในคุณสมบัติโครงการให้ทำดังต่อไปนี้:

  • เซ็นชื่อแอสเซมบลีด้วยคีย์ - ที่แข็งแกร่ง
  • ในแท็บดีบั๊กตั้งค่าเริ่มโปรแกรมภายนอกเป็นC:\Program Files (x86)\Internet Explorer\iexplore.exe
  • ในแท็บ Debug ตั้งอาร์กิวเมนต์บรรทัดคำสั่งเป็นhttp://msdn.microsoft.com/en-us/library/ms976373.aspx#bho_getintouch
  • ในแท็บ Build Events ให้ตั้งค่าบรรทัดคำสั่ง Post-build eventsเป็น:

    "C: \ Program ไฟล์ (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 มี x64 เฉพาะอยู่ในเส้นทางของ gacutil ที่สามารถเรียกใช้งานได้บนเครื่องของฉันซึ่งอาจแตกต่างจากของคุณ

64 บิต IEต้องการ BHO ที่คอมไพล์แล้ว 64 บิตและ 64 บิตที่ลงทะเบียนไว้ ใช้ RegAsm.exe 64 บิต (โดยปกติแล้วจะอยู่ใน C: \ Windows \ Microsoft.NET \ Framework64 \ v4.0.30319 \ RegAsm.exe)

วิธีการทำงานของ Add-on นี้

มันสำรวจต้นไม้ DOM ทั้งหมดแทนที่ข้อความกำหนดค่าโดยใช้ปุ่มด้วยตัวเองด้วยพื้นหลังสีเหลือง หากคุณคลิกที่ข้อความสีเหลืองมันจะเรียกใช้ฟังก์ชันจาวาสคริปต์ที่แทรกอยู่บนหน้าเว็บแบบไดนามิก คำเริ่มต้นคือ 'เบราว์เซอร์' เพื่อให้ตรงกับพวกเขามาก! แก้ไข:หลังจากเปลี่ยนสตริงที่จะเน้นคุณต้องคลิกกล่อง URL และกด Enter ... F5 จะไม่ทำงานฉันคิดว่ามันเป็นเพราะ F5 ถือเป็น 'นำทาง' และมันจะต้องฟังเหตุการณ์นำทาง (อาจจะ). ฉันจะพยายามแก้ไขในภายหลัง

ตอนนี้เป็นเวลาที่จะไป ฉันเหนื่อยมาก. อย่าลังเลที่จะถามคำถาม ... อาจเป็นเพราะฉันไม่สามารถตอบได้ตั้งแต่ฉันไปเที่ยว ... ใน 3 วันฉันกลับมาแล้ว แต่ฉันจะพยายามมาที่นี่ในเวลาเดียวกัน


2
สวัสดีฉันทำทุกอย่างตรงตามที่อธิบายไว้ในคำตอบ ปุ่มปรากฏขึ้น funtion exec มีการ exectued อย่างไรก็ตามฟังก์ชัน SetSite และ GetSite จะไม่ถูกเรียกใช้ ฉันต้องการทราบ URL ของหน้าเว็บที่ฉันใช้อยู่ การเรียกวิธีการเหล่านี้ล้มเหลวในการเริ่มต้นเบราว์เซอร์โปรดช่วยด้วย
mustafabar

3
ฉันพยายามทำเช่นนี้ใน IE9 และ: 1. หากเส้นทางโครงการของคุณมีช่องว่าง: แทนที่จะ$(TargetDir)$(TargetFileName)ใช้"$(TargetDir)$(TargetFileName)" 2 ถ้าคุณใช้ Visual Studio 2010 Express คุณอาจ (ฉันใช่) ไม่เห็นตัวเลือกเริ่มโปรแกรมภายนอกในแท็บดีบั๊ก - ฉัน เพียงแค่เรียกใช้ IE และนำทางไปยัง URL ที่ให้ไว้ 3 ดูเหมือนว่าจะไม่ทำงานบน IE9 - ฉันสามารถเปิดแบบฟอร์ม (ตัวเลือก
ปากกา

8
สำหรับการอ้างอิง Interop.SHDocVw - คุณควรเพิ่มการอ้างอิง COM ไปที่ "Microsoft Internet Controls" และ "ใช้ SHDocVw;"
Eric Hartford

8
"IE10 บน x64 Windows 8 จะไม่โหลดโปรแกรมเสริมของคุณเมื่อเริ่มต้นเว้นแต่คุณจะสร้างด้วยสถาปัตยกรรม" ใด ๆ ของ CPU "และลงทะเบียนโดยใช้ RegAsm.exe ทั้ง 32 และ 64 บิต เป็นการแก้ไขโดยคนที่ถูกปฏิเสธ
Matsemann

3
โปรดดูการติดตาม: stackoverflow.com/questions/22953571/…

12

แนวทางอีกอย่างที่น่าสนใจก็คือลองดู:

http://www.crossrider.org

เป็นเฟรมเวิร์กที่อิงจาก JS พร้อม jquery ซึ่งให้คุณพัฒนาส่วนขยายเบราว์เซอร์สำหรับ IE, FF และ Chrome โดยใช้รหัส JS ทั่วไป โดยทั่วไปกรอบการทำงานทั้งหมดที่น่ารังเกียจและคุณทิ้งไว้กับการเขียนรหัสการใช้งานของคุณ


ใช่นี่เป็นวิธีที่จะไปและหลีกเลี่ยงฝันร้ายที่กำลังพัฒนาปลั๊กอินใน visual studio นั่นหมายความว่าคุณต้องเขียนปลั๊กอินของคุณเพียงครั้งเดียวสำหรับเบราว์เซอร์ทั้งหมด นอกจากนี้ยังหมายถึงไม่ต้องพัฒนาในเครื่องเสมือนหากคุณเป็นผู้ใช้ mac
opsb

11

สถานะของส่วนขยาย IE น่าเศร้าจริง ๆ คุณมี IE5 Browser Helper Object รุ่นเก่า (ใช่แล้ว BHOs ​​ที่น่าอับอายที่ทุกคนชอบปิดกั้นในตอนกลางวัน) แถบเครื่องมือและตัวเร่งความเร็วใหม่สำหรับ IE ถึงอย่างนั้นบางครั้งความเข้ากันได้ก็จะพัง ฉันเคยรักษาส่วนขยายสำหรับ IE6 ที่ยากจนด้วย IE7 ดังนั้นจึงมีบางสิ่งที่เปลี่ยนแปลงไป ส่วนใหญ่เท่าที่ฉันรู้ (ฉันไม่ได้สัมผัส BHOs ​​ในปี) คุณยังคงต้องใช้รหัสพวกเขาโดยใช้ Active Template Libraries (เช่น STL สำหรับ COM ของ Microsoft) และเช่นนี้มีไว้สำหรับ C ++ เท่านั้น คุณสามารถใช้ COM Interop ร่วมกับ C # และหลีกเลี่ยงการทำมันใน C # แต่มันอาจจะยากเกินไปสำหรับสิ่งที่คุ้มค่า อย่างไรก็ตาม,

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 ค่อนข้างล้าสมัย ยังฉันหวังว่าสิ่งนี้จะช่วย

แก้ไข: ฉันเดาว่าฉันสามารถโยนแหล่งข้อมูลสุดท้ายได้ที่นี่ ฉันกำลังดูบันทึกย่อของฉันกลับเมื่อฉันทำงาน BHOs และนี่คือบทความที่ให้ฉันเริ่มต้นกับพวกเขา มันค่อนข้างเก่า แต่มีคำอธิบายที่ดีเกี่ยวกับอินเตอร์เฟส ATL ที่คุณจะใช้เมื่อทำงานกับ IE BHOs ​​(เช่น IObjectWithSite) ฉันคิดว่ามันอธิบายได้ค่อนข้างดีและช่วยฉันได้มากตอนนั้น http://msdn.microsoft.com/en-us/library/bb250436.aspx ฉันตรวจสอบตัวอย่างที่ GregC โพสต์ด้วย มันใช้งานได้กับ IE8 เป็นอย่างน้อยและเข้ากันได้กับ VS 2010 ดังนั้นหากคุณต้องการทำ C # คุณสามารถเริ่มต้นที่นั่นและดูที่ Jon Skeet's Book (C # ในรุ่นที่ 2 ลึก) บทที่ 13 มีข้อมูลจำนวนมากเกี่ยวกับคุณสมบัติใหม่ใน C # 4 ที่คุณสามารถใช้เพื่อโต้ตอบกับ COM nicer (ฉันขอแนะนำให้คุณใช้ Addin ของคุณใน C ++)


6

การพัฒนา C # BHOs ​​เป็นความเจ็บปวด มันเกี่ยวข้องกับรหัส COM icky จำนวนมากและการโทรแบบ p / invoke

ฉันมี C # BHO ที่เสร็จสิ้นแล้วส่วนใหญ่ที่นี่ซึ่งคุณมีอิสระที่จะใช้แหล่งข้อมูลสำหรับสิ่งที่คุณต้องการ ผมบอกว่า"ส่วนใหญ่"เพราะฉันไม่เคยคิดออกว่าจะบันทึก appdata ภายใต้ IE โหมดป้องกัน


4
C # 4.0 อาจดีกว่าในเรื่องนี้เนื่องจาก COM Interop ได้รับการปรับปรุงให้ดีขึ้นมาก
Robert Harvey

@ Robert: จริงเหรอ? ฉันไม่รู้ว่า ... อะไรคือความแตกต่าง?
user541686

@Mehrdad: คุณสามารถได้รับรสชาติของความแตกต่างที่นี่: devx.com/dotnet/Article/42590/1954 สำหรับการสนทนาเชิงลึกเพิ่มเติมดูการพูดคุยของ Anders Hejlsberg "The Future of C #," ที่นี่: channel9.msdn.com/Blogs/pdc2008/TL16
Robert Harvey

1
@Robert @Mehrdad: ไม่จริง ไม่ใช่การทำงานร่วมกันของ COM ที่เป็น icky (ในแง่นี้)มันกำลังพัฒนาและลงทะเบียนโมดูล COM ซึ่งคุณสมบัติ C # 4.0 ใหม่ไม่ได้ช่วย
BlueRaja - Danny Pflughoeft

4

ฉันได้ทำงานกับการควบคุมเว็บเบราว์เซอร์ของ IE มาหลายปีแล้วและในช่วงเวลานั้นชื่อเดียวก็ปรากฏขึ้นซ้ำแล้วซ้ำอีกด้วยการโพสต์ที่เป็นประโยชน์: Igor Tandetnik

ถ้าฉันกำลังพัฒนาส่วนขยายฉันจะกำหนดเป้าหมาย BHO และเริ่ม googling สำหรับ:

BHO Igor Tandetnik

หรือ

เครื่องมือช่วยเหลือเบราว์เซอร์ Igor Tandetnik

โพสต์ของเขามักจะมีรายละเอียดมากและเขารู้ว่าเขากำลังพูดถึงอะไร

คุณจะพบว่าตัวเองติดหูในการเขียนโปรแกรม COM และ ATL สำหรับคำแนะนำแบบตัวอย่างลองดูที่: http://msdn.microsoft.com/en-us/library/ms976373.aspx


ข้อเสียที่ใหญ่ที่สุดในการใช้ C # (ซึ่งเป็นทิศทางที่ผู้อื่นโพสต์ส่วนใหญ่กำลังทำอยู่) ก็คือมันจะต้องผ่านเลเยอร์พิเศษทุกประเภทโดยมีวิธีแก้ปัญหาและแพทช์สำหรับโค้ดที่เป็นภาษา C ++
ลินน์บี้บี้

3

ฉันเห็นด้วยกับ Robert Harvey, คุณลักษณะ C # 4.0 ที่ปรับปรุง COM interop นี่คือรหัส C # ที่เก่ากว่าเล็กน้อยซึ่งต้องการการเขียนใหม่อีกครั้ง

http://www.codeproject.com/KB/cs/Attach_BHO_with_C_.aspx

นี่คือความพยายามในการทำให้สิ่งต่าง ๆ ง่ายขึ้นโดยหลีกเลี่ยง ATL และไปกับ Spartan COM:

C ++ และ COM เพื่อให้ BHO ดำเนินต่อไป


3

ถ้าคุณไม่ได้พยายามที่จะบูรณาการล้อคุณอาจลองเพิ่มใน Express สำหรับ IE ฉันใช้ผลิตภัณฑ์สำหรับสิ่ง VSTOและมันค่อนข้างดี พวกเขายังมีฟอรั่มที่เป็นประโยชน์และการสนับสนุนอย่างรวดเร็ว


3

มันจะแก้ไขได้อย่างเห็นได้ชัด แต่สำหรับผู้ใช้งานอื่นฉันอยากจะแนะนำกรอบ SpicIE ฉันได้ทำส่วนขยายของตัวเองตามนั้น จะสนับสนุนเฉพาะ Internet Explorer 7/8 อย่างเป็นทางการ แต่ผมทดสอบที่บน Internet Explorer 6-10 (จาก Windows XP เป็น Windows 8 ดูตัวอย่างผู้บริโภค) และมันทำงานได้ดี น่าเสียดายที่มีข้อผิดพลาดบางอย่างในรุ่นล่าสุดดังนั้นฉันจึงต้องแก้ไขและทำรุ่นของตัวเอง: http://archive.msdn.microsoft.com/SpicIE/Thread/View.aspx?ThreadId=5251


0

ฉันขอแนะนำให้คุณโพสต์ของ Pavel Zolnikov นี้เผยแพร่ในปี 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 สนุก!


เราชอบคำตอบที่จะมีอยู่ใน StackOverflow โพสต์ทั้งหมดนี้บอกฉันจริงๆว่า "ใช้ Band objects และ. Net 2.0" คุณสามารถใส่รหัสตัวอย่างบางส่วนที่นี่เพื่อแสดงว่าทำได้หรือไม่
Teepeemm

0

คำถามคือจาก 2013 ตอนนี้เป็น 2020 แต่อาจเป็นประโยชน์สำหรับผู้เข้าชมในอนาคต

ฉันพยายามที่จะใช้คำตอบของ @Miguel Angelo แต่ก็ไม่ได้ผลในตอนแรก

ยังมีการตั้งค่าบางอย่างที่คุณกำหนดไว้

บน internet explorer (ฉันใช้ IE-11) ไปที่Tools-->Internet Options-->Advanced: ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่

ดูคำถาม SO นี้และตัวอย่างนี้จาก github ด้วย


-2

ป้อนคำอธิบายรูปภาพที่นี่

ในแท็บ Build Events ให้ตั้งค่าบรรทัดคำสั่งหลังเหตุการณ์บิลด์เป็น: (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)"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.