views:

754

answers:

1

I have an IE BHO that's in development in C#. It is supposed to wait for the user to do some stuff, contact our server and download some data, and then alter the DOM of the currently loaded web page with the results.

I am running into some seemingly insurmountable issues relating to the rules of COM compartmentalization and threading -- namely, I can't seem access the IE DOMDocument outside of the current thread and I can't think of any way to run something asynchronously without locking up IE until it's finished.

My first attempt had the background server-communication stuff do its thing in an event-driven fashion: my program would initiate communications from within an mshtml event (BeforeNaviagate2 or DocumentComplete, for example), and would post the results from within a separate event handler fired by the server communication object when it finished its work.

That techniqued worked fine in a quick simulator I cobbled together (just a simple app with a WebBrowser control) but in IE it would throw a COM exception because I was attempting to alter page DOM through a separate thread.

So I tried keeping everything in the same function, and having my code wait for the server communications object to do its work with a while loop, like this:


    int waited = 0;
    while (!OurServerCommRequest.ready) {
     System.Threading.Thread.Sleep(1);
     Application.DoEvents();
     waited++;

     if (waited > constants.TIMEOUT_OURSERVER_REQUEST) {
      log.wL("Timed out");
     }

    }

The problem with this approach is while the code stays in the original thread, it executes synchroniously with the IE process it fired in (in IE8, it's one process per tab -- like Google Chrome -- it seems) ... therefore locking up the IE interface until my server communications completes.

Initially I wanted to start processing as soon as the URL was available (via NavigationComplete2 event) but I discovered that waiting for the <body> tag to become available should my server communications finish before the user's page loaded would also lock up IE -- throwing it into an infinite loop while my code waits for the HTML body, while the page is prevented from updating itself do to the aforementioned loop.

I've thought about moving all this into the actual user's page javascript but it seems that by doing so I am opening up a can of worms in wrangling with XSS security issues.

So... my question is such: is it possible to run code asynchroniously in an C# IE BHO while still being able to manipulate the user's page DOM? I've asked around some friends and most people tell me that it is not likely. I'm still new at COM and C#, having come from C/VB.net/JS/AS.

Thank you!

-Tom

+1  A: 

You need to marshal the DOM object from the thread it was created on to your worker thread. Here is a very detailed breakdown of how COM and C# play together.

All of the IE DOM objects are STA objects.

jeffamaphone
Thank you. Am reading now!
Tom the Junglist