2009-07-13 3 views
1

Ich fand einen Code von Winform hier: http://www.wincustomize.com/articles.aspx?aid=136426&c=1Wie verwende ich System.Windows.Forms.WebBrowser in einer Web-App?

Und es funktioniert gut als Winform. Aber ich möchte den Code in einer Web-App ausführen.

  1. ich hinzufügen, die Referenzen von System.Windows.Forms und die Microsoft.mshtml.dll im Verzeichnis C: \ Programme \ Microsoft.NET \ Primary Interop Assemblies \ meinen Web-App.

  2. Ich kopiere die WebPageBitmap.cs in meine Webanwendung.

  3. Ich kopiere die Main() von Program.cs als Button_Click() in meine Web App.

  4. Wenn ich auf den Button in meiner Web-App klicke. Es tritt ein Fehler auf:

ActiveX control '8856f961-340a-11D0-a96b-00c04fd705a2' kann nicht instanziiert werden, da der aktuelle Thread nicht in einer Single-Threaded-Wohnung ist.

Wie kann ich System.Windows.Forms.WebBrowser in einer Webanwendung verwenden, um eine Web Site Thumbnail zu erhalten?

public partial class Capture01 : System.Web.UI.Page 
{ 
    public delegate void WebBrowserDocumentCompletedEventHandler(object sender, WebBrowserDocumentCompletedEventArgs e); 

    [STAThread] 
    protected void Button1_Click(object sender, EventArgs e) 
    {   
     int width = 1024; 
     int height = 900; 

     int thumbwidth = width; 
     int thumbheight = height;   

     string fileName = "image01.jpg"; 
     string url = "http://www.iweixtest.cn/WE/Site/1647/index.aspx";   
     thumbwidth = 150; 
     thumbheight = 100; 

     //WebPageBitmap webBitmap = new WebPageBitmap(args[0], width, height, false, 10000); 
     WebPageBitmap webBitmap = new WebPageBitmap(url, width, height, false, 10000); 
     if (webBitmap.IsOk) 
     { 
      webBitmap.Fetch(); 
      Bitmap thumbnail = webBitmap.GetBitmap(thumbwidth, thumbheight); 
      //thumbnail.Save(args[1], ImageFormat.Jpeg); 
      thumbnail.Save(fileName, ImageFormat.Jpeg); 
      thumbnail.Dispose(); 
     } 
     else 
     { 
      MessageBox.Show(webBitmap.ErrorMessage); 
     }  
    } 
} 

WebPageBitmap.cs

namespace GetSiteThumbnail 
{ 
    /// <summary> 
    /// Thanks for the solution to the "sometimes not painting sites to Piers Lawson 
    /// Who performed some extensive research regarding the origianl implementation. 
    /// You can find his codeproject profile here: 
    /// http://www.codeproject.com/script/Articles/MemberArticles.aspx?amid=39324 
    /// </summary> 
    [InterfaceType(1)] 
    [Guid("3050F669-98B5-11CF-BB82-00AA00BDCE0B")] 
    public interface IHTMLElementRender2 
    { 
     void DrawToDC(IntPtr hdc); 
     void SetDocumentPrinter(string bstrPrinterName, ref _RemotableHandle hdc); 
    } 

    /// <summary> 
    /// Code by Adam Najmanowicz 
    /// http://www.codeproject.com/script/Membership/Profiles.aspx?mid=923432 
    /// http://blog.najmanowicz.com/ 
    /// Some improvements suggested by Frank Herget 
    /// http://www.artviper.net/ 
    /// </summary> 
    class WebPageBitmap 
    { 
     private WebBrowser webBrowser; 
     private string url; 
     private int width; 
     private int height; 
     private bool isOk; 
     private string errorMessage; 

     public string ErrorMessage 
     { 
      get { return errorMessage; } 
     } 

     public bool IsOk 
     { 
      get { return isOk; } 
      set { isOk = value; } 
     } 

     public WebPageBitmap(string url, int width, int height, bool scrollBarsEnabled, int wait) 
     { 
      this.width = width; 
      this.height = height; 

      this.url = 
       url.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase) ? 
       url : this.url = "http://" + url; 

      try 
      // needed as the script throws an exeception if the host is not found 
      { 
       HttpWebRequest req = (HttpWebRequest)WebRequest.Create(this.url); 
       req.AllowAutoRedirect = true; 
       //req.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.0.04506; .NET CLR 3.5.21022; .NET CLR 1.0.3705; .NET CLR 1.1.4322)"; //成功 
       req.UserAgent = "Mozilla/4.0 (Compatible; Windows NT 5.1; MSIE 6.0) (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)"; 
       //req.Referer = "http://www.cognifide.com"; 
       req.ContentType = "text/html"; 
       req.Accept = "*/*"; 
       req.KeepAlive = false; 

       using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse()) 
       { 
        string x = resp.StatusDescription; 
       }  
      } 
      catch (Exception ex) 
      { 
       errorMessage = ex.Message; 
       isOk = false; 
       return; 
      } 
      isOk = true;              // public, to check in program.cs if the domain is found, so the image can be saved 

      webBrowser = new WebBrowser(); 
      webBrowser.DocumentCompleted += 
      new WebBrowserDocumentCompletedEventHandler(documentCompletedEventHandler); 
      webBrowser.Size = new Size(width, height); 
      webBrowser.ScrollBarsEnabled = false; 
     } 

     /// <summary> 
     /// Fetches the image 
     /// </summary> 
     /// <returns>true is the operation ended with a success</returns> 
     public bool Fetch() 
     { 
      HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url); 
      req.AllowAutoRedirect = true; 
      //req.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.0.04506; .NET CLR 3.5.21022; .NET CLR 1.0.3705; .NET CLR 1.1.4322)"; 
      req.UserAgent = "Mozilla/4.0 (Compatible; Windows NT 5.1; MSIE 6.0) (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)"; 
      //req.Referer = "http://www.cognifide.com"; 
      req.ContentType = "text/html"; 
      req.AllowWriteStreamBuffering = true; 
      req.AutomaticDecompression = DecompressionMethods.GZip; 
      req.Method = "GET"; 
      req.Proxy = null; 
      req.ReadWriteTimeout = 20; 

      HttpStatusCode status; 
      using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse()) 
      { 
       status = resp.StatusCode; 
      } 

      if (status == HttpStatusCode.OK || status == HttpStatusCode.Moved) 
      { 
       webBrowser.Navigate(url); 
       while (webBrowser.ReadyState != WebBrowserReadyState.Complete) 
       { 
        Application.DoEvents(); 

       } 
       return true; 
      } 
      else 
      { 
       return false; 
      } 
     } 

     private void documentCompletedEventHandler(object sender, WebBrowserDocumentCompletedEventArgs e) 
     { 
      ((WebBrowser)sender).Document.Window.Error += 
       new HtmlElementErrorEventHandler(SuppressScriptErrorsHandler); 
     } 

     public void SuppressScriptErrorsHandler(object sender, HtmlElementErrorEventArgs e) 
     { 
      e.Handled = true; 
      MessageBox.Show("Error!"); 
     } 

     internal Bitmap GetBitmap(int thumbwidth, int thumbheight) 
     { 
      IHTMLDocument2 rawDoc = (IHTMLDocument2)webBrowser.Document.DomDocument; 
      IHTMLElement rawBody = rawDoc.body; 
      IHTMLElementRender2 render = (IHTMLElementRender2)rawBody; 

      Bitmap bitmap = new Bitmap(width, height); 
      Rectangle bitmapRect = new Rectangle(0, 0, width, height); 

      // Interesting thing that despite using the renderer later 
      // this following line is still necessary or 
      // the background may not be painted on some websites. 
      webBrowser.DrawToBitmap(bitmap, bitmapRect); 

      using (Graphics graphics = Graphics.FromImage(bitmap)) 
      { 
       IntPtr graphicshdc = graphics.GetHdc(); 
       render.DrawToDC(graphicshdc); 

       graphics.ReleaseHdc(graphicshdc); 
       graphics.Dispose(); 

       if (thumbheight == height && thumbwidth == width) 
       { 
        return bitmap; 
       } 
       else 
       { 
        Bitmap thumbnail = new Bitmap(thumbwidth, thumbheight); 
        using (Graphics gfx = Graphics.FromImage(thumbnail)) 
        { 
         // high quality image sizing 
         gfx.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;        
         gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;                  // make it look pretty 
         gfx.DrawImage(bitmap, new Rectangle(0, 0, thumbwidth, thumbheight), bitmapRect, GraphicsUnit.Pixel); 
        } 
        bitmap.Dispose(); 
        return thumbnail; 
       } 
      } 
     } 
    } 
} 

Antwort

3

Ich habe erfolgreich System.Windows.Forms.WebBrowser in einer Web-App verwendet.

folgen Sie einfach den Schritten oben und AspCompat = "true" in der webform Seite hinzufügen:

Sie die alle Antworten danken für.

0

Die kurze Antwort ist, dass nichts in System.Windows in einer Web-Anwendung verwendet werden soll.

System.Windows.Forms sind Clientsteuerelemente. Webanwendungen werden jedoch auf der Serverseite ausgeführt und verfügen über eigene Benutzeroberflächenelemente in System.Web.UI.

mshtml kann ein weiterer Stolperstein sein. Ich könnte ehrlich nicht sagen, ob es von IIS aus zugänglich wäre.

Es mag einen anderen Weg geben, aber ich lasse jemanden, der mehr darüber weiß, als ich diesen Teil beantworten.

3

Sie könnten Ihren eigenen Worker-Thread erstellen und SetApartmentState aufrufen, um ihn in einen STA-Thread zu ändern. Dieser Thread könnte das Rendern von Webseiten übernehmen. Allerdings wäre eine Vielzahl von Inter-Thread-Kommunikation erforderlich und, wie R. Bemrose sagte, die System.Windows Klassen sind nicht wirklich entworfen, um in einer Web-App verwendet werden.

Ein anderer Ansatz wäre, die Beispielanwendung (als .EXE) neu zu schreiben, um zwei Parameter zu erhalten: (1) die URL zum Herunterladen und (2) den Ausgabeort für das Screenshotbild. Ihre Webanwendung könnte einen temporären Pfad (für die Ausgabedatei) erstellen, dieses Programm starten (mit Process.Start), auf den Abschluss warten, die erstellte Ausgabedatei laden und dann die temporäre Datei löschen, nachdem sie an den Client gesendet wurde war sonst nicht mehr nötig. (Es müsste natürlich eine andere Fehlerbehandlung als eine Meldungsbox anzeigen, wenn etwas schief gelaufen ist.)

Verwandte Themen