C# - WebBrowser control seems to cache screenshots
- by Justin
Hey,
I'm using the WebBrowser control in an ASP.NET MVC 2 app (don't judge, I'm doing it in an admin section only to be used by me), here's the code:
public static class Screenshot
{
private static string _url;
private static int _width;
private static byte[] _bytes;
public static byte[] Get(string url)
{
// This method gets a screenshot of the webpage
// rendered at its full size (height and width)
return Get(url, 50);
}
public static byte[] Get(string url, int width)
{
//set properties.
_url = url;
_width = width;
//start screen scraper.
var webBrowseThread = new Thread(new ThreadStart(TakeScreenshot));
webBrowseThread.SetApartmentState(ApartmentState.STA);
webBrowseThread.Start();
//check every second if it got the screenshot yet.
//i know, the thread sleep is terrible, but it's the secure section, don't judge...
int numChecks = 20;
for (int k = 0; k < numChecks; k++)
{
Thread.Sleep(1000);
if (_bytes != null)
{
return _bytes;
}
}
return null;
}
private static void TakeScreenshot()
{
try
{
//load the webpage into a WebBrowser control.
using (WebBrowser wb = new WebBrowser())
{
wb.ScrollBarsEnabled = false;
wb.ScriptErrorsSuppressed = true;
wb.Navigate(_url);
while (wb.ReadyState != WebBrowserReadyState.Complete) { Application.DoEvents(); }
//set the size of the WebBrowser control.
//take Screenshot of the web pages full width.
wb.Width = wb.Document.Body.ScrollRectangle.Width;
//take Screenshot of the web pages full height.
wb.Height = wb.Document.Body.ScrollRectangle.Height;
//get a Bitmap representation of the webpage as it's rendered in the WebBrowser control.
var bitmap = new Bitmap(wb.Width, wb.Height);
wb.DrawToBitmap(bitmap, new Rectangle(0, 0, wb.Width, wb.Height));
//resize.
var height = _width * (bitmap.Height / bitmap.Width);
var thumbnail = bitmap.GetThumbnailImage(_width, height, null, IntPtr.Zero);
//convert to byte array.
var ms = new MemoryStream();
thumbnail.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
_bytes = ms.ToArray();
}
}
catch(Exception exc)
{//TODO: why did screenshot fail?
string message = exc.Message;
}
}
This works fine for the first screenshot that I take, however if I try to take subsequent screenshots of different URL's, it saves screenshots of the first url for the new url, or sometimes it'll save the screenshot from 3 or 4 url's ago. I'm creating a new instance of WebBrowser for each screenshot and am disposing of it properly with the "using" block, any idea why it's behaving this way?
Thanks,
Justin