Too many WebBrowsers causing crash in mshtml.dll - c#

The program I am writing takes a very large amount of html text, splits it up, and displays it in multiple WebBrowser controls. It is split up because the amount of text is so large that it cannot be placed in a single string variable, let alone a single WebBrowser control. This all seems to work well, up to a certain point. The point where it breaks seems to be after creating about 72 WebBrowser controls, with about 2000 lines of html in each one. Each browser is instantiated like so:
var browser = new WebBrowser();
browser.Navigate("about:blank");
browser.Document.OpenNew(false);
browser.Document.Write(node.HTML);
After instantiating all of the webbrowsers, the form will load and show itself. Note that only one WebBrowser is visible at a time, the rest are tabbed. After about 5 seconds (while the winforms event loop is basically idling) the program will crash due to an exception in mshtml.dll. Below is the call stack that i pulled:
and the disassembler:
The mouse cursor is where the program breaks. I've doubled checked all of the html and it is all valid. I can load up the first half and the second half of the html separately without crashing. Only when all is loaded it will fail. I've also tried cutting down the number of browsers in half, and doubling the amount of html they individually show, which ended up with the same result. Also tried dynamically loading the html in each web browser when they are first opened.
It seems to me there is some kind of shared memory between all web browser instances, and it eventually just gets corrupted or something.
I'm pretty much at a loss here. I was thinking of possibly replacing the WebBrowser with CefSharp browser, but I don't want to go that route just yet if its not necessary.

Related

How can I take a remote screenshot of a website from a url?

So I have an application that does:
Take n amount of links from SQL
Creates a new thread for each link
Get HTML code of this website with HTML-Agility-Pack for each thread
Saves its data to SQL (image sizes, page size, word count, words etc) and saves this process with its date
This is to check the data on a website and see if there is any changes (like a typo or a problem with images that were previously uploaded) and I want to add a screenshot/thumbnail to these for each page. How can I take a screenshot of the whole page during each thread?
In order to make a screenshot, you need your HTML to be rendered. This is a task for a web browser. As you are looking for a C# solution, you could use CefSharp (https://github.com/cefsharp/CefSharp) to render your html in offscreen mode.
Seems like an interesting app. As you already get the HTML for the entire URL (I would assume the app is running on a machine/server which has internet connectivity):
There are 3 ways you can do this (many more actually).
In the Thread - create a System.Windows.Forms.Form object, Add a webbrowser control to its list of Child Controls (Dock = Fill). Make the browser navigate to the url. Once navigation is complete - take the screenshot of the WinForms Dialog.
In the thread - launch chrome/IE web browser passing the Url as Command line argument. Wait for sometime in the thread (there isnt a good way to know when rendering finishes). Take the screenshot.
In the thread - Use selenium type of .net compatible library - which helps you do web ui testing automation and then do Step #2. You will have more granular control over the web browser using this approach.

.NET ImageList becomes corrupt occasionally

With a Winforms .net application, we have an issue where an image list occasionally becomes corrupted.
By corrupted I mean that the count of the number of images will be wrong and/or the images may have been replaced by system images (like dialog box icons).
For example, the screenshot below shows the imageInfoCollection showing the correct number, but the count showing the incorrect number.
The image list is on a form that is opened repeatedly by the user throughout the use of the application. The image list is used by a tab control on the form.
The issue occurs only occasionally, anywhere between every 5 and 20 times of opening the form.
The code to load the imagelist is built by the designer, and uses images from the resources:
this.imageListCallTakingScreen.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageListCallTakingScreen.ImageStream")));
this.imageListCallTakingScreen.TransparentColor = System.Drawing.Color.Transparent;
this.imageListCallTakingScreen.Images.SetKeyName(0, "spinner.png");
this.imageListCallTakingScreen.Images.SetKeyName(1, "recommendation-star.png");
this.imageListCallTakingScreen.Images.SetKeyName(2, "recommendation-star_red.png");
this.imageListCallTakingScreen.Images.SetKeyName(3, "recommendation-star - Transparent.png");
this.imageListCallTakingScreen.Images.SetKeyName(4, "Initialisation_fail16.png");
this.imageListCallTakingScreen.Images.SetKeyName(5, "information_white.png");
this.imageListCallTakingScreen.Images.SetKeyName(6, "Check-icon.png");
The imagelist isn't used anywhere other than in the designer.cs code to create it and wire it up to the tab control (except for the error trapping line I have put in):
Ideas? We are stuck on this one and google doesn't turn much up.
The imageInfoCollection field properly tracks the number of images you have in the ImageList. The Count property tracks the number of images that are actually present in the native Windows imagelist control.
There's only one way those values could have a mismatch that I can think of. Your program is leaking GDI object handles. A fairly common problem in Winform apps. That works for quite a while until you reach the operating system quota for such handles, after you've consumed 10,000 of them then Windows stops allowing you to create more. The error checking in the .NET wrapper class is not entirely kosher so this can happen without an exception getting generated. You'll see some more strange painting artifacts when you hit that limit btw.
You can get a basic diagnostic from Task Manager, Processes tab. Use View + Select columns and tick GDI Objects and USER objects. Observe these values while you operate the program like a user would. A steadily climbing value for GDI Objects spells doom. A hint that you are forgetting to use the using statement to dispose System.Drawing objects. And the garbage collector not running often enough to keep you out of trouble. You need to fix this in your code so the counter remains stable at, say, no more than several hundred objects.
A steadily climbing value for USER Objects is also a very common Winforms bug. That's a pretty fatal one, it will jack-up the GDI object count as well and the GC cannot fix this problem. This will happen when you remove controls in your code with Controls.Remove/At() or Controls.Clear() and forget to dispose the removed control objects.

Website hangs only on certain clients ; if ViewState is disabled, loads at normal speed

This is very weird and it has taken lots of time to reach this point.
I have certain clients (from any computer on their network) and on one of my remote-working colleague that when loading some of our sites, the page hangs for 3-4 minutes before displaying.
The same page, on the same client machine, when connected to a wireless network loads fine.
We have checked DNS problems and the DNS resolution works fine.
Inspecting the page load in Firebug, I can see that the ASP.NET page goes into receiving state fairly quickly but then it takes forever to receive.
The head of the HTML file loads, in fact the Firebug's Net tab shows loading CSS, JS files, however the ASP.NET page itself takes, as said 3-4 minutes.
If, while it is loading, I right click and select View Source I see the full HTML content loaded in 1-2 seconds (in Firefox, View Source re-fetches the page from the server)
If while loading in IE, I right click and select View Source (in IE the View source corresponds to what the browser has got available at the moment) I can see that the HTML content is loaded up to halfway through the ViewState, if I keep re-asking for View Source, I can see slightly more of the ViewState loaded.
As a test I have therefore disabled ViewState all together and the page load as fast as it does in our office.
I know that ViewState is and ugly beast, it takes a big chunk of bandwidth and always takes a toll on page load time, however this is not the point.
I do not understand why that affects only certain machine connected to certain networks.
Can anyone shed any light on this?
EDIT:
Re-trying loading the page with ViewState disabled, and now the page load hangs again, further down the HTML content when I view the source in IE.
Interesting is:
When the same page is loaded in HTTS, it loads fine!
FURTHER ADDITION:
The site in question is http://www.theclifftownhouse.com/

.Net WebBrowser Control memory leak

My c# application uses .net WebBrowser. I need to close child control everytime and I have noticed WebBrowser is not getting disposed and RAM consumption is increasing heavily with each call (around 10 mb on each new control declaration) and application crashes in sometime with OutOfMemoryException. Searched over forums but couldn't find a clean solution.
Tried SetProcessWorkingSetSize(pHandle, -1, -1); but it doesn't reduce virtual memory though RAM uses will be reduced and its not a clean way of overcoming the issue.
Seems this issues exists since years, for more details look at this thread How to get around the memory leak in the .NET Webbrowser control?
Any suggestions ? Tried almost everything but no success yet.
Thanks,
Abhinav
I don't know whether your situation is similiar to mine but I have wasted three days for that weird problem.
My application was performing a search on a web page and my code was like that;
1.Open web page
for(1000 times)
{
2.Write input and click search button.
3.Check the result.
}
As you see my program opens the web page and makes repeated searches.Here opening the page (navigaiton) occurs only one time. My program's memory consumption was continuously increasing even above 1 GB! Then I tried putting the navigation inside the loop it worked.
for(1000 times)
{
1.Open web page
2.Write input and click seach button.
3.Check the result.
}
I exactly don't know the reason but reusing the same page for a long time was the cause of my problem. I hope it helps.

AJAX .NET CollapsiblePanel inside a gridview is causing memory leaks?

One of our ASP.NET pages has a significant memory leak. After a process of manual enable/disabling, I narrowed down the issue to a set of collapsible panels which are dynamically built on the code page and placed into an UpdatePanel which is already on the page.
Using sIEve, I was able to see that this control apparently is creating a large amount of script tags, each having the following form (ignore the sIEve hook attribute):
<SCRIPT type=text/javascript __sIEve_hookedNode="true">Sys.Application.add_init(function() {
$create(AjaxControlToolkit.CollapsiblePanelBehavior, {"ClientStateFieldID":"ctl00_Main_branchPanelExtender_ClientState","CollapseControlID":"ctl00_Main_btnBranchExpander","Collapsed":true,"CollapsedSize":0,"CollapsedText":"* ; ","ExpandControlID":"ctl00_Main_btnBranchExpander","ExpandedSize":100,"ExpandedText":"Collapse","ScrollContents":true,"TextLabelID":"ctl00_Main_btnBranchExpander","id":"ctl00_Main_branchPanelExtender"}, null, null, $get("ctl00_Main_BranchPanel"));});</SCRIPT>
I think this is the problem, but I'm not completely sure. sIEve isn't reporting it as a memory leak, but the DOM nodes are definitely increasing and the page size grows out of control. I'm also not sure what to do about it. My best guess is that the corresponding remove_init isn't being called (or doesn't exist) but I can't find either function call in the AjaxControlToolkit library project.
Has anyone else encountered this problem or have any ideas on how to proceed with fixing it?
Edit: Browser Info
This is mainly IE 6, of course, but I also note the issue with FireFox 3. Opera and Chrome don't seem to have the memory leak, but Chrome doesn't render the controls right either.
Further Info:
I've noticed a similar problem on another page using HoverMenuExtender. It seems like the DOM just grows each time the UpdatePanel is posted and IE never frees the memory. Is there maybe a way to catch which items are holding over and manually remove them, or am I being overly cautious and IE will eventually free the memory up if needed?
Well, no answers on this one and I doubt one is coming. The problem can be answered very briefly though as "It's IE6." Sometimes certain DOM elements (the selection elements in an Option tag seem particularly prone) just don't clean up, so they fill the DOM up over time. Nasty, but just another thing to manage in IE6.

Categories