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

标签 c# .net winforms webforms webbrowser-control

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

而且它作为 winform 工作正常。但我想在网络应用程序中运行代码。

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

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

  3. 我将 Program.cs 的 Main() 作为 Button_Click() 复制到我的 Web 应用。

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

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

最佳答案

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

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

关于c# - 如何在 Web 应用程序中使用 System.Windows.Forms.WebBrowser?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1119549/

相关文章:

.net - 从某些客户端使用 MySqlConnection (.NET) 以 SSL 连接到 MySql-server 失败

c# - 来自 SQL Server 的 Datagrid 使用

C# 模块应该包含程序集 list

c# - 什么类型的编程结构可以用来枚举类?

c# - C#'s equivalent of Java' s <?在泛型中扩展 Base>

c# - 使用 fiddlercore 后关闭应用程序时代理设置未更改

c# - 如何禁用文本框内的鼠标右键单击

c# - 使用动态创建的控件跟踪值

c# - 在 C# 中回滚

由于 StringBuilder 添加新行,Javascript 警报未启动