BHO Development using managed code


Browser Helper Object (BHO) is a plug-in for Internet Explorer (IE). BHO let developers to drive IE. A plug-in is a program which extends the functionality of a browser. It can be used to retrieve information or modify the content of the webpage that is being displayed in a browser window, or it may just be used to provide the user an option to see the day’s Stock market status or, weather in a toolbar.

To start BHO development can be depressing at the very first beginning to learn all those things. As a beginner I want to share my experience to other beginners. Here I am going to explain the simple implementation of BHO.

A Browser Helper Object is a COM object loaded for each IE window. As a browser window is opened, it creates its own copy of the BHO; and, when the window is closed, it destroys its copy of the BHO. You will need a COM dll which interact with browser. This need to done by implementing the IObjectWithSite in class. We need to use COM interop library to implement COM dll in our dotNet project.

While we are writing in C#, we also need to write the interface IObjectWithSite ourselves. Also, we have to then implement the interface in your BHO. To interact with the HTML document, we will need to add a reference to the Microsoft.mshtml library & to get the DOM or the webpage currently in the browser, we will have to add SHDocVw library as a reference. Also, we will have to add 2 functions which will register (& unregister) our COM component as a BHO with Internet Explorer with the key.

Say Hello to BHO development world:

Let’s create a Hello world project regarding BHO. Start a new C# class library project. I named it as ‘HelloBHOWorld’.



Rename the ‘Class1.cs’ as ‘IObjectWithSite.cs’

Add ‘using System.Runtime.InteropServices;‘ to the class. We need to implement the interface ‘IObjectWithSite’ under this class and we also need to add to function ‘GetSite’ and ‘SetSite’. To know more about this interface, please refer to http://msdn2.microsoft.com/en-us/library/Aa768220.aspx

IObjectWithSite Members

GetSite Gets the last site set with IObjectWithSite::SetSite. If there is no known site, the object returns a failure code.
SetSite Provides the site’s IUnknown pointer to the object.

Under the IObjectWithSite.cs, we need to point out the GUID of IE for our program, so it can attach to IE. The code snippet should look like the following,

using System.Runtime.InteropServices;

namespace HelloBHOWorld

{

//GUID reference of IF

[

ComVisible(true),

InterfaceType(ComInterfaceType.InterfaceIsIUnknown),

Guid(“FC4801A3-2BA9-11CF-A229-00AA003D7352”)

]

//Declaration of the interface

public interface IObjectWithSite

{

[PreserveSig]

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

[PreserveSig]

int GetSite(ref Guid guid, out IntPtr ppvSite);

}

}

We have done with IObjectWithSite.cs. New we need to add another class file named BHO.cs. and add a class ‘BHO’ there. As we mentioned before we need to have two references, SHDocVw.dll and MSHTML.dll. SHDocVw is Microsoft Shell Doc Object and Control Library. MSHTML is the interfaces for accessing the Dynamic HTML (DHTML) Object Model are based on IDispatch and are the basis of access to the object model that is also used by scripts. To know more, please refer to: http://msdn2.microsoft.com/en-us/library/bb498651.aspx

Let’s add them,



We are going to use messagebox to display information, so we need to add another reference,


We need to add the following reference under BHO.cs file,

using SHDocVw;

using mshtml;

using System.IO;

using Microsoft.Win32;

using System.Runtime.InteropServices;

We will need to implement the inerface on BHO class, later we will define the two method.


We need to assign a GUID for our own program under BHO.cs. We can use System.Guid.NewGuid() method to get a new key (I have a small tool to generate GUID). And also we will add two variables into the class, WebBrowser and HTMLDocument.

In BHO.cs file we need to write two functions for register/unregister of this DLL.

public static string BHO_KEY_NAME = “Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Browser Helper Objects”;

[ComRegisterFunction]

public static void RegisterBHO(Type type)

{

RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(BHO_KEY_NAME, true);

if (registryKey == null)

registryKey = Registry.LocalMachine.CreateSubKey(BHO_KEY_NAME);

string guid = type.GUID.ToString(“B”);

RegistryKey ourKey = registryKey.OpenSubKey(guid);

if (ourKey == null)

ourKey = registryKey.CreateSubKey(guid);

ourKey.SetValue(“Alright”, 1);

registryKey.Close();

ourKey.Close();

}


[ComUnregisterFunction]

public static void UnregisterBHO(Type type)

{

RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(BHO_KEY_NAME, true);

string guid = type.GUID.ToString(“B”);

if (registryKey != null)

registryKey.DeleteSubKey(guid, false);

}

Here we will use OnBeforeNavigate() method to retrieve some information from browser. ‘OnBeforeNavigate’ invokes an event before navigation occurs on the web browser. To know more please refer, http://msdn.microsoft.com/en-us/library/2chzz53b.aspx

So next we write the method body of OnBeforeNavigate method and define the ‘SetSite’ and GetSite’ method. On ‘SetSite’ method we write the event handler for OnBeforeNavigate function.

public void OnBeforeNavigate2(object pDisp, ref object URL, ref object Flags, ref object TargetFrameName, ref object PostData, ref object Headers, ref bool Cancel)

{

}

#region IObjectWithSite Members

public int SetSite(object site)

{

if (site != null)

{

webBrowser = (WebBrowser)site;

webBrowser.BeforeNavigate2 += new
DWebBrowserEvents2_BeforeNavigate2EventHandler(this.OnBeforeNavigate2);

}

else

{

webBrowser.BeforeNavigate2 -= new
DWebBrowserEvents2_BeforeNavigate2EventHandler(this.OnBeforeNavigate2);

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

Marshal.Release(punk);

return hr;

}

#endregion

For example we write some code for method ‘OnBeforeNavigate2′. This code will track the input field of the site and show input fields name and value.

public void OnBeforeNavigate2(object pDisp, ref object URL, ref object Flags, ref object TargetFrameName, ref object PostData, ref object Headers, ref bool Cancel)

{

document = (HTMLDocument)webBrowser.Document;

System.Windows.Forms.MessageBox.Show(“URL to redirect: “ + URL.ToString());

foreach (IHTMLInputElement tempElement in document.getElementsByTagName(“INPUT”))

{

System.Windows.Forms.MessageBox.Show(tempElement.name + ” = “ + tempElement.value);

}

}

Register and unregister BHO:

To register/unregister BHO we use ‘RegAsm.exe’ and write to bat file ‘registercom.bat’ and ‘unregisterall.bat’

REM register for com so we can test the register/unregister functions while debugging

regasm.exe /codebase “HelloBHOWorld.dll”

pause

REM unregister HelloBHOWorld.dll for COM

regasm.exe /unregister “HelloBHOWorld.dll”

pause

Run the file ‘registercom.bat’


Now open IE browser and go to ‘Tools’>’Manage Add-ons…’ You should see your BHO is on the list



Now browse any site (google.com), input text on the box and click button. You should see,


So this can be your first add-in for IE. This is just the beginning, long way to go for writing a professional BHO. Let’s hope for the best.

Please don’t forget to drop your comments……………..

Advertisements

4 thoughts on “BHO Development using managed code

  1. nandkumar T. November 27, 2010 / 4:34 pm

    How to do it in ATL

  2. George Ki June 21, 2011 / 11:16 pm

    Holy Friholies batman. Nice. Thanks for all the detail. 🙂

  3. Amruta September 13, 2013 / 6:36 pm

    Hi… I have followed similar steps but i dont see a message box being poped up. The Manage Add on screen shows the extension but i dont see a pop up. Could you please help?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s