Posts Tagged 'WebBrowser'

WebBrowser.DocumentComplete Firing Multiple Times: Solution

My previous hunch was correct: before you do any actual work in the DocumentComplete event handler, make sure the ReadyState of the control equals “Complete”.

Here’s the updated diagnostic output: notice the time taken drops to three seconds now that I’m not looping through the worker code eleven different times.

'Snapper.WinForm.vshost.exe' (Managed): Loaded 'C:\Windows\assembly\GAC_MSIL\System.Configuration\2.0.0.0__b03f5f7f11d50a3a\System.Configuration.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
Uninitialized
Uninitialized
Uninitialized
Uninitialized
Uninitialized
'Snapper.WinForm.vshost.exe' (Managed): Loaded 'C:\Windows\assembly\GAC\Microsoft.mshtml\7.0.3300.0__b03f5f7f11d50a3a\Microsoft.mshtml.dll'
Interactive
Interactive
Interactive
Interactive
Interactive
Interactive
Interactive
Interactive
Interactive
Interactive
Interactive
Interactive
Interactive
Interactive
12/29/2007 1:15:03 PM - DocumentCompleted!
12/29/2007 1:15:03 PM - DocumentCompleted!
Interactive
Interactive
Interactive
12/29/2007 1:15:03 PM - DocumentCompleted!
12/29/2007 1:15:03 PM - DocumentCompleted!
Interactive
Interactive
Interactive
Interactive
Interactive
12/29/2007 1:15:05 PM - DocumentCompleted!
12/29/2007 1:15:05 PM - DocumentCompleted!
Interactive
Interactive
Interactive
Interactive
Interactive
Interactive
12/29/2007 1:15:05 PM - DocumentCompleted!
12/29/2007 1:15:05 PM - DocumentCompleted!
12/29/2007 1:15:05 PM - DocumentCompleted!
12/29/2007 1:15:05 PM - DocumentCompleted!
Interactive
12/29/2007 1:15:06 PM - DocumentCompleted!
Complete
12/29/2007 1:15:06 PM - DocumentCompleted!
Doing work..

It’s probably also the case that the WebBrowserDocumentCompletedEventArgs parameter of the DocumentCompleted event handler gives me additional info with which to discriminate this ReadyState. May have to look into that one.

WebBrowser.DocumentCompleted Firing Multiple Times

I’m running in to the same problem that Adi ran into wherein the DocumentCompleted event of the WebBrowser control is firing more than once. Sometimes a lot of times!

Seems to me that this should be a Once and Only Once type of thing.

Here’s my diagnostic output when I open techcrunch.com: the timestamped lines are the DocumentCompleted events; the others are the ProgressChanged events.

'Snapper.WinForm.vshost.exe' (Managed): Loaded 'C:\Windows\assembly\GAC_MSIL\System.Configuration\2.0.0.0__b03f5f7f11d50a3a\System.Configuration.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
Uninitialized
Uninitialized
Uninitialized
Uninitialized
Uninitialized
'Snapper.WinForm.vshost.exe' (Managed): Loaded 'C:\Windows\assembly\GAC\Microsoft.mshtml\7.0.3300.0__b03f5f7f11d50a3a\Microsoft.mshtml.dll'
Interactive
Interactive
Interactive
Interactive
Interactive
Interactive
Interactive
Interactive
Interactive
Interactive
Interactive
Interactive
Interactive
12/29/2007 1:00:23 PM - DocumentCompleted!
12/29/2007 1:00:24 PM - DocumentCompleted!
12/29/2007 1:00:25 PM - DocumentCompleted!
Interactive
Interactive
12/29/2007 1:00:27 PM - DocumentCompleted!
12/29/2007 1:00:29 PM - DocumentCompleted!
Interactive
Interactive
Interactive
Interactive
Interactive
12/29/2007 1:00:31 PM - DocumentCompleted!
Interactive
Interactive
Interactive
Interactive
Interactive
Interactive
12/29/2007 1:00:33 PM - DocumentCompleted!
Interactive
12/29/2007 1:00:35 PM - DocumentCompleted!
12/29/2007 1:00:36 PM - DocumentCompleted!
Interactive
Interactive
12/29/2007 1:00:40 PM - DocumentCompleted!
Complete
12/29/2007 1:00:41 PM - DocumentCompleted!

Aside from the fact that it took 18 seconds to get this page’s contents in code (whereas FasterFox reports 8 seconds in Flock), having 11 DocumentCompleted events seems a little odd.

UPDATE: Looking at this the answer seems to pop out at me.  Just wait for the ProgressChanged event to change to “Complete” before I do anything meaningful in the DocumentCompleted event handler.  I’ll give that a try right now.

Mini Project I’ll Be Working On

I decided to go ahead and follow through on my research a couple weeks ago into image-processing routines to take screenshots and create a little ecosystem of client apps that will leverage this library:

Screenie App 2

Now that I know what I know about the WebBrowser class, the missing DrawToBitmap() function, and the GDI32 / USER32 library calls from managed .NET code, the core library probably won’t be that difficult. I think the hardest part will be “stitching” together the various parts of a full-height web page that extends beyond the viewable window. But hey, any problem you can describe is a problem half-solved.

Updates to come.

The missing DrawToBitmap() function in the .NET WebBrowser class

The last couple days I’ve been farting around with how to get access to a rendering engine in order to do screenshots of web pages. My first attempts were based on the Gecko engine used in Mozilla browsers, and I didn’t have much luck with Mono or the C# wrappers around the Gtk/Gecko libraries.

Browsing around some more I found some source for the Microsoft rendering engine (aka Trident) as encapsulated in the older-style SHDOCVW/MSHTML libraries. Then I quickly found that as of .NET 2.0, there was a new control, System.Windows.Forms.WebControl, that allowed you to embed a browser in your application, with the same semantics as the old style, but which was easier to use. I remember back in the day trying to get the first IE ActiveX controls on some dumb VB form or another and thinking “how goddamned fragile can they make this thing?” Anyway, that new class discovery led me to this code which works great — see the screenshot below, taken at 1024×768, of this blog. Good enough to get started.

But all along I’d been doodling with the WebBrowser control class and never saw this neat method DrawToBitmap() in intellisense. Hm. Strange enough. I thought maybe it had been deprecated in .NET 3.5, so I fiddled around with changing the Framework Target but no, it has been out of Intellisense since at least Visual Studio 2005. I found out why when I F1-ed the method:

WebBrowserBase.DrawToBitmap Method
This method supports the .NET Framework infrastructure and is not intended to be used directly from your code.

… and yet it works. I’m actually surprised it even compiles.

Poking around even further, I found a more “nativist” approach from Alan Dean that brings back the mshtml, GDI32, and USER32 libs.   mshtml can be referenced directly as c:\program files\microsoft.net\primary interop assemblies\microsoft.mshtml.dll, but the other two require the DllImports voodoo from the bad old days of yore.  So, I have the resources now to do what it was I wanted to do in the first place, which was….what again?  I seem to remember looking at the Amazon Associates Program, seeing a reference to the Alexa Site Thumbnail service, and thinking “how hard can that be?”

I think that the Windows code I’ve found to date can be updated in two significant ways:

  1. ensure you can do full-page snapshots if necessary, not just the current viewport.
  2. return the PNG file as an .ashx stream, not necessarily saving the image first.  Of course you could cache the image and still serve it up as an .ashx, I suppose, saving some network traffic.

It’s been an interesting exploration!


TwitterCounter for @anthonyrstevens
Add to Technorati Favorites

RSS Feed

View Anthony Stevens's profile on LinkedIn