在这篇文章中,将探讨如何开发一个.NET控制台应用程序,该程序能够加载一个网页并将其截图保存为JPG文件。这种类型的应用程序对于需要批量处理多个网站截图的系统管理员来说非常有用。尽管在Windows Forms中实现这一功能相对简单,但为了满足Linux用户的需求,选择了更具挑战性的控制台应用程序方案。
系统管理员最近提出了一个需求,他想知道是否可以编写一个.NET应用程序来生成网站的缩略图。使用Windows Forms实现这个功能相对简单,但考虑到他是一个Linux用户,决定选择更具挑战性的控制台应用程序作为解决方案。这是一个有趣的用例。
在WinForms中,只需要从工具箱中拖放一个WebBrowser控件到表单上,然后在页面加载完成后调用以下代码:
C#
Bitmap bitmap = new Bitmap(width, height);
webBrowser1.DrawToBitmap(bitmap, new Rectangle(webBrowser1.Location.X, webBrowser1.Location.Y, webBrowser1.Width, webBrowser1.Height));
当涉及到在控制台应用程序中实现时,问题就变得复杂了。可能会考虑创建一个完整的表单,让它显示(或不显示),完成工作,然后退出WinForms应用程序。这可能对于快速解决方案足够了,但想要一个干净的代码,所以并不会为此感到自豪。
首先在类构造函数中实例化Web控件:
C#
public WebPageBitmap(string url, int width, int height, bool scrollBarsEnabled)
{
this.url = url;
this.width = width;
this.height = height;
webBrowser = new WebBrowser();
webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(documentCompletedEventHandler);
webBrowser.Size = new Size(width, height);
webBrowser.ScrollBarsEnabled = scrollBarsEnabled;
}
接下来是有趣的部分。由于调用是异步的,简单的webBrowser.Navigate(URL);是不够的。处于单线程中,浏览器不会为此创建一个单独的线程。这是符合Windows规则的:只有创建控件的线程才能访问控件。需要以某种方式允许控件接管线程的流程并执行其工作。Navigate只是告诉它应该执行操作,然后立即退出。开发者的责任是知道控件何时准备好使用,这发生在webBrowser.ReadyState变为WebBrowserReadyState.Complete状态时。
为了将流程传递给应用程序控件,需要执行Application.DoEvents(),这是最初使用时的一个猜测。令人惊讶的是,它就像在其他Windows框架中使用过的那样有效。
C#
public void Fetch()
{
webBrowser.Navigate(url);
while (webBrowser.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
}
}
这样做的结果是一个小而整洁的应用程序,它从网络上拉取一个网页并对其进行截图(可能还会进行缩放)。
可以直接获取源代码或应用程序。应用程序的使用方法如下:
GetSiteThumbnail.exe http://www.yoursite.com/ thumbnail.jpg [browser_width(defaults to 800) browser_height (defaults to 600) ] [thumbnail_width thumbnail_height]
GetSiteThumbnail.exe http://www.cognifide.com/ cognifide.jpg 1280 1024 640 480