¿Cómo comenzar a desarrollar extensiones de Internet Explorer?


207

¿Alguien aquí tiene experiencia con / en el desarrollo de extensiones de IE que puedan compartir sus conocimientos? Esto incluiría ejemplos de código, o enlaces a buenos, o documentación sobre el proceso, o cualquier cosa.

Realmente quiero hacer esto, pero estoy golpeando una pared gigante con documentación pésima, código pésimo / código de ejemplo / falta de ella. Cualquier ayuda / recursos que pueda ofrecer sería muy apreciada.

Específicamente, me gustaría comenzar con cómo obtener acceso / manipular el DOM desde una extensión de IE.

EDITAR, aún más detalles:

Idealmente, me gustaría plantar un botón de barra de herramientas que, cuando se hace clic, aparece un menú que contiene enlaces a sitios externos. También me gustaría acceder al DOM y JavaScript de planta en la página, dependiendo de algunas condiciones.

¿Cuál es la mejor manera de conservar la información en una extensión de IE? En Firefox / Chrome / La mayoría de los navegadores modernos, usted usa window.localStorage, pero obviamente con IE8 / IE7, esa no es una opción. Tal vez una base de datos SQLite o tal? ¿Está bien suponer que .NET 4.0 se instalará en la computadora de un usuario?

No quiero usar Spice IE, ya que también quiero construir uno que sea compatible con IE9. También agregué la etiqueta C ++ a esta pregunta, porque si es mejor construir una en C ++, puedo hacerlo.


1
En mi humilde opinión, IE 9 es un orden de magnitud mejor que las versiones anteriores. (No es que deje Chrome para IE, por supuesto ... todavía no de todos modos)
User541686

1
@Alex: ¿qué tipo de cosas imagina implementar en IE, para que podamos comenzar a cavar en la dirección general correcta?
GregC

@ Alex: Para dividir este problema en partes manejables, necesitaría saber lo siguiente: ¿podemos suponer que el usuario final ejecutará IE9 y estará dispuesto a instalar el tiempo de ejecución dotNET 4.0?
GregC

Estoy de acuerdo con GregC. Un poco más de información ayudará aquí. ¿Está pensando en algo como una barra de herramientas, o tal vez algo que preprocesará lo que el usuario está navegando o algo que se conectará a un servicio de terceros?
cloudraven

44
@Alex, mira Crossrider . Hará tu vida mucho más fácil.
shdev

Respuestas:


229

[ACTUALIZACIÓN] Estoy actualizando esta respuesta para que funcione con Internet Explorer 11 , en Windows 10 x64 con Visual Studio 2017 Community . La versión anterior de esta respuesta (para Internet Explorer 8, en Windows 7 x64 y Visual Studio 2010) se encuentra al final de esta respuesta.

Crear un complemento de Internet Explorer 11 que funcione

Estoy usando Visual Studio 2017 Community , C # , .Net Framework 4.6.1 , por lo que algunos de estos pasos pueden ser ligeramente diferentes para usted.

Debe abrir Visual Studio como administrador para compilar la solución, de modo que el script posterior a la compilación pueda registrar el BHO (necesita acceso al registro).

Comience creando una biblioteca de clases. Llamé a la mía InternetExplorerExtension .

Agregue estas referencias al proyecto:

  • Interop.SHDocVw: pestaña COM / buscar "Microsoft Internet Controls"
  • Microsoft.mshtml: pestaña Ensamblados / búsqueda de "Microsoft.mshtml"

Nota: De alguna manera, MSHTML no estaba registrado en mi sistema, aunque pude encontrarlo en la ventana Agregar referencia. Esto causó un error al construir:

No se puede encontrar el ensamblaje de contenedor para la biblioteca de tipos "MSHTML"

La solución se puede encontrar en http://techninotes.blogspot.com/2016/08/fixing-cannot-find-wrapper-assembly-for.html O, puede ejecutar este script por lotes:

"%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

Crea los siguientes archivos:

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);
    }
}

y finalmente un formulario, que usaremos para configurar las opciones. De esta forma, coloque un TextBoxy un Ok Button. Establezca el DialogResult del botón en Ok . Coloque este código en el código del formulario:

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; }
        }
    }
}

En las propiedades del proyecto, haga lo siguiente:

  • Firme el ensamblaje con una tecla fuerte;
  • En la pestaña Depurar, configure Iniciar programa externo enC:\Program Files (x86)\Internet Explorer\iexplore.exe
  • En la pestaña Depurar, establezca Argumentos de línea de comando enhttp://msdn.microsoft.com/en-us/library/ms976373.aspx#bho_getintouch
  • En la pestaña Eventos de compilación, establezca la línea de comando de eventos posteriores a la compilación en:

    "% 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" / unregister "$ (TargetDir) $ (TargetFileName)"
    
    "% windir% \ Microsoft.NET \ Framework \ v4.0.30319 \ RegAsm.exe" "$ (TargetDir) $ (TargetFileName)"

Atención: aunque mi computadora es x64, utilicé la ruta de la no x64 gacutil.exey funcionó ... la específica para x64 está en:

C: \ Archivos de programa (x86) \ Microsoft SDKs \ Windows \ v10.0A \ bin \ NETFX 4.6.1 Tools \ x64 \ gacutil.exe

IE de 64 bits Necesita BHO compilado de 64 bits y registrado de 64 bits. Aunque solo pude depurar usando 32 bits de IE11, la extensión registrada de 32 bits también funcionó ejecutando 64 bits de IE11.

Esta respuesta parece tener información adicional sobre esto: https://stackoverflow.com/a/23004613/195417

Si lo necesita, puede usar el regasmo de 64 bits:

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

Cómo funciona este complemento

No cambié el comportamiento del complemento ... eche un vistazo a la sección IE8 a continuación para obtener una descripción.


## Respuesta anterior para IE8

Hombre ... ¡esto ha sido mucho trabajo! Tenía tanta curiosidad acerca de cómo hacer esto, que lo hice yo mismo.

Primero que nada ... el crédito no es todo mío. Esta es una compilación de lo que encontré en estos sitios:

Y, por supuesto, quería que mi respuesta tuviera las características que me pediste:

  • Recorrido DOM para encontrar algo;
  • un botón que muestra una ventana (en mi caso para configurar)
  • persistir la configuración (usaré el registro para eso)
  • y finalmente ejecutar javascript.

Lo describiré paso a paso, cómo logré hacerlo trabajando con Internet Explorer 8 , en Windows 7 x64 ... tenga en cuenta que no pude probar en otras configuraciones. Espero que entiendas =)

Crear un complemento de Internet Explorer 8 que funcione

Estoy usando Visual Studio 2010 , C # 4 , .Net Framework 4 , por lo que algunos de estos pasos pueden ser ligeramente diferentes para usted.

Creó una biblioteca de clase. Llamé a la mía InternetExplorerExtension .

Agregue estas referencias al proyecto:

  • Interop.SHDocVw
  • Microsoft.mshtml

Nota: Estas referencias pueden estar en diferentes lugares en cada computadora.

esto es lo que contiene mi sección de referencias en 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" />

Cree los archivos de la misma manera que los archivos IE11 actualizados.

IEAddon.cs

Puede descomentar las siguientes líneas de la versión 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

Igual que la versión IE11.

y finalmente un formulario, que usaremos para configurar las opciones. De esta forma, coloque un TextBoxy un Ok Button. Establezca el DialogResult del botón en Ok . El código es el mismo para el complemento IE11.

En las propiedades del proyecto, haga lo siguiente:

  • Firme el ensamblaje con una tecla fuerte;
  • En la pestaña Depurar, configure Iniciar programa externo enC:\Program Files (x86)\Internet Explorer\iexplore.exe
  • En la pestaña Depurar, establezca Argumentos de línea de comando enhttp://msdn.microsoft.com/en-us/library/ms976373.aspx#bho_getintouch
  • En la pestaña Eventos de compilación, establezca la línea de comando de eventos posteriores a la compilación en:

    "C: \ Archivos de programa (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" / anular el registro "$ (TargetDir) $ (TargetFileName)"
    
    "C: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ RegAsm.exe" "$ (TargetDir) $ (TargetFileName)"

Atención: como mi computadora es x64, hay una x64 específica dentro de la ruta del ejecutable gacutil en mi máquina que puede ser diferente en la suya.

IE de 64 bits Necesita BHO compilado de 64 bits y registrado de 64 bits. Utilice 64 bits RegAsm.exe (generalmente vive en C: \ Windows \ Microsoft.NET \ Framework64 \ v4.0.30319 \ RegAsm.exe)

Cómo funciona este complemento

Atraviesa todo el árbol DOM, reemplazando el texto, configurado usando el botón, solo con un fondo amarillo. Si hace clic en los textos amarillentos, llama a una función de JavaScript que se insertó en la página dinámicamente. ¡La palabra predeterminada es 'navegador', por lo que coincide con muchos de ellos! EDITAR: después de cambiar la cadena a resaltar, debe hacer clic en el cuadro URL y presionar Enter ... F5 no funcionará, creo que es porque F5 se considera como 'navegación', y requeriría escuchar el evento de navegación (tal vez). Trataré de arreglar eso más tarde.

Ahora es hora de irnos. Estoy muy cansado. Siéntase libre de hacer preguntas ... es posible que no pueda responder ya que me voy de viaje ... en 3 días estoy de regreso, pero intentaré venir aquí mientras tanto.


2
Hola, hice exactamente lo que se describe en la respuesta. El botón está apareciendo. Se ejecuta la función ejecutiva. Sin embargo, las funciones SetSite y GetSite nunca se llaman. Quiero poder saber la URL de la página en la que estoy. No se puede llamar a estos métodos para inicializar el navegador. Por favor, ayuda
mustafabar

3
Traté de hacer esto en IE9 y: 1. Si la ruta de su proyecto tiene espacios: en lugar de $(TargetDir)$(TargetFileName)usar "$(TargetDir)$(TargetFileName)" 2. Si usa Visual Studio 2010 Express, probablemente (lo haga) no vea la opción Iniciar programa externo en la pestaña Depurar - I simplemente ejecute IE y navegue a la URL provista 3. Parece que no funciona en IE9 : puedo abrir el formulario (opciones de resaltador) pero no sé cómo hacer que resalte el texto
pinus.acer

8
Para la referencia Interop.SHDocVw: en su lugar, debe agregar una referencia COM a "Microsoft Internet Controls" y luego "usar SHDocVw";
Eric Hartford

8
"IE10 en x64 Windows 8 no cargará su complemento al iniciar a menos que construya con la arquitectura" Cualquier CPU "y se registre utilizando RegAsm.exe de 32 y 64 bits". fue una edición de alguien que fue rechazado.
Matsemann

3
Consulte el seguimiento: stackoverflow.com/questions/22953571/…

12

Otro enfoque genial sería revisar:

http://www.crossrider.org

Es un marco basado en JS con jquery que le permite desarrollar extensiones de navegadores para IE, FF y Chrome utilizando un único código JS común. Básicamente, el marco hace todo el trabajo desagradable y te queda escribir tu código de aplicaciones.


Sí, este es realmente el camino a seguir, además de evitar la pesadilla que está desarrollando un complemento en Visual Studio, significa que solo tienes que escribir tu complemento una vez para todos los navegadores. También significa no tener que desarrollar en una máquina virtual si eres un usuario de Mac.
opsb

11

El estado de las extensiones de IE es bastante triste. Tienes el antiguo modelo de IE5 Browser Helper Object (sí, esos BHO infames que a todos les gustaba bloquear en el día), barras de herramientas y los nuevos aceleradores para IE. Incluso entonces, la compatibilidad se romperá a veces. Solía ​​mantener una extensión para IE6 que rompió con IE7, por lo que hay algunas cosas que han cambiado. En su mayor parte, hasta donde yo sé (no he tocado BHO en años) todavía necesita codificarlos usando Active Template Libraries (algo así como un STL para COM de Microsoft) y, como tal, es solo para C ++. Podría hacer COM Interop con C # y salirse con la suya en C #, pero probablemente será demasiado difícil para lo que vale. De todas formas,

http://msdn.microsoft.com/en-us/library/aa753587(v=vs.85).aspx

Y para los aceleradores que son nuevos en IE8, puede verificar este.

http://msdn.microsoft.com/en-us/library/cc289775(v=vs.85).aspx

Estoy de acuerdo en que la documentación es terrible, y las API están bastante desactualizadas. Aún así espero que esto ayude.

EDITAR: Creo que puedo arrojar una última fuente de información aquí. Estaba mirando mis notas de atrás cuando estaba trabajando en BHO. Y este es el artículo que me ayudó a comenzar con ellos. Es un poco viejo, pero tiene una buena explicación de las interfaces ATL que usará cuando trabaje con IE BHO (IObjectWithSite, por ejemplo). Creo que está bastante bien explicado y me ayudó mucho en ese entonces. http://msdn.microsoft.com/en-us/library/bb250436.aspx También verifiqué el ejemplo que GregC publicó. Funciona con al menos IE8, y es compatible con VS 2010, por lo que si desea hacer C # puede comenzar allí y echar un vistazo al Libro de Jon Skeet. (C # in Depth 2nd edition) El Capítulo 13 tiene una buena cantidad de información sobre las nuevas funciones en C # 4 que puede usar para hacer que la interacción con COM sea más agradable. (Todavía te recomendaría hacer tu complemento en C ++)


6

Desarrollar C # BHOs ​​es un dolor de cabeza. Implica una gran cantidad de código COM repugnante y llamadas p / invoke.

Tengo un C # BHO en su mayoría terminado aquí , que puede usar libremente la fuente para lo que quiera. Digo "principalmente" , porque nunca descubrí cómo guardar datos de aplicación en el Modo protegido de IE .


44
C # 4.0 podría ser mejor en este sentido, ya que la interoperabilidad COM ha mejorado mucho.
Robert Harvey

@Robert: ¿En serio? No tenía idea ... ¿cuáles son las diferencias?
user541686

@Mehrdad: Puedes ver las diferencias aquí: devx.com/dotnet/Article/42590/1954 . Para una discusión más profunda, vea la charla de Anders Hejlsberg, "El futuro de C #", aquí: channel9.msdn.com/Blogs/pdc2008/TL16
Robert Harvey

1
@Robert @Mehrdad: En realidad no. No es la interoperabilidad COM lo que es desagradable (a este respecto) , está desarrollando y registrando un módulo COM, con lo que las nuevas características de C # 4.0 no ayudan.
BlueRaja - Danny Pflughoeft

4

Llevo años trabajando con el control de navegador web de IE y, a lo largo de ellos, aparece un nombre una y otra vez con publicaciones útiles: Igor Tandetnik

Si estuviera desarrollando una extensión, apuntaría a un BHO y comenzaría a buscar en Google:

BHO Igor Tandetnik

O

Navegador Ayudante Objeto Igor Tandetnik

Sus publicaciones son a menudo muy detalladas, y él sabe de lo que está hablando.

Te encontrarás hasta tus oídos en la programación de COM y ATL. Para ver un tutorial de muestra, consulte: http://msdn.microsoft.com/en-us/library/ms976373.aspx


El mayor inconveniente de usar C # (que es la dirección en la que se dirigen la mayoría de los otros carteles) es que pasará por todo tipo de capas adicionales, con soluciones y parches para el código que sería nativo de C ++.
Lynn Desmoronando el



3

Obviamente está resuelto, pero para los demás usuarios, recomendaría el framework SpicIE . He hecho mi propia extensión basada en ella. Solo es compatible oficialmente con Internet Explorer 7/8, pero lo probé en Internet Explorer 6-10 (desde Windows XP hasta Windows 8 Consumer Preview) y funciona bien . Desafortunadamente, hubo algunos errores en la última versión, por lo que tuve que corregirlos e hice mi propia versión: http://archive.msdn.microsoft.com/SpicIE/Thread/View.aspx?ThreadId=5251


0

¡Te sugiero calurosamente esta publicación de Pavel Zolnikov publicada en 2002!

http://www.codeproject.com/Articles/2219/Extending-Explorer-with-Band-Objects-using-NET-and

Se basa en el uso de objetos Band y se compila utilizando .Net 2.0. El código fuente se proporciona y se abre y se compila bien con Visual Studio 2013. Como leerá en los comentarios de la publicación, funciona perfectamente bien para IE 11 y Windows 7 y Windows 10. Me funcionó perfectamente bien en Windows 7 + SP1 e IE 11 ¡Disfruta!


Nos gusta que las respuestas sean independientes en StackOverflow. Todo lo que esta publicación realmente me dice es "usar objetos Band y .Net 2.0". ¿Podría incluir algún código de muestra aquí para mostrar cómo se puede hacer?
Teepeemm

0

La pregunta es de 2013, ahora es 2020, pero puede ser útil para futuros visitantes.

Traté de implementar la respuesta de @Miguel Angelo, no funcionó al principio.

Todavía hay algunas configuraciones que se definirán.

en Internet Explorer (estoy usando IE-11) vaya a Tools-->Internet Options-->Advanced: ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

También vea esta pregunta SO y este ejemplo de github


-2

ingrese la descripción de la imagen aquí

En la pestaña Eventos de compilación, establezca la línea de comando de eventos posteriores a la compilación en: (x64) se enumera a continuación

"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)"

Quiero la pestaña Eventos de compilación, establezca la línea de comando de eventos posteriores a la compilación en (sistema operativo de 32 bits)

"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)"
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.