Tag Archive for 'browser helper object'

making an Internet Explorer add-on

I was recently doing a project to make an add-​on for Inter­net Explorer. How do I put it? I must say that was an extremely frus­trat­ing expe­ri­ence. The doc­u­men­ta­tion is severely lack­ing, if not non-​existent. One page from MSDN (which states the psarray is a BSTR is even dead wrong).

I have never been more moti­vated to con­tribute to the scene by writ­ing my own “Internet Explorer add-​on writ­ing sur­vival guide” sort of thing, but then I real­ized Pete has beat me to it by open­ing an entire [bho-wiki][wiki].

Nev­er­the­less, I’m writ­ing this arti­cle so more people can find these scarce infor­ma­tion on IE add-​on. On the other hand, here are some thoughts I had when writ­ing the IE add-​on. If you’re about to write an IE add-​on, these would prob­a­bly be the “survival guides” you’re using (as there aren’t many).

1. An IE add-​on is a Browser Helper Object (BHO)

To save you some time search­ing in vain, try using BHO in your Google searches. This would give you programming-​related infor­ma­tion instead of where to down­load the latest IE add-​on product.

2. Use C#

C++ just plain sucks, in terms of writ­ing an IE add-​on. Don’t get me wrong here, the lan­guage is mar­velous, but Microsoft’s sup­port just seems broken and unfin­ished. The whole Win32 hack­ing, COM stuffs involved when using C++ just makes your life 10 times more difficult.

The inter­face for C# is much more usable, and you won’t have to deal with all the bull­shits when pro­gram­ming in the out­dated (and most prob­a­bly unmain­tained) Win32 API.

Another major issue with C++ is Visual C++ 2008 Express. It doesn’t come with ATL, which means a ridicu­lous amount of grunt work deal­ing with point­ers, releas­ing and stuffs (as illus­trated below, as I hap­pened to use VC++ Express). VC# doesn’t have this prob­lem and it even has a number of libraries built-​in (such as reg­u­lar expressions).

Exam­ple 1: getEle­ment­ById from BHO

Using C++ IHTMLCollection * elements; HRESULT hr = document->get_all ( &elements ); assert ( SUCCEEDED ( hr ) );

long numElements; hr = elements->get_length ( &numElements ); assert ( SUCCEEDED ( hr ) );

IHTMLElement * element;

for ( int i = 0; i < numElements; i++ ) { VARIANT index; index.vt = VT_I4; index.intVal = i;

IDispatch * elementDispatch;

hr = elements->item ( index, index, &elementDispatch ); assert ( SUCCEEDED ( hr ) );

hr = elementDispatch->QueryInterface ( IID_IHTMLElement, (void **)&element ); assert ( SUCCEEDED ( hr ) );

elementDispatch->Release();

// After all this hard work, we have finally obtained our element! // GetAttribute is a custom function, I didn't even bother to // list out it's content here if ( GetAttribute ( element, L"id" ) == id ) break; else { element->Release(); element = NULL; } }

elements->Release(); return element;

Using C# document.getElementById(id); Exam­ple 2: exe­cute some Javascript

Using C++ BSTR code = SysAllocString ( L"alert ( 'Hello World' );" ); BSTR language = SysAllocString ( L"javascript" ); VARIANT result = {0};

window->execScript ( code, language, &result );

SysFreeString ( code ); SysFreeString ( language ); Using C# window.execScript ( "alert ( 'Hello World' )", "javascript" ); 3. Use jQuery for DOM manipulation

jQuery is a client side JavaScript library to sim­plify common tasks (the “write less, do more” library as they say). I found it delight­fully pleas­ant to use. It has some pow­er­ful func­tions like CSS selec­tors that would be a pain in the ass to imple­ment in BHO. With jQuery, you can do stuff like: // Find all the <a> elements with class "bookmark" and // target attribute "_blank" and hide // them smoothly using a slow slide up animation

$('a.bookmark[@target="_blank"]').slideUp("slow"); To use jQuery, simply use execScript to load the jQuery file on doc­u­ment complete.

4. About XmlHttpRequest

Fetch­ing exter­nal Web pages using client side JavaScript will give you a per­mis­sion denied error because of the cross-​domain poli­cies of most modern browsers. Xml­HttpRe­quest must be done in the BHO. Sven offers an exam­ple code to use IXml­HttpRe­quest, which is very valu­able con­sid­er­ing the lack of offi­cial doc­u­men­ta­tion. Pete has rolled his own CPete­HttpRe­quest class using WinHttp.

(Strangely enough, both of the above are coded in C++. I have yet to come across an equally effi­cient way to do Xml­HttpRe­quest in C#. Please feel free to leave a com­ment if you have good ideas)