Attached code uses altered version of WebPreview from http://smallsharptools.com/Projects/WebPreview/. WebPreview works just fine with most of the sites but, if site you are trying to get screenshot/thumbnail has a JavaScript prompt, by default webbrowser control shows it to user. Its ok if you are using it on an asp.net application, user can click to prompt. Things change if you try to use it on an asp.net website. As there will be no one to click to prompt or even no way to display the prompt code hangs. I have derived from webbrowser control and overwrite OnNavigated event and injected some java script code to disable prompts. Download SmallSharpTools.WebPreview-1.0.0-src.rar (84.13 kb). Keep in mind that webbrowser control uses internet explorer installed on the system and trying to get screenshots/thumbnails of malicious sites may create trouble for your server.
You may also be interested with http://nolovelust.com/post/C-Website-Screenshot-Generator-AKA-Get-Screenshot-of-Webpage-With-Aspnet-C.aspx
WebBrowserEx.cs
using System.Windows.Forms;
using mshtml;
namespace SmallSharpTools.WebPreview
{
class WebBrowserEx : WebBrowser
{
public WebBrowserEx() { }
protected override void OnNavigated(WebBrowserNavigatedEventArgs e)
{
HtmlElement he = this.Document.GetElementsByTagName("head")[0];
HtmlElement se = this.Document.CreateElement("script");
mshtml.IHTMLScriptElement element = (mshtml.IHTMLScriptElement)se.DomElement;
string alertBlocker = "window.alert = function () { }";
element.text = alertBlocker;
he.AppendChild(se);
string alertBlockerB = "window.confirm = function () { }";
element.text = alertBlockerB;
he.AppendChild(se);
string alertBlockerC = "window.prompt = function () { }";
element.text = alertBlockerC;
he.AppendChild(se);
string alertBlockerD = "window.open = function () { }";
element.text = alertBlockerD;
he.AppendChild(se);
base.OnNavigated(e);
}
}
}
ThumbnailBuilder.cs
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
namespace SmallSharpTools.WebPreview
{
public class ThumbnailBuilder
{
#region " Events "
public event EventHandler ExceptionCatching;
///
/// Raise the ExceptionCatching event
///
///
protected virtual void OnExceptionCatching(EventArgs e)
{
if (ExceptionCatching != null)
{
ExceptionCatching(this, e);
}
}
#endregion
#region " Methods "
public void CreateThumbnail(string sourceFilename, string cachedFilename, int width, int height)
{
if (File.Exists(sourceFilename))
{
FileInfo inputFile = new FileInfo(sourceFilename);
FileInfo outputFile = new FileInfo(cachedFilename);
if (!outputFile.Directory.Exists)
{
outputFile.Directory.Create();
}
if (outputFile.Exists && inputFile.CreationTime < outputFile.CreationTime)
{
return;
}
try
{
using (Bitmap inBmp = new Bitmap(sourceFilename))
{
using (Bitmap outBmp = new Bitmap(width, height))
{
using (Graphics g = Graphics.FromImage(outBmp))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(inBmp, 0, 0, width, height);
}
outBmp.Save(cachedFilename);
}
}
}
catch (Exception ex)
{
CurrentError = ex;
OnExceptionCatching(EventArgs.Empty);
}
}
}
#endregion
#region " Properties "
private Exception _currentException = null;
public Exception CurrentError
{
get { return _currentException; }
set { _currentException = value; }
}
#endregion
}
}
SiteConfiguration.cs
using System.Configuration;
using System.Web;
///
/// Summary description for SiteConfiguration
///
public class SiteConfiguration
{
public static string SourceImageDirectory
{
get
{
return HttpContext.Current.Server.MapPath(
ConfigurationManager.AppSettings["SourceImageDirectory"]);
}
}
public static string CachingImageDirectory
{
get
{
return HttpContext.Current.Server.MapPath(
ConfigurationManager.AppSettings["CachingImageDirectory"]);
}
}
}
PreviewBuilder.cs
using System;
using System.ComponentModel;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
namespace SmallSharpTools.WebPreview
{
public class PreviewBuilder
{
#region " Variables "
private string _url = String.Empty;
private string _filename = String.Empty;
#endregion
#region " Constructor "
public PreviewBuilder(string url, string filename)
{
this._url = url;
this._filename = filename;
// Path.Combine(Environment.CurrentDirectory, "output.bmp");
}
#endregion
#region " Methods "
public void CreatePreview()
{
ThreadStart ts = new ThreadStart(this.DoWork);
Thread t = new Thread(ts);
t.SetApartmentState(ApartmentState.STA);
t.Start();
// TODO find the proper way to wait for a thread
// wait for the thread
while (t.IsAlive)
{
Thread.Sleep(25);
}
}
private void DoWork()
{
Bitmap bitmap = GetPreviewImage();
bitmap.Save(_filename);
bitmap.Dispose();
}
private Bitmap GetPreviewImage()
{
WebBrowser wb = new WebBrowserEx();
wb.ScrollBarsEnabled = false;
wb.Size = new Size(Width, Height);
wb.ScriptErrorsSuppressed = true;
wb.NewWindow += new System.ComponentModel.CancelEventHandler(wb_NewWindow);
wb.Navigate(_url);
// wait for it to load
while (wb.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
}
Bitmap bitmap = new Bitmap(Width, Height);
Rectangle rect = new Rectangle(0, 0, Width, Height);
wb.DrawToBitmap(bitmap, rect);
return bitmap;
}
void wb_NewWindow(object sender, CancelEventArgs e)
{
e.Cancel = true;
}
#endregion
#region " Properties "
private int _width = 1024;
public int Width
{
get { return _width; }
set { _width = value; }
}
private int _height = 768;
public int Height
{
get { return _height; }
set { _height = value; }
}
#endregion
}
}
WebPreviewHandler.ashx
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Web;
using System.Web.Caching;
using SmallSharpTools.WebPreview;
public class WebPreviewHandler : IHttpHandler
{
public void ProcessRequest (HttpContext context)
{
string url = context.Request.QueryString["url"];
int width;
if (!int.TryParse(context.Request.QueryString["width"], out width))
{
width = 150;
}
int height;
if (!int.TryParse(context.Request.QueryString["height"], out height))
{
height = 100;
}
string sourceFilename = GetSourceFilename(url);
FileInfo file = new FileInfo(sourceFilename);
if (!file.Exists || file.CreationTime < DateTime.Now.AddHours(-4))
{
PreviewBuilder pb = new PreviewBuilder(url, sourceFilename);
pb.CreatePreview();
}
string cachedFilename = GetCachedFilename(sourceFilename, width, height);
if (!File.Exists(cachedFilename))
{
ThumbnailBuilder tb = new ThumbnailBuilder();
// handle the error by throwing it
tb.ExceptionCatching += delegate { throw tb.CurrentError; };
tb.CreateThumbnail(sourceFilename, cachedFilename, width, height);
}
context.Response.ContentType = GetContentType(cachedFilename);
context.Response.WriteFile(cachedFilename);
}
public string GetContentType(string filename)
{
string contentType = "image/x-unknown";
string ext = Path.GetExtension(filename);
switch (ext)
{
case ".jpg":
contentType = "image/jpeg";
break;
case ".gif":
contentType = "image/gif";
break;
case ".png":
contentType = "image/png";
break;
default:
contentType = "image/jpeg";
break;
}
return contentType;
}
public string GetSourceFilename(string url)
{
Uri uri = new Uri(url);
string shortFilename = uri.Host.Replace(".", "_") +
uri.LocalPath.Replace("/", "_") + ".png";
return Path.Combine(SiteConfiguration.SourceImageDirectory, shortFilename);
}
public string GetCachedFilename(string sourceFilename, int width, int height)
{
FileInfo sourceFile = new FileInfo(sourceFilename);
string shortFilename = sourceFile.Name;
string ext = Path.GetExtension(shortFilename);
string replacementEnding = String.Format("-{0}x{1}", width, height) + ext;
string cachedFilename = shortFilename.Replace(ext, replacementEnding);
return Path.Combine(SiteConfiguration.CachingImageDirectory, cachedFilename);
}
public bool IsReusable
{
get {
return false;
}
}
}