2009-03-17 10 views
13

Ist es möglich, einen Screenshot einer beliebigen URL mit dem .Net-Code zu erstellen?Wie nehmen Sie einen Screenshot einer Website über .Net-Code?

Was ist der einfachste Weg?

+0

Mit welcher Rendering-Engine?Immerhin werden verschiedene Rendering-Engines unterschiedliche Ergebnisse liefern. –

+0

webkit scheint die meisten Standards zu sein –

+0

wow. dachte nicht, dass es so einfach war :) – Karim

Antwort

3

Ich würde vorschlagen, einen Ansatz von Drittanbietern für diese nicht selbst tun. Wenn Sie darauf bestehen, dann ist die grobe Methode, System.Diagnostics.Process zu verwenden, um einen Browser zu starten, dann GetDesktopImage, um einen Screenshot zu erhalten.

Ich bin sicher, dass es ein einfacher Weg, aber das sieht wie folgt aus:

using System; 
using System.Drawing; 
using System.Drawing.Imaging; 
using System.Runtime.InteropServices; 

public class PlatformInvokeGDI32 
{ 
    public const int SRCCOPY = 13369376; 

    [DllImport("gdi32.dll",EntryPoint="DeleteDC")] 
    public static extern IntPtr DeleteDC(IntPtr hDc); 

    [DllImport("gdi32.dll",EntryPoint="DeleteObject")] 
    public static extern IntPtr DeleteObject(IntPtr hDc); 

    [DllImport("gdi32.dll",EntryPoint="BitBlt")] 
    public static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, int RasterOp); 

    [DllImport ("gdi32.dll",EntryPoint="CreateCompatibleBitmap")] 
    public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc,int nWidth, int nHeight); 

    [DllImport ("gdi32.dll",EntryPoint="CreateCompatibleDC")] 
    public static extern IntPtr CreateCompatibleDC(IntPtr hdc); 

    [DllImport ("gdi32.dll",EntryPoint="SelectObject")] 
    public static extern IntPtr SelectObject(IntPtr hdc,IntPtr bmp); 
} 

public class PlatformInvokeUSER32 
{ 
    public const int SM_CXSCREEN = 0; 
    public const int SM_CYSCREEN = 1; 

    [DllImport("user32.dll", EntryPoint="GetDesktopWindow")] 
    public static extern IntPtr GetDesktopWindow(); 

    [DllImport("user32.dll",EntryPoint="GetDC")] 
    public static extern IntPtr GetDC(IntPtr ptr); 

    [DllImport("user32.dll",EntryPoint="GetSystemMetrics")] 
    public static extern int GetSystemMetrics(int abc); 

    [DllImport("user32.dll",EntryPoint="GetWindowDC")] 
    public static extern IntPtr GetWindowDC(Int32 ptr); 

    [DllImport("user32.dll",EntryPoint="ReleaseDC")] 
    public static extern IntPtr ReleaseDC(IntPtr hWnd,IntPtr hDc); 
} 

public class CaptureScreen 
{ 
    public static Bitmap GetDesktopImage() 
    { 
     //In size variable we shall keep the size of the screen. 
     SIZE size; 

     //Variable to keep the handle to bitmap. 
     IntPtr hBitmap; 

     //Here we get the handle to the desktop device context. 
     IntPtr hDC = PlatformInvokeUSER32.GetDC(PlatformInvokeUSER32.GetDesktopWindow()); 

     //Here we make a compatible device context in memory for screen device context. 
     IntPtr hMemDC = PlatformInvokeGDI32.CreateCompatibleDC(hDC); 

     //We pass SM_CXSCREEN constant to GetSystemMetrics to get the 
     //X coordinates of the screen. 
     size.cx = PlatformInvokeUSER32.GetSystemMetrics(PlatformInvokeUSER32.SM_CXSCREEN); 

     //We pass SM_CYSCREEN constant to GetSystemMetrics to get the Y coordinates of the screen. 
     size.cy = PlatformInvokeUSER32.GetSystemMetrics (PlatformInvokeUSER32.SM_CYSCREEN); 

     //We create a compatible bitmap of the screen size and using the screen device context. 
     hBitmap = PlatformInvokeGDI32.CreateCompatibleBitmap(hDC, size.cx, size.cy); 

     //As hBitmap is IntPtr, we cannot check it against null. 
     //For this purpose, IntPtr.Zero is used. 
     if(hBitmap != IntPtr.Zero) 
     { 
      //Here we select the compatible bitmap in the memeory device 
      //context and keep the refrence to the old bitmap. 
      IntPtr hOld = (IntPtr) PlatformInvokeGDI32.SelectObject(hMemDC, hBitmap); 

      //We copy the Bitmap to the memory device context. 
      PlatformInvokeGDI32.BitBlt(hMemDC, 0, 0, size.cx, size.cy, hDC, 0, 0, PlatformInvokeGDI32.SRCCOPY); 

      //We select the old bitmap back to the memory device context. 
      PlatformInvokeGDI32.SelectObject(hMemDC, hOld); 

      //We delete the memory device context. 
      PlatformInvokeGDI32.DeleteDC(hMemDC); 

      //We release the screen device context. 
      PlatformInvokeUSER32.ReleaseDC(PlatformInvokeUSER32.GetDesktopWindow(), hDC); 

      //Image is created by Image bitmap handle and stored in local variable. 
      Bitmap bmp = System.Drawing.Image.FromHbitmap(hBitmap); 

      //Release the memory to avoid memory leaks. 
      PlatformInvokeGDI32.DeleteObject(hBitmap); 

      //This statement runs the garbage collector manually. 
      GC.Collect(); 

      //Return the bitmap 
      return bmp; 
     } 

     //If hBitmap is null, retun null. 
     return null; 
    } 
} 

//This structure shall be used to keep the size of the screen. 
public struct SIZE 
{ 
    public int cx; 
    public int cy; 
} 
2

Es gibt mehrere 3rd-Party-Komponenten, die dies tut. Anscheinend ist es nicht trivial, da Dinge wie Flash und andere Dinge nicht so einfach erfasst werden können.

Ich habe HTMLSnapshot in der Vergangenheit verwendet und war damit zufrieden (es ist nicht kostenlos, aber ziemlich billig).

Ich schlage vor, dass Sie nicht zu viel Zeit damit verschwenden, dies selbst zu implementieren, weil Sie am Ende viele Endfälle wiederholen müssen, die diese Lösungen von Drittanbietern bereits handhaben.

+0

Ich frage mich, ob jemand Larry Page und Sergey Brin das gleiche empfohlen hat: P –

2

Ich suchte weit und breit nach einer Lösung für dieses Problem und das Problem mit der Verwendung des WebBrowser und andere Vorschläge ist, dass Sie eine Menge Zugriff auf die Box benötigen.

Bisher dies der beste Drittanbieter-Tool ist ich fündig geworden:

http://www.websitesscreenshot.com/

Ihre SEO ist schrecklich, aber ich glaube, ich sie auf einem Forum oder sogar Stapel ... fand ich besitzen Sie eine Lizenz und was Sie erhalten, ist nur eine einzelne DLL, die Sie verweisen können. Wenn Sie eine Lizenz an den Konstruktor übergeben, wird das Wasserzeichen entfernt.

Nach einem kurzen Blick mit ILSpy glaube ich, was es tut ist, dass es den HTML-Code interpretiert und ein Bild für Ihr Sehvergnügen ablegt.

Nutzungs

Speichern einer URL

WebsitesScreenshot.WebsitesScreenshot _Obj; 
_Obj = new WebsitesScreenshot.WebsitesScreenshot(); 
WebsitesScreenshot.WebsitesScreenshot.Result _Result; 
_Result = _Obj.CaptureWebpage("http://www.google.com"); 
if (_Result == WebsitesScreenshot.WebsitesScreenshot.Result.Captured) 
{ 
    _Obj.ImageFormat = WebsitesScreenshot. 
     WebsitesScreenshot.ImageFormats.PNG; 
    _Obj.SaveImage ("c:\\google.png"); 
}    
_Obj.Dispose(); 

Saving Raw HTML String

WebsitesScreenshot.WebsitesScreenshot _Obj; 
_Obj=new WebsitesScreenshot.WebsitesScreenshot(); 
WebsitesScreenshot.WebsitesScreenshot.Result _Result; 
_Result = _Obj.CaptureHTML(
"<html><body><h1> Hello world </h1></body></html>"); 
if (_Result == WebsitesScreenshot.WebsitesScreenshot.Result.Captured) 
{ 
    _Obj.ImageFormat = WebsitesScreenshot. 
     WebsitesScreenshot.ImageFormats.GIF; 
    _Obj.SaveImage("c:\\test.gif"); 
} 
_Obj.Dispose(); 

Sie können mehr über ihre Nutzung Seite. Gefunden hier:

http://www.websitesscreenshot.com/Usage.html

hoffe, das hilft!

Prost !!