title: How to use System.Windows.Forms.WebBrowser in a web app?
body: <p>I found a code of winform here: <a href="http://www.wincustomize.com/articles.aspx?aid=136426&amp;c=1" rel="nofollow noreferrer">http://www.wincustomize.com/articles.aspx?aid=136426&amp;c=1</a></p>
  
  <p>And it works fine as a winform. But I want to run the code in a web app.</p>
  
  <ol>
  <li><p>I add the references of System.Windows.Forms and the Microsoft.mshtml.dll in the C:\Program Files\Microsoft.NET\Primary Interop Assemblies\  to my web app.</p></li>
  <li><p>I copy the WebPageBitmap.cs into my web app.</p></li>
  <li><p>I copy the Program.cs 's Main() to my web app as a Button_Click().</p></li>
  <li><p>When I click the button in my web app. It occurs an error:</p></li>
  </ol>
  
  <p>ActiveX control '8856f961-340a-11d0-a96b-00c04fd705a2' cannot be instantiated because the current thread is not in a single-threaded apartment.</p>
  
  <p>How can I use System.Windows.Forms.WebBrowser in a web app to get a Web Site Thumbnail?</p>
  
  <pre><code>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);
          }       
      }
  }
  </code></pre>
  
  <p>WebPageBitmap.cs</p>
  
  <pre><code>namespace GetSiteThumbnail
  {
      /// &lt;summary&gt;
      /// 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
      /// &lt;/summary&gt;
      [InterfaceType(1)]
      [Guid("3050F669-98B5-11CF-BB82-00AA00BDCE0B")]
      public interface IHTMLElementRender2
      {
          void DrawToDC(IntPtr hdc);
          void SetDocumentPrinter(string bstrPrinterName, ref _RemotableHandle hdc);
      }
  
      /// &lt;summary&gt;
      /// 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/
      /// &lt;/summary&gt;
      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;
          }
  
          /// &lt;summary&gt;
          /// Fetches the image 
          /// &lt;/summary&gt;
          /// &lt;returns&gt;true is the operation ended with a success&lt;/returns&gt;
          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 &amp;&amp; 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;
                  }
              }
          }
      }
  }
  </code></pre>