Saturday, 13 October 2007

How to create browser extensions for IE

OK, this is a strange blog posting as its unfinished, and actually doesnt work!? I wrote this back in February and it has been sitting in draft mode ever since!

The aim was to try and make some sence of how to create a browser helper object (basically a piece of .net which can site within IE and parse pages - but also manipulte the HTML like insert text and stuff). Now I did get a working demo but I changed something and couldnt for the life of me get it working again! I am probably not going to get a chance to revisit this so since I have a pretty good guide getting you probably 99% of the way there I thought I would hand it over to you - if you can let me know where I have gone wrong Ill update the post!

Thanks, and promise all my posts from now on will be complete and working!


First off lets explain what browser extensions are! A browser helper object is some code which you write to interface with Internet explorer - there are many examples, such as the google toolbar.

Im going to talk you through writing a simple c# browser extension which will highlight every html password text box.

Getting Started
Fire up Visual studio 2005 and create a new class library.

References:
Time to add some references (right click on project and select add reference - see image below)

Now change tabs to COM and add "Microsoft Browser Helpers" to your project (you should now see SHDocVw in your references list).

Repeat this and add "Microsoft HTML Object Library" which should add "MSHTML".

COM Interface:
We have added the com components so now we need to create the interface we have to implement. Add a new class to your project and call it "IObjectWithSite.cs". Then copy the following code into it:-



using System;

using System.Runtime.InteropServices;



namespace YourNameSpace!

{

/// <summary>

/// Summary description for IObjectWithSite.

/// </summary>

[

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, out IntPtr ppvSite);

}

}


This allows you to interface with the current displayed html. Rember to change the namespace to your namespace.

The main class:
You will probably want to rename your main class from class1.cs to something more useful. Once you have done that go into the class and make it implement the newly created interface. You also might as well get it to add the GetSite and SetSite methods for you (See the image below)

I have added the following using statements to the top of my page for ease of use:-

using SHDocVw;
using mshtml;
using System.Runtime.InteropServices;
We need a global variable added. This is a pointer to the host IE window.

WebBrowser oPage;

Time to implement the methods required by the interface. Set Site first. This passes in a site object


public int SetSite(object site)

{

if (site != null)

{

oPage= (WebBrowser)site;

oPage.DocumentComplete += new DWebBrowserEvents2_DocumentCompleteEventHandler(this.OnDocumentComplete);

}

else

{

oPage.DocumentComplete -= new DWebBrowserEvents2_DocumentCompleteEventHandler(this.OnDocumentComplete);

oPage= null;

}

return 0;

}
SetSite is called whenever the object is created, and destroyed - pretty basic code. The really important bit is the document complete event (which we will implement in a little bit).

Now to implement GetSite: -


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

{

IntPtr punk = Marshal.GetIUnknownForObject(oPage);

int hr = Marshal.QueryInterface(punk, ref guid, out ppvSite);

Marshal.Release(punk);

return hr;

}
Not really sure where this code gets used - but this is how to implement it!

Time to implment that onDocumentComplete event handler. For now we will simply create a new element on the page and whack some test text in there.


private void OnDocumentComplete(object frame, ref object urlObj)

{

IHTMLDocument2 document = (IHTMLDocument2)oPage.Document;

IHTMLElement oElem = document.createElement("test");

oElem.innerHTML = "TEST!!!";

}
Quite simple really!

COMifiy it
Ok lets add everything we need to in order to make this a COM component.


  1. Right click on the project

  2. Select Properties

  3. Click Assembly Infomation

  4. Check "Make Assembly COM-Visible"

Now back to the main class. You have to generate a GUID, very easy in visual studio 2005. Simply go to Tools and select "Create Guid". Pick Registry Format and click Copy then exit.

We have to add an attribute to the main class with the new guid. In my case this looks like this:

[

ComVisible(true),

Guid("B9215076-8906-4f65-A8D4-CCBEC942D0C2"),

ClassInterface(ClassInterfaceType.None)

]

public class SampleExtension : IObjectWithSite

{

WebBrowser oPage;
Rember to remove the curly brackets when you paste in your guid.

Time for a setup package!
Add a setup package to your solution, then right click on it and select add project output then click ok.
I have to right click and exclude IEFrame.dll - pretty sure its a vista thing. Probably best just to exclude it.
Now right click on the setup package and go to view registry.
You have to add the following keys
\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Extensions\
Now add a key for the guid you generated before (you probably still have it in your clip board) and remember this time to include the curly brackets.
Now select "Primary Output from ..." from your setup package and in the properties change register to "vsdrpCOM".
And thats it! Build it and install it.

2 comments:

dogomogomogo said...

Hello. What are the other event types and how can I find their names?

harshit said...

pls can u provide me sample project, i had try it but it is not executing ;)