对 COM 组件的调用返回了错误 HRESULT E_FAIL

时间:2021-02-06 18:29:30
我用 WebBrowser(.net 2.0内置的类) 来实现网页截图功能,代码正常运行一两天,就会出现异常:对 COM 组件的调用返回了错误 HRESULT E_FAIL。

更离奇的是:一但出现一次,只要不重启程序,程序运行这段代码时,这个异常会一直出现。我不懂 COM组件(WebBrowser)的实现,难道它是 Singleton 模式吗?我明明是每次都释放,下次运行时,再创建一个新实例。

下面是截图这部分的代码:

using (WebBrowser webBrowser = new WebBrowser())
{
    webBrowser.ScrollBarsEnabled = false;
    webBrowser.ScriptErrorsSuppressed = true;
    webBrowser.Navigate(url);

    while (webBrowser.ReadyState != WebBrowserReadyState.Complete)
    {
        Application.DoEvents();
    }

    if (webBrowser.Document.Body.InnerText.Trim() == "")
    {
        throw new Exception("Document.Body.InnerText 为空,无法完成截图。");
    }

    if (webBrowser.Document.Body.InnerText.Contains("已取消到该网页的导航"))
    {
        throw new Exception("加载网页出错:已取消到该网页的导航。无法完成截图。");
    }

    webBrowser.ClientSize = new Size(this.browserWidth, this.browserHeight);
    webBrowser.ScrollBarsEnabled = false;

    this.bitmap = new Bitmap(webBrowser.Bounds.Width, webBrowser.Bounds.Height);
    webBrowser.BringToFront();
    webBrowser.DrawToBitmap(this.bitmap, webBrowser.Bounds);    // 将图片截取到全局变量

    // 不再要再做缩略图转换,可以提高效率和稳定性。
    //bitmap = (Bitmap)bitmap.GetThumbnailImage(thumbnailWidth, thumbnailHeight, null, IntPtr.Zero);
}


另外,CSDN 这个帖子编辑框,一打字快了,怎么这卡?它好像一直在用 ajax 回传东西还是怎么,你们的浏览器这样吗?用着真难受。

13 个解决方案

#1


com组建模型中,组建是独立于调用者的,一般来说,组件有自己的进程,WebBrowser其实在IE浏览器的进程提供的组建服务,你创建一个WebBrowser对象,只是创建了一个访问IE进程的代理对象而已,

不论你new WebBrowser多少次,你访问的都是同一个IE进程,

应该你的IE出故障了,重装IE可能就可以解决问题,

#2


引用 1 楼 stonespace 的回复:
com组建模型中,组建是独立于调用者的,一般来说,组件有自己的进程,WebBrowser其实在IE浏览器的进程提供的组建服务,你创建一个WebBrowser对象,只是创建了一个访问IE进程的代理对象而已,

不论你new WebBrowser多少次,你访问的都是同一个IE进程,

应该你的IE出故障了,重装IE可能就可以解决问题,


谢谢 stonespace :

服务器上是新装的IE8(之前是系统自带的IE6),这个要重装吗?另外,像你说的,我调用IE进程的代理过于频繁,会不会有什么瓶颈?我有至少3个以上的线程同时截图。


#3


对了,我重启程序后,就又好了。但程序运行一两天,就又不行了。必须要重启。

#4


windows自己都大量引用WebBrowser控件,不要紧的,

引用 2 楼 oldhunter 的回复:
引用 1 楼 stonespace 的回复:com组建模型中,组建是独立于调用者的,一般来说,组件有自己的进程,WebBrowser其实在IE浏览器的进程提供的组建服务,你创建一个WebBrowser对象,只是创建了一个访问IE进程的代理对象而已,

不论你new WebBrowser多少次,你访问的都是同一个IE进程,

应该你的IE出故障了,重装IE可能就可以……

#5


不要用while (webBrowser.ReadyState != WebBrowserReadyState.Complete)
而是在 webbrowser.documentcommplte事件里面写

#6


引用 5 楼 hdt 的回复:
不要用while (webBrowser.ReadyState != WebBrowserReadyState.Complete)
而是在 webbrowser.documentcommplte事件里面写


为什么呢? 那样也是在等运行完后再做截图处理啊?

#7


引用 1 楼 stonespace 的回复:
com组建模型中,组建是独立于调用者的,一般来说,组件有自己的进程,WebBrowser其实在IE浏览器的进程提供的组建服务,你创建一个WebBrowser对象,只是创建了一个访问IE进程的代理对象而已,

不论你new WebBrowser多少次,你访问的都是同一个IE进程,

应该你的IE出故障了,重装IE可能就可以解决问题,


就是就是。
ie出现问题是正常的。

#8


webbrowser经常内存泄漏,这和javascript垃圾回收机制不完善有关。

#9


引用 8 楼 caozhy 的回复:
webbrowser经常内存泄漏,这和javascript垃圾回收机制不完善有关。


谢谢 caozhy(一看就是牛人),也谢谢上面的 hdt,zanfeng。

那c# 有没有办法操作 webbrowser COM组件的对象?出问题后可以销毁它,重新创建一个对象,它是不是用的对象池?

我这几天为了解决这个问题,翻了很多讲COM原理的书。网上下了一个 COM多线程模型、DCOM——潘爱民.pdf,里面一些截图讲得挺明白。

如果能控制这个COM组件在内存泄露后销毁,就可以了,毕竟我们改变不了它,是MS的东西。

#10


该回复于2013-03-27 14:14:20被管理员删除

#11


最近我也遇到这个问题了!不过调用的是其他的组件!

#12


你重启一下vs一下试试。我也遇到过这样的问题,我调用的是自定义组件,莫名其妙就出现了那个问题,重启一下就好了。

#13


我用的webkit.net也出这个问题

#1


com组建模型中,组建是独立于调用者的,一般来说,组件有自己的进程,WebBrowser其实在IE浏览器的进程提供的组建服务,你创建一个WebBrowser对象,只是创建了一个访问IE进程的代理对象而已,

不论你new WebBrowser多少次,你访问的都是同一个IE进程,

应该你的IE出故障了,重装IE可能就可以解决问题,

#2


引用 1 楼 stonespace 的回复:
com组建模型中,组建是独立于调用者的,一般来说,组件有自己的进程,WebBrowser其实在IE浏览器的进程提供的组建服务,你创建一个WebBrowser对象,只是创建了一个访问IE进程的代理对象而已,

不论你new WebBrowser多少次,你访问的都是同一个IE进程,

应该你的IE出故障了,重装IE可能就可以解决问题,


谢谢 stonespace :

服务器上是新装的IE8(之前是系统自带的IE6),这个要重装吗?另外,像你说的,我调用IE进程的代理过于频繁,会不会有什么瓶颈?我有至少3个以上的线程同时截图。


#3


对了,我重启程序后,就又好了。但程序运行一两天,就又不行了。必须要重启。

#4


windows自己都大量引用WebBrowser控件,不要紧的,

引用 2 楼 oldhunter 的回复:
引用 1 楼 stonespace 的回复:com组建模型中,组建是独立于调用者的,一般来说,组件有自己的进程,WebBrowser其实在IE浏览器的进程提供的组建服务,你创建一个WebBrowser对象,只是创建了一个访问IE进程的代理对象而已,

不论你new WebBrowser多少次,你访问的都是同一个IE进程,

应该你的IE出故障了,重装IE可能就可以……

#5


不要用while (webBrowser.ReadyState != WebBrowserReadyState.Complete)
而是在 webbrowser.documentcommplte事件里面写

#6


引用 5 楼 hdt 的回复:
不要用while (webBrowser.ReadyState != WebBrowserReadyState.Complete)
而是在 webbrowser.documentcommplte事件里面写


为什么呢? 那样也是在等运行完后再做截图处理啊?

#7


引用 1 楼 stonespace 的回复:
com组建模型中,组建是独立于调用者的,一般来说,组件有自己的进程,WebBrowser其实在IE浏览器的进程提供的组建服务,你创建一个WebBrowser对象,只是创建了一个访问IE进程的代理对象而已,

不论你new WebBrowser多少次,你访问的都是同一个IE进程,

应该你的IE出故障了,重装IE可能就可以解决问题,


就是就是。
ie出现问题是正常的。

#8


webbrowser经常内存泄漏,这和javascript垃圾回收机制不完善有关。

#9


引用 8 楼 caozhy 的回复:
webbrowser经常内存泄漏,这和javascript垃圾回收机制不完善有关。


谢谢 caozhy(一看就是牛人),也谢谢上面的 hdt,zanfeng。

那c# 有没有办法操作 webbrowser COM组件的对象?出问题后可以销毁它,重新创建一个对象,它是不是用的对象池?

我这几天为了解决这个问题,翻了很多讲COM原理的书。网上下了一个 COM多线程模型、DCOM——潘爱民.pdf,里面一些截图讲得挺明白。

如果能控制这个COM组件在内存泄露后销毁,就可以了,毕竟我们改变不了它,是MS的东西。

#10


该回复于2013-03-27 14:14:20被管理员删除

#11


最近我也遇到这个问题了!不过调用的是其他的组件!

#12


你重启一下vs一下试试。我也遇到过这样的问题,我调用的是自定义组件,莫名其妙就出现了那个问题,重启一下就好了。

#13


我用的webkit.net也出这个问题