Advanced C# Programming: Developing IE Extensions


Desktop-as-a-Service Designed for Any Cloud ? Nutanix Frame

Browser extension software lives inside the browser, adding new features that make the browser suitable for specific personal or business needs. The most common business needs, which are easily accomplished with browser plugins are:

  • modify default search
  • add side frames
  • inject new content into existing webpage
  • communicate with remote servers or web services
  • search highlight
  • show ads
  • any other task that an intalled software program can do

In this article I will explain how to insert new static and dynamic content into anexisting webpage.

The Business Use Case: You want to develop an Internet Explorer extension that shows some fixed layer containing promotional offers and discounts for the goods you are selling.

To achieve that you need to develop a custom IE plugin using Browser Helper Objects (BHO) that will track user browsing activities and display your discounts based on some content keywords filtering.

So far so good. You know what should be done. Now let's discover how it is done.

I will explain, step-by-step, how to accomplish this task as it is better to learn how to do it instead of using a ready-made solution since you don't know how ready-made solutionswork and the moment you touch something to make it suit your needs it breaks down and you have no idea why. I will use .NET C# as a programming framework and language.

Step by Step Walk-through

1. Open your MS Visual Studio 2010.

2. Create a new project "Visual C$" -> "Windows" -> "Class Library" named "IEPlugin"

A new project is opened for you containing a single class "Class1". Rename the class to "BHO". You can use F2 on the CS file in the solution explorer.

Now you have to define the IObjectWithSite interface which the BHO class will implement. The IObjectWithSite interface provides simple objects with a lightweight siting mechanism (lighter than IOleObject). Often, an object must communicate directly with a container site that is managing the object. Outside of IOleObject::SetClientSite, there is no generic means through which an object becomes aware of its site. The IObjectWithSite interface provides a siting mechanism. This interface should only be used when IOleObject is not already in use. By using IObjectWithSite, a container can pass the IUnknown pointer of its site to the object through SetSite. Callers can also get the latest site passed to SetSite by using GetSite.

3. Add references and imports to the following components

using System.Runtime.InteropServices; 
using SHDocVw;
using mshtml;

4. Define the IOleObjectWithSite interface just above your BHO class declaration/.

    public interface IObjectWithSite
        int SetSite([MarshalAs(UnmanagedType.IUnknown)]object site);
        int GetSite(ref Guid guid, out IntPtr ppvSite);

5. Now make the BHO class implement the IOleObjectWithSite interface.

    public class BHO : IObjectWithSite
        private WebBrowser webBrowser;

        public int SetSite(object site)
            if (site != null)
                webBrowser = (WebBrowser)site;
                webBrowser.DocumentComplete += new DWebBrowserEvents2_DocumentCompleteEventHandler(this.OnDocumentComplete);
                webBrowser.DocumentComplete -= new DWebBrowserEvents2_DocumentCompleteEventHandler(this.OnDocumentComplete);
                webBrowser = null;

            return 0;


        public int GetSite(ref Guid guid, out IntPtr ppvSite)
            IntPtr punk = Marshal.GetIUnknownForObject(webBrowser);
            int hr = Marshal.QueryInterface(punk, ref guid, out ppvSite);
            return hr;

        public void OnDocumentComplete(object pDisp, ref object URL)
            HTMLDocument document = (HTMLDocument)webBrowser.Document;


We have implemented the SetSite and GetSite methods and added an empty event handler for the document load event. Thus, we will receive an event every time the document is loaded into the browser.

6. Now we have to implement the OnDocumentComplete method to insert the Javascript code and the div element like this:

        public void OnDocumentComplete(object pDisp, ref object URL)
            HTMLDocument document = (HTMLDocument)webBrowser.Document;

            IHTMLElement head = (IHTMLElement)((IHTMLElementCollection)document.all.tags("head")).item(null, 0);
            IHTMLScriptElement scriptObject = (IHTMLScriptElement)document.createElement("script");
            scriptObject.type = @"text/javascript";
            scriptObject.text = "function hidediv(){document.getElementById('myOwnUniqueId12345').style.visibility = 'hidden';}";

            string div = "<div id=\"myOwnUniqueId12345\" style=\"position:fixed;bottom:0px;right:0px;z-index:9999;width=300px;height=150px;\">" + 
                "<div style=\"position:relative;float:right;font-size:9px;\"><a href=\"javascript:hidediv();\">close</a></div>" +
                "My content goes here ...</div>";

            document.body.insertAdjacentHTML("afterBegin", div);

First we inject the Javascript that we will use to close the div popup. Then we inject the HTML for the div element in the body with style that it is displayed in the bottom right corner of the browser. And that it is. You may want to filter our URLs and content for which you display the div. You can go like this:

        public void OnDocumentComplete(object pDisp, ref object URL)
            if (URL.ToString().Contains("www.google.com"))
                // Show div in here ...

7. Register your BHO to be loaded by the Internet Explorer like:

        public const string BHO_REGISTRY_KEY_NAME = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Browser Helper Objects";

        public static void RegisterBHO(Type type)
            RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(BHO_REGISTRY_KEY_NAME, true);

            if (registryKey == null)
                registryKey = Registry.LocalMachine.CreateSubKey(BHO_REGISTRY_KEY_NAME);

            string guid = type.GUID.ToString("B");
            RegistryKey ourKey = registryKey.OpenSubKey(guid);

            if (ourKey == null)
                ourKey = registryKey.CreateSubKey(guid);

            ourKey.SetValue("NoExplorer", 1, RegistryValueKind.DWord);


        public static void UnregisterBHO(Type type)
            RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(BHO_REGISTRY_KEY_NAME, true);
            string guid = type.GUID.ToString("B");

            if (registryKey != null)
                registryKey.DeleteSubKey(guid, false);

The register method simply tells IE which is the GUID of your extension so that it can be loaded. The "No Explorer" value simply says that we don't want to be loaded by Windows Explorer.

Now all you have to do is create a simple installation project that will install your IE plugin or install it manually.

That is all about it! Quick and simple.

About the Author

Rosen Ivanov

Inacent: Offshore Software Development House offers custom software development services. Inacent is specialized in browser addons development. We have delivered hundreds of browser addons. Our company is the most influential provider when it comes to customizing browsers' behavior.

Related Articles


  • 14 errors trying in VS 2017

    Posted by Ahmed on 10/24/2017 05:28am

    Hello, I have to make a BHO to inject script tag into a page. None of the examples including this are working. I am getting "missing directive" error. Even SHDocVw, mshtml are underlined red and says it is unnecessary. Please, can you help? I am using VS 2017

  • Code Issue

    Posted by Chris on 08/01/2015 06:28pm

    The GUID within code section #5 is too long. The fourth set of values has one too many characters. That brings up another question. Should those specific GUIDs be used? Should new ones be generated for the specific compile?

  • Doesnt work

    Posted by Andy on 06/23/2015 02:41pm

    I tried this by making a console app as my exe file. When i run it, nothing happened in my IE browser.

  • Awesome

    Posted by Bilal on 04/14/2015 08:34am

    Awsome share... Saved alot of time... Thanks alot n alot.. :)

  • Javascript events does not work with external.menuArgument

    Posted by Arvind on 11/04/2014 02:00pm

    Hi, I have tried to create toolbar button using BHO. All the events work fine. I can access toolbar button click function. Now I want to create button element inside that which gets created successfully but onclick event of that crated button does not work. Is there any special way to use javascript events with external.menuArgument? Even creating the sample code provided by you everything works but onclick event of anchor 'close' doesnt get called. I am not able to run any javascript event. Any help would be greatly appreciated. Thanks and regards, Arvind

  • In

    Posted by Kirill Shur on 10/04/2012 07:00pm

    [PreserveSig] int SetSite([In,MarshalAs(UnmanagedType.IUnknown)]object site);

  • Question Regarding BHO

    Posted by surseh on 05/30/2012 11:19am

    Hi I studied all ur code.. i have small doubt.. can i change guids [ ComVisible(true), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("Here I can Generate New Guid ") ] and another one is here.. [ ComVisible(true), Guid("Here I can Generate new Guid"), ClassInterface(ClassInterfaceType.None) ] Why these two Guid is created can u explain me plzzzzzzzzzzz

  • student registration

    Posted by hail on 04/03/2012 11:06am


  • A couple of questions

    Posted by IMOsiris on 07/13/2011 10:34pm

    I ran this code as shown (though I did have to change the second guid because it is was not in the right format). When I ran the .exe file, nothing appeared in my IE web browser. I opened and closed it, still nothing. Should I have seen something? And how would I add a custom toolbar button using this code?

  • You must have javascript enabled in order to post comments.

Leave a Comment
  • Your email address will not be published. All fields are required.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date