[GÜNCELLEME] Ben çalışmak için bu cevabı güncelliyorum Internet Explorer 11 içinde, Windows'un 10 x64 ile Visual Studio 2017 Topluluğun . Bu yanıtın önceki sürümü (Internet Explorer 8, Windows 7 x64 ve Visual Studio 2010'da) bu yanıtın altındadır.
Çalışan bir Internet Explorer 11 Eklentisi Oluşturma
Ben kullanıyorum Visual Studio 2017 Topluluğu'nu , C # , .Net Framework 4.6.1 Bu adımlardan bazıları sizin için biraz farklı olabilir, bu yüzden.
Çözümü oluşturmak için Visual Studio'yu Yönetici olarak açmanız gerekir , böylece derleme sonrası komut dosyası BHO'yu (kayıt defteri erişimine ihtiyaç duyar) kaydedebilir.
Bir sınıf kütüphanesi oluşturarak başlayın. Benim InternetExplorerExtension adını verdim .
Bu referansları projeye ekleyin:
- Interop.SHDocVw: COM sekmesi / arama
"Microsoft Internet Controls"
- Microsoft.mshtml: Montajlar sekmesi / araması
"Microsoft.mshtml"
Not: Referans Ekle penceresinde bulabilsem bile MSHTML bir şekilde sistemime kaydedilmedi. Bu, bina sırasında bir hataya neden oldu:
"MSHTML" tür kitaplığı için sarıcı aksamı bulunamıyor
Düzeltmeyi http://techninotes.blogspot.com/2016/08/fixing-cannot-find-wrapper-assembly-for.html adresinde bulabilirsiniz
Veya bu toplu komut dosyasını çalıştırabilirsiniz:
"%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
Aşağıdaki dosyaları oluşturun:
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);
}
}
ve son olarak seçenekleri yapılandırmak için kullanacağımız bir form. Bu formda bir TextBox
ve bir Ok yerleştirin Button
. Set DialogResult için düğmeye Ok . Bu kodu form koduna yerleştirin:
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; }
}
}
}
Proje özelliklerinde aşağıdakileri yapın:
- Montajı bir anahtarla imzalayın;
- Hata ayıklama sekmesinde, set Başlat Dış Program için
C:\Program Files (x86)\Internet Explorer\iexplore.exe
- Hata ayıklama sekmesinde, set Komut satırı bağımsız değişkenleri için
http://msdn.microsoft.com/en-us/library/ms976373.aspx#bho_getintouch
Olayları Oluştur sekmesinde, Yapım sonrası olayları komut satırını şu şekilde ayarlayın:
"% ProgramFiles (x86)% \ Microsoft SDKs \ Windows \ v10.0A \ bin \ NETFX 4.6.1 Araçlar \ gacutil.exe" / f / i "$ (TargetDir) $ (TargetFileName)"
"% windir% \ Microsoft.NET \ Framework \ v4.0.30319 \ RegAsm.exe" / "$ (TargetDir) $ (TargetFileName)" kaydını kaldırın
"% windir% \ Microsoft.NET \ Framework \ v4.0.30319 \ RegAsm.exe" "$ (TargetDir) $ (TargetFileName)"
Dikkat: Bilgisayarım x64 olsa da, x64 olmayan yolun yolunu kullandım gacutil.exe
ve işe yaradı ... x64 için özel olan:
C: \ Program Dosyaları (x86) \ Microsoft SDKs \ Windows \ v10.0A \ bin \ NETFX 4.6.1 Araçlar \ x64 \ gacutil.exe
64bit IE 64bit derlenmiş ve 64bit kayıtlı BHO'ya ihtiyaç duyar. Ben sadece 32bit IE11 kullanarak hata ayıklamak rağmen, 32bit kayıtlı uzantısı da 64bit IE11 çalıştırarak çalıştı.
Bu cevabın bununla ilgili ek bilgi var gibi görünüyor: https://stackoverflow.com/a/23004613/195417
Gerekirse, 64 bit regasmını kullanabilirsiniz:
% windir% \ Microsoft.NET \ Framework 64 \ v4.0.30319 \ RegAsm.exe
Bu eklenti nasıl çalışır?
Eklentinin davranışını değiştirmedim ... açıklama için aşağıdaki IE8 bölümüne bakın.
## IE8 için Önceki Yanıt
Dostum ... bu çok iş oldu! Bunu nasıl yapacağımı çok merak ettim, kendim yaptım.
Her şeyden önce ... kredi hepsi benim değil. Bu, bu sitelerde bulduğum bir derleme:
Ve elbette, cevabımın sorduğunuz özelliklere sahip olmasını istedim:
- Bir şey bulmak için DOM geçişi;
- bir pencere gösteren bir düğme (benim durumumda kurulum için)
- yapılandırmaya devam et (bunun için kayıt defterini kullanacağım)
- ve nihayet javascript çalıştırın.
Ben birlikte çalıştığım bunu nasıl başardığını adım, adım anlatacağız Internet Explorer 8 içinde, Windows 7 x64 notu ben diğer konfigürasyonlarda testi yapamadım .... Umarım anlarsın =)
Çalışan bir Internet Explorer 8 Eklentisi Oluşturma
Ben kullanıyorum Studio 2010, Visual , C # 4 , .Net Framework 4 Bu adımlardan bazıları sizin için biraz farklı olabilir, bu yüzden.
Bir sınıf kütüphanesi oluşturuldu. Benim InternetExplorerExtension adını verdim .
Bu referansları projeye ekleyin:
- Interop.SHDocVw
- Microsoft.mshtml
Not: Bu başvurular her bilgisayarda farklı yerlerde olabilir.
csproj benim referans bölümünde bu içerir:
<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" />
Dosyaları, güncellenen IE11 dosyalarıyla aynı şekilde oluşturun.
IEAddon.cs
IE11 sürümünden aşağıdaki satırları kaldırabilirsiniz:
...
// @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 sürümü ile aynı.
ve son olarak seçenekleri yapılandırmak için kullanacağımız bir form. Bu formda bir TextBox
ve bir Ok yerleştirin Button
. Set DialogResult için düğmeye Ok . Kod IE11 eklentisi için aynıdır.
Proje özelliklerinde aşağıdakileri yapın:
- Montajı bir anahtarla imzalayın;
- Hata ayıklama sekmesinde, set Başlat Dış Program için
C:\Program Files (x86)\Internet Explorer\iexplore.exe
- Hata ayıklama sekmesinde, set Komut satırı bağımsız değişkenleri için
http://msdn.microsoft.com/en-us/library/ms976373.aspx#bho_getintouch
Olayları Oluştur sekmesinde, Yapım sonrası olayları komut satırını şu şekilde ayarlayın:
"C: \ Program Dosyaları (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)" kaydını kaldırın
"C: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ RegAsm.exe" "$ (TargetDir) $ (TargetFileName)"
Dikkat: Bilgisayarım x64 olduğundan, makinemdeki gacutil çalıştırılabilir yolunun içinde sizinkinden farklı olabilecek belirli bir x64 var.
64bit IE 64bit derlenmiş ve 64bit kayıtlı BHO'ya ihtiyaç duyar. 64bit RegAsm.exe kullanın (genellikle C: \ Windows \ Microsoft.NET \ Framework64 \ v4.0.30319 \ RegAsm.exe içinde yaşar)
Bu eklenti nasıl çalışır?
Düğme kullanılarak yapılandırılan metnin yerini sarı bir arka planla değiştirerek tüm DOM ağacını geçer. Sararmış metinleri tıklatırsanız, sayfaya dinamik olarak eklenen bir javascript işlevini çağırır. Varsayılan kelime 'tarayıcı'dır, böylece birçoğuyla eşleşir!
DÜZENLE: vurgulanacak dize değiştirdikten sonra, URL kutusunu tıklamanız ve Enter tuşuna basmanız gerekir ... F5 işe yaramaz, bence F5 'navigasyon' olarak kabul edilir ve navigasyon olayını dinlemek gerekir (olabilir). Bunu daha sonra düzeltmeye çalışacağım.
Şimdi gitme zamanı. Çok yorgunum. Soru sormaktan çekinmeyin ... belki bir seyahate çıkacağımdan beri cevap veremeyeceğim ... 3 gün içinde geri döndüm, ama bu arada buraya gelmeye çalışacağım.