核心架構
- WebBrowser 控制項:WinForms 內嵌 IE/Edge (IE 模式) 渲染引擎,支援 `DrawToBitmap` 離屏繪製。
- STA 執行緒:WebBrowser 單執行緒套間模型,**必須在 STA 執行緒**建立與操作。
- 流程:建立 STA 執行緒 → 實例化 WebBrowser → `Navigate` → 等待 `DocumentCompleted` → `DrawToBitmap` → 縮放儲存。
完整可用類別
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Threading;
using System.Windows.Forms;
public class WebPageScreenshot
{
public Bitmap Capture(string url, int viewportWidth, int viewportHeight, int outputWidth, int outputHeight, int timeoutMs = 30000)
{
Bitmap result = null;
Exception error = null;
var done = new ManualResetEvent(false);
var thread = new Thread(() =>
{
try
{
Application.SetCompatibleTextRenderingDefault(false);
using (var browser = new WebBrowser())
{
browser.ScrollBarsEnabled = false;
browser.Size = new Size(viewportWidth, viewportHeight);
browser.ScriptErrorsSuppressed = true;
browser.DocumentCompleted += (s, e) =>
{
if (browser.ReadyState == WebBrowserReadyState.Complete)
{
// 1. 完整視口位圖
var full = new Bitmap(viewportWidth, viewportHeight);
browser.DrawToBitmap(full, new Rectangle(0, 0, viewportWidth, viewportHeight));
// 2. 縮放至目標尺寸 (高品質雙線性插值)
var thumb = new Bitmap(outputWidth, outputHeight);
using (var g = Graphics.FromImage(thumb))
{
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.DrawImage(full, 0, 0, outputWidth, outputHeight);
}
full.Dispose();
result = thumb;
done.Set();
}
};
browser.Navigate(url);
Application.Run(); // 啟動訊息迴圈
}
}
catch (Exception ex)
{
error = ex;
done.Set();
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.IsBackground = true;
thread.Start();
if (!done.WaitOne(timeoutMs))
{
thread.Abort(); // 強制結束
throw new TimeoutException($"網頁截圖逾時 ({timeoutMs}ms)");
}
if (error != null) throw error;
return result;
}
}
ASP.NET / 服務端呼叫範例
public async Task CapturePageAsync(string url)
{
return await Task.Run(() =>
{
var capture = new WebPageScreenshot();
using (var bmp = capture.Capture(url, 1280, 720, 640, 360))
using (var ms = new System.IO.MemoryStream())
{
bmp.Save(ms, ImageFormat.Jpeg);
return ms.ToArray();
}
});
}
關鍵限制與替代方案
| 限制 | 影響 | 替代方案 |
| 依賴 IE/Edge IE 模式 | 現代 CSS/JS (Flex/Grid/ES6+) 渲染失敗 | Puppeteer Sharp (Headless Chrome), Playwright Sharp |
| 需 STA 執行緒 | ASP.NET 執行緒池為 MTA,須另開 STA 執行緒 | 同樣需 STA,或用無頭瀏覽器 |
| 記憶體佔用大 | 每個實例 ~50-100MB | 無頭瀏覽器共用進程池 |
| Windows Server 需安裝 Desktop Experience | Core/Container 環境無法運行 | Docker + Puppeteer/Playwright |
現代化推薦:Puppeteer Sharp
// NuGet: PuppeteerSharp
using PuppeteerSharp;
public async Task CaptureModernAsync(string url)
{
await new BrowserFetcher().DownloadAsync(); // 首次下載 Chromium
using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true });
using var page = await browser.NewPageAsync();
await page.SetViewportAsync(new ViewPortOptions { Width = 1280, Height = 720 });
await page.GoToAsync(url, WaitUntilNavigation.Networkidle0);
return await page.ScreenshotDataAsync(new ScreenshotOptions { FullPage = false });
}
總結
傳統 `WebBrowser.DrawToBitmap` 方案**僅適用於舊版 IE 相容頁面、Windows 桌面/Server (含 Desktop Experience)**。新專案**強烈建議改用 Puppeteer Sharp / Playwright Sharp**,支援現代 Web 標準、無頭模式、容器化部署、截圖品質更高、API 更豐富 (PDF 生成、網路攔截、效能分析等)。
- 上一篇文章: C# 中文取拼音首字母 (GB2312 區位碼對照) 完整實作
- 下一篇文章: C# IP 路由判斷實作:子網遮罩與網路位址比對演算法
Copyright ©
程式碼之家 All Rights Reserved