Screenshots von Webseiten oder HTML-Dateien in .NET (C#)
Screenshots von Webseiten programmgesteuert zu erstellen, ist eine wertvolle Fähigkeit für automatisierte Tests, Dokumentation und Monitoring. In diesem Leitfaden zeigen wir, wie Sie mit .NET (C#) Screenshots von Webseiten und HTML-Dateien erstellen.
Voraussetzungen
Um diesem Tutorial zu folgen, benötigen Sie:
- .NET 8.0 oder neuer
- Visual Studio 2022 oder Visual Studio Code
- Einen installierten Chrome-Browser
Selenium WebDriver verwenden
Selenium WebDriver ist ein leistungsfähiges Werkzeug zur Browser-Automatisierung, das auch Screenshot-Funktionen bietet. Installieren Sie zunächst die erforderlichen NuGet-Pakete:
dotnet new console -n WebpageScreenshots
cd WebpageScreenshots
dotnet add package Selenium.WebDriver --version 4.28.0
dotnet add package Selenium.Support --version 4.28.0
Das folgende Beispiel zeigt, wie Sie den sichtbaren Viewport mit der Erweiterungsmethode
TakeScreenshot() aus Selenium 4 erfassen. Sie erfasst keine Inhalte unterhalb des
Viewports. Speichern Sie die Klasse in ScreenshotCapture.cs und rufen Sie
ScreenshotCapture.CaptureWebpage(url, outputPath) aus Program.cs auf. Geben Sie einen Ausgabepfad
.png an, dessen übergeordnetes Verzeichnis vorhanden ist.
using System;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using OpenQA.Selenium.Support.Extensions;
public class ScreenshotCapture
{
public static void CaptureWebpage(string url, string outputPath)
{
try
{
var options = new ChromeOptions();
options.AddArgument("--headless=new");
using (var driver = new ChromeDriver(options))
{
driver.Manage().Window.Size = new System.Drawing.Size(1920, 1080);
driver.Navigate().GoToUrl(url);
// Wait for the document to finish loading
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(d => ((IJavaScriptExecutor)d)
.ExecuteScript("return document.readyState").Equals("complete"));
var screenshot = driver.TakeScreenshot();
screenshot.SaveAsFile(outputPath);
}
}
catch (WebDriverException ex)
{
throw new Exception($"Failed to capture screenshot: {ex.Message}", ex);
}
}
}
Browser-Kompatibilität
Diese Beispiele verwenden Chrome mit --headless=new (Chrome 112 oder neuer).
Selenium Manager, der in Selenium 4 enthalten ist, ermittelt beim
Start von ChromeDriver einen passenden ChromeDriver oder lädt ihn herunter. Der
erste Lauf erfordert möglicherweise Netzwerkzugriff. Für Firefox und Edge sind die jeweiligen
Treiber- und Optionsklassen erforderlich.
Rendern Sie nur Seiten und HTML-Dateien, denen Sie vertrauen. Die Navigation und
document.readyState prüfen keine HTTP-Statuscodes und garantieren nicht, dass die
asynchronen Inhalte einer Anwendung vollständig geladen sind.
Lokale HTML-Dateien erfassen
Um Screenshots von lokalen HTML-Dateien zu erstellen, verwenden Sie das Protokoll
file:// mit sauberer Fehlerbehandlung. Fügen Sie die folgende Methode in
ScreenshotCapture ein und ergänzen Sie am Anfang der Datei die zugehörigen Direktiven
mit using:
using System;
using System.IO;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using OpenQA.Selenium.Support.Extensions;
public static void CaptureLocalHtml(string htmlFilePath, string outputPath)
{
try
{
var absolutePath = Path.GetFullPath(htmlFilePath);
if (!File.Exists(absolutePath))
{
throw new FileNotFoundException("HTML file not found", absolutePath);
}
var fileUri = new Uri(absolutePath).AbsoluteUri;
var options = new ChromeOptions();
options.AddArgument("--headless=new");
using (var driver = new ChromeDriver(options))
{
driver.Navigate().GoToUrl(fileUri);
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(d => ((IJavaScriptExecutor)d)
.ExecuteScript("return document.readyState").Equals("complete"));
var screenshot = driver.TakeScreenshot();
screenshot.SaveAsFile(outputPath);
}
}
catch (Exception ex)
{
throw new Exception($"Failed to capture local HTML: {ex.Message}", ex);
}
}
Umgang mit dynamischen Inhalten
Moderne Webanwendungen enthalten häufig dynamische Inhalte, die zusätzliche Zeit zum Laden
benötigen. Fügen Sie diese Methode derselben Klasse hinzu und ersetzen Sie
content-loaded durch ein Element, das Ihre Anwendung anzeigt, sobald ihre Inhalte
bereit sind:
using System;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using OpenQA.Selenium.Support.Extensions;
public static void CaptureDynamicWebpage(string url, string outputPath)
{
try
{
var options = new ChromeOptions();
options.AddArgument("--headless=new");
using (var driver = new ChromeDriver(options))
{
driver.Manage().Window.Size = new System.Drawing.Size(1920, 1080);
driver.Navigate().GoToUrl(url);
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
// Wait for a specific element to ensure dynamic content is loaded
wait.Until(d => d.FindElement(By.Id("content-loaded")).Displayed);
var screenshot = driver.TakeScreenshot();
screenshot.SaveAsFile(outputPath);
}
}
catch (WebDriverTimeoutException ex)
{
throw new Exception("Timeout waiting for dynamic content to load", ex);
}
}
Screenshot-Speicherung verwalten
Verwenden Sie für diesen Manager ein Verzeichnis, das Ihrer Anwendung gehört. Er erstellt ein
Unterverzeichnis screenshots und bereinigt nur Dateien, die seiner eigenen
Namenskonvention entsprechen; andere PNG-Dateien bleiben unangetastet. Übergeben Sie
screenshot.AsByteArray an SaveScreenshot:
using System;
using System.IO;
using System.Text.RegularExpressions;
public class ScreenshotManager
{
private readonly string _baseDirectory;
public ScreenshotManager(string baseDirectory)
{
_baseDirectory = Path.Combine(Path.GetFullPath(baseDirectory), "screenshots");
Directory.CreateDirectory(_baseDirectory);
}
public string SaveScreenshot(byte[] screenshotBytes, string prefix = "")
{
if (!Regex.IsMatch(prefix, @"\A[A-Za-z0-9_-]*\z"))
{
throw new ArgumentException("Use only letters, digits, underscores, or hyphens", nameof(prefix));
}
var fileName = $"{prefix}screenshot_{DateTime.UtcNow:yyyyMMdd_HHmmss}_{Guid.NewGuid():N}.png";
var filePath = Path.Combine(_baseDirectory, fileName);
using var output = new FileStream(filePath, FileMode.CreateNew, FileAccess.Write);
output.Write(screenshotBytes);
return filePath;
}
public void CleanupOldScreenshots(int daysToKeep = 7)
{
if (daysToKeep < 1)
{
throw new ArgumentOutOfRangeException(nameof(daysToKeep));
}
var cutoffDate = DateTime.UtcNow.AddDays(-daysToKeep);
var files = Directory.GetFiles(_baseDirectory, "*screenshot_*.png");
foreach (var file in files)
{
if (Regex.IsMatch(Path.GetFileName(file),
@"\A[A-Za-z0-9_-]*screenshot_[0-9]{8}_[0-9]{6}_[0-9a-f]{32}\.png\z")
&& File.GetLastWriteTimeUtc(file) < cutoffDate)
{
File.Delete(file);
}
}
}
}
Umgang mit unterschiedlichen Bildschirmgrößen
Um responsives Design zu testen, fügen Sie diese Methode zu ScreenshotCapture hinzu, um
verschiedene Browserfenstergrößen zu erfassen. Die Fenstermaße schließen die Browser-Oberfläche ein,
sodass der genaue Viewport abweichen kann. So prüfen Sie responsive Layouts, ohne den User Agent,
die Touch-Eingabe oder das Pixelverhältnis eines Mobilgeräts zu emulieren:
using System;
using System.IO;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using OpenQA.Selenium.Support.Extensions;
public static void CaptureResponsiveScreenshots(string url, string outputDirectory)
{
try
{
Directory.CreateDirectory(outputDirectory);
var viewports = new[]
{
new { Width = 375, Height = 667, Name = "mobile" },
new { Width = 768, Height = 1024, Name = "tablet" },
new { Width = 1920, Height = 1080, Name = "desktop" }
};
var options = new ChromeOptions();
options.AddArgument("--headless=new");
using (var driver = new ChromeDriver(options))
{
foreach (var viewport in viewports)
{
driver.Manage().Window.Size = new System.Drawing.Size(viewport.Width, viewport.Height);
driver.Navigate().GoToUrl(url);
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(d => ((IJavaScriptExecutor)d)
.ExecuteScript("return document.readyState").Equals("complete"));
var screenshot = driver.TakeScreenshot();
var outputPath = Path.Combine(outputDirectory,
$"{viewport.Name}_{Guid.NewGuid():N}.png");
screenshot.SaveAsFile(outputPath);
}
}
}
catch (Exception ex)
{
throw new Exception($"Failed to capture responsive screenshots: {ex.Message}", ex);
}
}
Fazit
Dieser Leitfaden zeigt verschiedene Ansätze, um Screenshots von Webseiten programmgesteuert in .NET zu erstellen, von statischen Seiten über dynamische Inhalte bis hin zu responsiven Designs. Die Beispiele umfassen eine detaillierte Fehlerbehandlung, Hinweise zur Browser-Kompatibilität und bewährte Verfahren für die Verwaltung der Screenshot-Speicherung.
