Introduction

Microsoft has provided the Browser Helper Object (BHO) to let developers "drive" Internet Explorer. The first BHO was introduced in 1997 with IE 4.0.
I have been writing programs on BHO for months. It could be quite depressing at the very beginning to learn all those things. I am writing this
article to help beginners like me get familiar with BHO as soon as possible.

Background

My personal interest is actually C++. C++ programs can be a lot less memory-consuming than C# programs. But C# does provide better service on BHO compared to C++.
My first BHO program was written in C++. It took me quite a while to figure out how to handle BHO under VC++. But in C#, it only took me a few minutes.
Also, C# has a lot of pleasant features such as foreach and type conversion.

Process

To set up a BHO Hello World project, let us first start a C# Class Library, as BHO is written in a .dll attached to IE.
You don't need Visual Studio 2005; C# Express is totally enough.

After we have this empty project, let's add a folder named BHO and an empty .cs file into the folder.

Add a class called BHO in the newly added file (BHO.cs). The class contains the interface IObjectWithSite.

class BHO:IObjectWithSite

To use BHO, we need to have two references: SHDocVw.dll and MSHTML.dll. You can find them in the Windows\System32 folder. SHDocVw is
a Microsoft Shell Doc Object and Control Library. MSHTML: All 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.
http://msdn2.microsoft.com/en-us/library/bb498651.aspx.

Having using SHDocVw is not enough, you need to add references to the project. Add SHDocVw. Later we are going to use
MessageBox, so we also need to add a Windows Forms reference.

Now in BHO.cs: we add two variables into the class, WebBrowser and HTMLDocument. From their names, you can easily figure out what they do.

Besides the two methods we defined in the IObjectWithSite interface, we also need to add OnDocumentComplete. You can name the function anything you want as long
as the parameters are the same as what's defined in the CDHtmlDialog class. Later you need to carefully attach it to an Event Handler. For consistency of code,
we name it OnDocumentComplete. OnDocumentComplete is a function of
the CDHtmlDialog class (http://msdn2.microsoft.com/en-us/library/8bed8k60(VS.80).aspx.
It will be triggered if the HTMLDocument downloading is complete, in other words, when your page is loaded. You can also use Navigate()
or OnBeforeNavigate(). Please refer to http://msdn2.microsoft.com/en-us/library/8k5z3ekh(VS.80).aspx
to find out what you need exactly.

Now compile; under your Release folder, you will find the .dll of your project.

Then, use regasm /codebase "BHO HelloWorld.dll" to register the DLL. We have a problem here. REGASM will tell us me it's not registered. Why?

Because we didn't set the BHO class as public. That's why.

publicclass BHO:IObjectWiteSite

Now, do it again. It'll be successful.

Open your Registry. Find out the Browser Helper Object under LOCAL_MACHINE->SOFTWARE->MICROSOFT->WINDOWS->EXPLORER.

Now the program is officially attached to your BHO. We need to fill in the OnDocumentComplete function. It's really neat to use C#'s foreach loop rather than
the for loop in C++. Because you don't need to care about the indexer. We will also see the type conversion is quite easy. This is an example of
how find out the NAME attribute of an IHTMLInputElement.

An IHTMLInputElement is an Input element in an HTML page.

If the IHTMLInputElement does not have a name attribute, we will fetch the ID attribute. Then pop up the value.

Conclusion

In conclusion, it is really easy to handle BHO with C#. That is why there are so many IE add-ons. I hope this was useful to you. To save your time, you can use
the project template I made. Download it and put it under your
Visual Studio 2005\Templates\ProjectTemplates folder (it is usually under My Documents).

Share

About the Author

My name is Jia Chen and I want you tell you about my childhood dream: being a problem-solver. My mom told me it was silly because it wasn't really a profession. Through the last decade, I have been a software engineer, a product manager, a repetitive student, a management consult and an entrepreneur. They appear far from my childhood dream. But I still think I am living it. Because the essence of it is to find problems and solve problems. Some times I may not solve new problems, but I always want to solve old problems in a new way.

Its very nice article and i have installed it in my browser and i can see the mscoree.dll but it is not working and now i want to unregister the dll and try to reinstall but i got error while unregister the dll and i got error as under

RegAsm : error RA0000 : Unable to locate input assembly 'Classlibrary1.dll'
or one of its dependencies.

Using C# express, I followed your article and wanted to post corrections needed for the next person.

BHO class needs these references:
using SHDocVw;
using mshtml;
using Microsoft.Win32; <-----Needed for RegistryKey references.
using System.Runtime.InteropServices;
using System; <-----This one must be there to avoid Intptr and Guid compile errors.

Note: Read the section on compiler attributes carefully. The interface doesn't take all of the same attributes as the BHO class.

Finally, this solution appears to be good when you want to interface to the native IExplorer browser. However, virtually all of this function is available for the webBrowser object which you can embed into your own form. The webBrowser object is much easier to use (IMO).

I had created a small application from the article http://www.codeproject.com/KB/cs/Attach_BHO_with_C_.aspx?fid=447248&df=90&mp p=25&noise=3&sort=Position&view=Quick&fr=51&select=2421069
But while the control is in "foreach loop", the CPU usage increases near about 80-90%. I just want to reduce that CPU usage.

The other thing is if I try to manipulate the web page text, the original text is visible to user for a fraction of second, and then the replaced text is visible to user. I don't want that original text is visible to user. I just want to replace the original text of a web page on the fly, for the I am using DWebBrowserEvents2_ProgressChangeEventHandler.

In the foreach loop I was identifying the tagname and replacing the innertext of tag element.
I want the replaced text should be seen directly by the user. But there was some delay in displaying the replaced text. i.e., initially for a fraction of second the original text is visible to user before the replaced text.

How can I avoid these two problems and the output should be...

1. User should be seen directly the replaced text but not the original text of a web page.
2. The CPU usage should be reduced which is caused because of "foreach loop".

As well as I was trying to identify individual tag elements using
http://www.codeproject.com/KB/shell/enum_selected_elements.aspx?
in which IMarkupServices interface is used. Here also same problem occurs. There is some delay in displaying the replaced text on the web page.

But the main problems are:
1. Delay in display of replaced text on a web page when it is visible to the user
2. The CPU usage is high which is caused because of "foreach loop".

I manipulated by innertext property of HTML tag elements in a foreach loop.
This has been developed from
http://www.codeproject.com/KB/cs/Attach_BHO_with_C_.aspx?fid=447248&df=90&mp p=25&noise=3&sort=Position&view=Quick&fr=51&select=2421069

How can i solve this.........

Any suggestions would have been appreciated.

I had spent so much time on these but are of no use.

I tried all these links but output is samea nd my problems can't be avoided.

The BHO shows up in the browser as mscoree.dll even though the registered DLL is TestBHO.dll or something like that. Is there someway to change the name of the DLL to something that I choose? Where is the setting located to name the registered control as mscoree.dll?

Hi,
Great article.
I just downloaded the Source code, and build it and registered.

After registering the dll, if I open IE, the CPU usage is shown as 40-50% and sometimes even 100%.
Even when I try to build the solution provided, VCSExpress.exe also consumes 100% CPU usage. How to reduce this?

I downloaded the code and compiled, after run regasm to register, I opened IE, tried several sites, but no message box shown up. it is strange, I checked the Add-ons enabled in IE, I found the file for the BHO_HelloWorld.BHO is mscoree.dll, is that the correct dll? Thanks a lot.

When displaying a secure web page, Internet explorer shows a small
yellow padlock in the bottom right corner. When hovering over the
padlock it says something like "SSL Secured (128 Bit)". When
double-clicking it, Internet Explorer opens a new window that displays
detailed information on the server's certificate (e.g., Issuer, Valid
From-To, Subject, Public Key, etc.). That's the information I'm
trying to get from a running instance from Internet Explorer!
Is it possible to get the information using BHO?
Thanks

Here's a strange one -- I compile and register your BHO on my dev box (Windows XP SP2, IE 6.0) and everything works fine. Events are fired properly and message box is displayed.

But, on a test box running IE 7 (Windows XP SP3), the BeforeNavigate2 and DocumentComplete events do not get fired. The BHO appears to be loaded properly -- I can see it listed under Tools->Manage Add-Ons->Enable or Disable Add-Ons, and the BHO is enabled.

I put some debug message boxes into GetSite and SetSite and those methods appear to be called correctly when IE starts up. Any ideas why BeforeNavigate2 and DocumentComplete aren't called?

first thanks alot this is one of the best article that exist, it's a good point to start for beginners realy thanks alot.

but i have a problem it seems that nothing happens when i open a simple application with webbrowser control embedded in it, nothing happens either with internet explorer

the registry was registered successfully it is there i saw it, i also unregistered and registered again with your example and the
"enable third party is checked" but nothing seems to work please can you try to solve this problem i realy need to learn how to do that.

This is Good article , It Works On Windows Browser But.........
I want this same Functionality of BHO
On PPC Or WM 5.0,
i tried this article but no use.
So Please Help Me.
I do not want to use VC++ Or ATL , i am interested in C# only

Hi, my question is kinda general for IE plugins but i'll make it specific using the example of youtube flash object. This control is available via the javascript model (http://code.google.com/apis/youtube/js_api_reference.html)I want to be able to call its functions from plugin code and get the values. This includes also being able to call it's events addition methods. I think this is not possible directly via code but i'm not sure...can somebody say if this is something possible?

What i'm thinking to do now is along the line of:1. create a Hidden element on every page i want to probe, using the plugin interface (i can create new elements)2. attach to the above hidden element value change event via the plugin3. run IHTMLWindow2::execScript with a script that will call the object method and place the value in the hidden element. Now i can detect the value change event via the plugin and get whatever i want. (i.e. onvaluechange event is possible to attach to from the plugin).

for events i can do something similar - i.e. write a handler that will place a value in the hidden element.

found it myself.
i just need to get a handle to the flash object and can make call via the flash external API
(http://livedocs.adobe.com/flex/201/html/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Book_Parts&file=19_External_Interface_178_5.html).

still getting problems on registering to events...for some reason my calls to the addEventListener of the youTube object don't result in anything that i get in the BHO...i left a question in their forum. will update.

To register the typelibs for the mshtml stuff. This isn't registered by default on non-development machines. You'll also need to copy the file over to your directory, it's big - this is not normally installed unless you are installing Visual Studio.

Another article around here on c# BHOs used a subset of the mshtml interface ibraries to get around this.

hi,
I've developed BHO with C# following the steps in this article.For every IE window opened BHO is instansiated.This i ensured by putting a message box in constructor of my BHO.But the SetSite method is not calling.With out this method i cant do what i need. I'm unable to find source of this problem ?? how to fix this ?

Dear:
I've saw your code .well. I want to use IDispatch::Invoke() to handle events, I want to use Iconnectpoint::advise() to recall IDispatch::Invoke(),but advise() always throw an error no.CONNECT_E_CANNOTCONNECT .would you like giving me an example or some pieces of codes.
thank you!
regards
vincent
2008.5.29

This article does not cover one thing: Handling events generated from mshtml elements.
For anyone interested in handling the events in C# AND avoiding reverting to long-winded ATL biolerplate, the following link may be helpful:

I could not find any MSDN articles covering mshtml events with C#. And many of the C++ samples are no longer available on MSDN (archived/deleted?)
I wonder if future versions of IE will have more documented BHO/addon APIs?

To be honest, I never did that before. To the best of my knowledge, I think it's feasible. It's some basic windows operation.I think the best place to raise such question is MSDN forum. I am really sorry that I don't have much experience on this specific question. But I am certain there will be people who are capable of helping you solve it.

Sorry!

We must learn to be equally good at what is short and sharp as what is long and tough.

First, let me say thanks for a great article. Your article describes almost everything I needed to know to write the BHO I need to write.

However, I've duplicated your steps as best as I can and my BHO does not seem to get called. I have checked and double checked everything I can think of. I registered my BHO with regasm and then checked the registry with regedit and I see that the GUID for my BHO object is correctly added under the right key in the registry (there are other BHOs registered there, so I am fairly certain that is all working fine). But when I run IE, I don't see the effect my BHO is coded to produce -- specifically for testing purposes I am just changing the title of every page to a hardcoded string so I can see that everything is working.

So, I tried attaching to IE with the debugger and setting breakpoints both in the SetSite method and the OnDocumentComplete callback method and neither of my breakpoints is being hit.

I am out of ideas on what could be going wrong. Do you have any advice on where I should be looking for problems?

I found one more piece of relevant information that I am not sure how to interpret -- I checked in IE->Tools->Manage Add-ons and my add on shows up there, but under the "File" column it shows "mscoree.dll" instead of my .DLL name. My guess is this is the problem, but I don't know why its happening or how to get rid of it? Maybe the GUID I generated was bad/overlapped with an existing .DLL? I will try a different GUID but the chances of that seem so small that I doubt that is the problem.