如何在Web应用程序中使用System.Windows.Forms.WebBrowser?

时间:2009-07-13 13:49:41

标签: c# .net winforms webforms webbrowser-control

我在这里找到了一个winform代码:http://www.wincustomize.com/articles.aspx?aid=136426&c=1

它作为一个winform工作得很好。但我想在网络应用程序中运行代码。

  1. 我将System.Windows.Forms和Microsoft.mshtml.dll的引用添加到我的Web应用程序C:\ Program Files \ Microsoft.NET \ Primary Interop Assemblies \中。

  2. 我将WebPageBitmap.cs复制到我的网络应用程序中。

  3. 我将Program.cs的Main()作为Button_Click()复制到我的网络应用程序。

  4. 当我点击我的网络应用程序中的按钮时。它发生错误:

  5. ActiveX控件'8856f961-340a-11d0-a96b-00c04fd705a2'无法实例化,因为当前线程不在单线程单元中。

    如何在Web应用程序中使用System.Windows.Forms.WebBrowser获取网站缩略图?

    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;
                    }
                }
            }
        }
    }
    

3 个答案:

答案 0 :(得分:3)

您可以创建自己的工作线程并调用SetApartmentState将其更改为STA线程;这个线程可以完成渲染网页的工作。但是,需要进行大量的线程间通信,正如R. Bemrose所说,System.Windows类并非真正设计用于Web应用程序。

另一种方法是重写示例应用程序(作为.EXE)以获取两个参数:(1)要下载的URL,以及(2)屏幕截图图像的输出位置。您的Web应用程序可以创建临时路径(对于输出文件),启动此程序(使用Process.Start),等待它完成,加载它创建的输出文件,然后删除临时文件一旦发送给客户或不再需要。 (当然,如果出现问题,它将需要进行不同的错误处理而不是显示消息框。)

答案 1 :(得分:3)

我已成功在Web应用程序中使用System.Windows.Forms.WebBrowser。

只需按照上述步骤操作,在网页表单页面中添加AspCompat =“true”:

感谢您的所有答案。

答案 2 :(得分:0)

简短的回答是System.Windows中的任何内容都不打算用于Web应用程序。

System.Windows.Forms是客户端控件。但是,Web应用程序在服务器端运行,并在System.Web.UI中拥有自己的UI元素。

mshtml可能是另一个绊脚石。老实说,我不能说它是否可以从IIS访问。

可能有另一种方法可以做到这一点,但我会让那些了解更多信息的人比我回答那个部分。