Click here to Skip to main content
Click here to Skip to main content

Internet Explorer Late Binding Automation

By , 9 Jun 2009
 

Introduction

Most developers often need Internet Explorer automation, which basically means opening a browser, filling some forms, and posting data programmatically.

The most common approach is to use shdocvw.dll (the Microsoft Web Browser control) and Mshtml.dll (the HTML Parsing and Rendering Component), or Microsoft.Mshtml.dll which is actually a .NET wrapper for Mshtml.dll. You can get more information about Internet Explorer - About the Browser here.

If you pick the above method and DLLs, let's see some of the problems you may have to deal with:

  • You have to distribute these DLLs because your project would be dependent to these DLLs, and this is a serious problem if you cannot deploy them correctly. Simply do some Googling about shdocvw and mshtml.dll distributing problems, and you'll see what I'm talking about.
  • You have to deploy an 8 MB Microsoft.mshtml.dll because this DLL is not part of the .NET framework.

In this case, what we need to do is use a late binding technique. Writing our own wrappers for the above mentioned DLLs. And of course, we'll do this as it is more useful than using these DLLs. For instance, we won't need to check if the document download operation is complete because IEHelper will do this for us.

Background

What we need to do here is use a late binding technique which is successfully explained here in this article. Thanks to Ariadne for this great article.

The missing point for me here is attaching to COM events which we really need to know for querying if the document download operation is complete.

Here is how we connect to the web browser's events:

private IConnectionPointContainer connectionPointContainer;
private IConnectionPoint connectionPoint;
private int pdwCookie = 0;

private void registerDocumentEvents()
{
    connectionPointContainer = IeApplication as IConnectionPointContainer;
    Guid guid = new Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D");

    connectionPointContainer.FindConnectionPoint(ref guid, out connectionPoint);
    browserEvents = new DWebBrowserEvents2_Helper();

    connectionPoint.Advise(browserEvents, out pdwCookie);
    DocumentStatus ds = DocumentStatus.Instance;
    ds.DownloadComplete = false;
}

After we have attached to the web browser events, we need to use a singleton class to query the document status. That is what DocumentStatus does.

After we get feedback from the DocumentComplete event, we set DownloadComplete to true so our code can flow.

void DWebBrowserEvents2.DocumentComplete(object pDisp, ref object URL)
{
    DocumentStatus ds = DocumentStatus.Instance;
    ds.DownloadComplete = true;
}

And, of course, we need to unregister events when we are done...

private void unregisteDocumentEvents()
{
    connectionPoint.Unadvise(pdwCookie);
    Marshal.ReleaseComObject(connectionPoint);
}

If you are curious about how I wrote those COM wrappers, let me give you a clue: Use Comto.net by aurigma.

Using the code

Simply start a new IEHelper instance. Navigate to the pages you want to be in. Find some input elements by name or ID. Set their values and post them.

IEHelper ie = new IEHelper();
ie.OpenAVisibleBlankDocument();

object p = null;
string url = @"http://mail.google.com/mail/?hl=en&tab=wm";
bool ret = ie.Navigate(url, ref p, ref p, ref p, ref p);

ie.SetValueById("Email", txtUserName.Text);
ie.SetValueById("Passwd", txtPassword.Text);
ie.ClickButtonByName("signIn");

What to do next

What you need to do is fill in the blanks. Because when you download the source code, you'll see that most of the events are not implemented yet. If you think that you need those events, evolve them according to your requirements.

void DWebBrowserEvents2.OnQuit()
{
    throw new Exception("The method or operation is not implemented.");
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

yincekara
Software Developer (Senior) MikroKom Yazilim A.S.
Turkey Turkey
Member
c# , vb6 , mssql , oracle , mysql , asp , asp.net developer.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralUsing POST operationmemberkizhakk29 Jun '10 - 10:41 
Hi,
This is great..
Can anyone show me how to use a POST operation with this control?
for e.g.
 
Thanks
Pratt
GeneralClickButton which has no namememberLehoanq6 Sep '09 - 7:56 
Hi, I like your program a lot. But there's some case it didn't work. For example, if a button is an image, and it is controlled by Javascript, can we detect/simulate the click() action? Here's my html code stuff:
 
  <tr>	
	<td align="left"><a href="javascript:checkdata();" onmouseover="window.status='msg';return true;" onmouseout="window.status='';return true;"><img border="0" src="button_submit.jsp" width="70" height="20" /></a></td>
  </tr>
 
 
Thanks for your sharing!
GeneralRe: ClickButton which has no namememberyincekara6 Sep '09 - 10:18 
I just made a sample. Like i said in the article you need to evolve the class according to your expectations.
 
DispHTMLDocument doc = (DispHTMLDocument)this.getDocument();
HTMLInputElement hie = null;
foreach (object o in doc.all)
{
o
you have o here. check each and every attribute. i 'm sure you'll find something.
check it's innerhtml, source, url etc. and make a method yourself like: clickButtonBySource() for instance...
GeneralRe: ClickButton which has no namememberLehoanq6 Sep '09 - 15:25 
Yeah! It would be nice to try myself, based on what you did!
But i'm not very sure that what is the type of the object that contains the src. I'll try and post my answer if I can find out.
 
Have a great day! Thanks once more!
GeneralRe: ClickButton which has no namememberLehoanq6 Sep '09 - 17:40 
Hi, I see a class from MSHTML, HTMLImgClass, which would be helpful. But i don't know how to overwrite it like the way you did (just like HTMLInputElementClass for example). How did you code like that:
 
    [Guid("3050F5D8-98B5-11CF-BB82-00AA00BDCE0B")]
    [ComImport]
    [TypeLibType((short)0)]
    [ClassInterface(ClassInterfaceType.None)]
    [ComSourceInterfaces("HTMLInputTextElementEvents, HTMLInputTextElementEvents2,.........
    public class HTMLInputElementClass 
    {
    }

GeneralRe: ClickButton which has no name [modified]memberyincekara29 Sep '09 - 1:08 
See my extended mshtml file[^]
modified on Wednesday, March 31, 2010 4:04 AM

GeneralRe: ClickButton which has no namememberdwegmann30 Mar '10 - 21:50 
Hi!
 
First of all: Great work!
I'm interested in your new mshtml.cs which you mentioned in last September.
 
Regards
Dirk
GeneralRe: ClickButton which has no namememberyincekara30 Mar '10 - 22:07 
Check the above link again please. We 've renamed directory over server download instead of downloads. Sorry for not updating here on time. I've correct the link now.
Questionget IE menubar, toolbar click notificationsmembersumedh.shrikrushana15 Jul '09 - 23:44 
Hi All,
 
i am working on project which requires logging user action on internet explorer.
 
I am able to get browsing event using BHO, but not able to log menu bar, toolbar events.
 
your valuable comments required.
 
Please help me!!
 
thanks.
AnswerRe: get IE menubar, toolbar click notifications [modified]memberyincekara15 Jul '09 - 23:56 
You need to check out add-in/add-on/extensibility projects. not automation projects.
for instance :
 
Class for Adding Buttons, Menu Items and Explorer Bars to Internet Explorer[^]
 
Creating and Installing Internet Explorer Context Menu using C#[^]
 
modified on Thursday, July 16, 2009 6:06 AM

GeneralExample of event handling from Form1memberhoncho2610 Jul '09 - 5:27 
Great code! For those of us who are newbies, can you possibly give an example of how to trap one of the events in Form1? I can't figure out which object to create a reference to from the Form. An example: if I wanted to reference the onClick event of the document loaded in the IEHelper, how might I do that?
 
Thanks a lot!
GeneralRe: Example of event handling from Form1memberhoncho2610 Jul '09 - 5:57 
An update, after tinkering some more: I was able to hook up event handlers for browser-level events like "TitleChange" or "NewWindow2", but still haven't a clue on how to get DOM-level event handling.
 
For anyone interested in the browser-level stuff, here is how I did it:
 

a.) First, I defined a public event in the DocumentEvents object, with a delegate handler class:
 
public delegate void OnTitleChangeHandler(string text);
public event OnTitleChangeHandler OnTitleChange;
 
b.) Next, I raise this event from the DocumentEvents object's TitleChange method (commented out the exception, of course):
void DWebBrowserEvents2.TitleChange(string Text)
{
OnTitleChange(Text);
//throw new Exception("The method or operation is not implemented.");
}
 
c.) Finally, I made reference to the DocumentEvents object associated with my IEHelper, then added an event handler to the TitleChange event. Note that I used VB.NET for my test application, having compiled IEHelper into a class library):
 
myDocument = myHelper.browserEvents
AddHandler myDocument.OnTitleChange, AddressOf TitleChange
 
and then:
 
Sub TitleChange(ByVal text As String)
Debug.Print(text)
End Sub
 
Works like a charm!
GeneralRe: Example of event handling from Form1memberyincekara15 Jul '09 - 23:53 
Nice. Congratulations
GeneralRe: Example of event handling from Form1memberhoncho2616 Jul '09 - 3:15 
Thanks! Any hints on how to access document-level events from your MSHTML implementation?
GeneralRe: Example of event handling from Form1memberyincekara16 Jul '09 - 4:01 
You will browse mshtml.dll and see the events which you need to implement. and add to mshtml.cs yourself. You can use Shift+F2, roedle's reflector, or the best is : Com to .net (Aurigma COM to .NET is intended to simplify the migration of COM-based code to .NET. This product allows you create COM wrappers in managed C# code.)
 
for instance: i later add DispHTMLImg class with it's events which is not exist in article's source code for my application. But it is not a good idea to add all interfaces to mshtml com component otherwise your dll would be 8 mb too. Just find events you need to and add them into your mshtml.cs yourself.
 
I hope this helps.
GeneralRe: Example of event handling from Form1memberhoncho2616 Jul '09 - 4:42 
Thanks for the advice. Could you possibly give me an example of how to implement an event through the wrapper interface? It appears to me as if the events in the DispHTMLDocument interface are defined as properties of some sort.
GeneralRe: Example of event handling from Form1memberyincekara20 Jul '09 - 2:38 
[Guid("25336920-03F9-11CF-8FD0-00AA00686F13")]
[ComImport]
[TypeLibType((short)2)]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces("HTMLDocumentEvents, HTMLDocumentEvents2, HTMLDocumentEvents3")]
internal class HTMLDocumentClass //: DispHTMLDocument //IHTMLDocument2, IHTMLDocument3, IHTMLDocument4, IHTMLDocument5, IHTMLDocument6, IHTMLDOMNode, IHTMLDOMNode2, IDocumentSelector, IHTMLDOMConstructor, DispHTMLDocument, HTMLDocument, , , HTMLDocumentEvents_EventHTMLDocumentEvents2_EventHTMLDocumentEvents3_Event
{
}
 
tell me the event you want to handle then i'll give you an example.
There are delegates as event handler. You need to attach them :
for instance :
HTMLDocumentEvents_onclickEventHandler
HTMLDocumentEvents2_onclickEventHandler
HTMLImgEvents_onclickEventHandler
GeneralRe: Example of event handling from Form1memberhoncho2620 Jul '09 - 2:46 
Thanks so much! A simple example involving HTMLDocuments2_onClickEventHandler would be great.
GeneralRe: Example of event handling from Form1memberyincekara20 Jul '09 - 4:23 
see http://www.mikrokom.com/downloads/ieaulbtest_event.zip[^]
GeneralRe: Example of event handling from Form1memberhoncho2620 Jul '09 - 4:32 
Thanks so much. The events fire perfectly, but when I try to access the event object which is passed as a parameter to the handlers, it results in an AccessViolationException followed by a TargetInvocationException. Any ideas what might cause this?
 
Thanks a lot for your help. I'll be sure to post back any discoveries I make while working with this code, for the good of everyone.
GeneralRe: Example of event handling from Form1memberyincekara20 Jul '09 - 4:48 
which event , which object , how you tried to access ? did you make any cast / conversion ? or using debugger's visualizer object ? did you notice that it is IHTMLEventObj actually.
GeneralRe: Example of event handling from Form1memberhoncho2620 Jul '09 - 4:55 
I didn't make a cast on it, no. I was trying to access pEvtObj in the onClick handler, specifically pEvtObj.srcElement.innerHTML. The idea was to try to get the text of a hyperlink I clicked in the document I loaded.
 
It returns this error in the visualizer object or when I try to send the value of that property to a message box.
 
Thanks!
GeneralRe: Example of event handling from Form1memberyincekara20 Jul '09 - 5:24 
You may need to wait for document complete first.
Please Pay Attention : Not the download complete but document complete.
 

See this example:
http://support.microsoft.com/kb/311284
 
or this one :
http://www.dotnetmonster.com/Uwe/Forum.aspx/dotnet-interop/708/hooking-into-HTMLDocumentEvents2-in-design-mode
 
or this one :
http://www.codeproject.com/KB/cs/Attach_BHO_with_C_.aspx
GeneralRe: Example of event handling from Form1memberhoncho2620 Jul '09 - 6:59 
No luck. I made sure to check both DocumentComplete and NavigateComplete after my call to Navigate2 and before I made my call to RegisterDOMEvents. I get a COMException in the returnvalue property of the pEvtObj, as well as the AccessViolations in the majority of the properties of the srcElement object underneath pEvtObj.
 
Here is the COMException:
"Bad variable type. (Exception from HRESULT: 0x80020008 (DISP_E_BADVARTYPE))"
 
Any thoughts?
GeneralRe: Example of event handling from Form1memberyincekara20 Jul '09 - 8:57 
Did you check example links ?
You may e-mail me your project if possible.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 9 Jun 2009
Article Copyright 2009 by yincekara
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid