我有一个.NET 2.0 WebBrowser控件,该控件用于在没有用户交互的情况下导航某些页面(不要问...长话短说)。由于此应用程序的用户较少,因此我将WebBrowser控件的ScriptErrorsSuppressed属性设置为true,VS 2005状态随附的文档将隐藏所有来自基础ActiveX控件的对话框,不只是脚本错误。"但是,MSDN文章没有提到这一点。
我设法取消了NewWindow事件,该事件可以防止弹出窗口,因此已经解决了这个问题。
任何人都有使用其中一种方法并成功阻止所有对话框,脚本错误等的经验吗?
编辑
这不是IE的独立实例,而是Windows Form应用程序上的WebBrowser控件的实例。任何人都对此控件或基础控件AxSHDocVW有经验吗?
再次编辑
抱歉,我忘了提及这一点...我试图仅使用OK按钮来阻止JavaScript alert()。也许我可以转换为IHTMLDocument2对象并以这种方式访问?疟荆乙丫褂昧薓SHTML一点,有人知道吗?
为了方便地注入神奇的javascript代码,请阅读如何将javascript注入到webbrowser控件中。
或者只使用下面的完整代码:
1 2 3 4 5 6 7
| private void InjectAlertBlocker() {
HtmlElement head = webBrowser1.Document.GetElementsByTagName("head")[0];
HtmlElement scriptEl = webBrowser1.Document.CreateElement("script");
string alertBlocker ="window.alert = function () { }";
scriptEl.SetAttribute("text", alertBlocker);
head.AppendChild(scriptEl);
} |
这绝对是很棘手的,但是如果您使用WebBrowser控件进行任何工作,您都会发现自己在做很多棘手的事情。
这是我所知道的最简单的方法。您需要注入JavaScript以覆盖警报功能...注入此JavaScript函数的过程如下:
1
| window.alert = function () { } |
有很多方法可以做到这一点,但这是很有可能的。一种可能性是挂钩DWebBrowserEvents2接口的实现。完成此操作后,您可以将其插入NavigateComplete,DownloadComplete或DocumentComplete(或我们的一些变体)中,然后调用已实现的InjectJavaScript方法来执行对窗口的覆盖。方法。
就像我说的,hacky,但是它可以用:)
如果需要,我可以详细介绍。
您可能必须自定义一些内容,看看IDocHostUIHandler,然后查看其他一些相关的接口。您甚至可以自定义对话框显示/用户界面(我想不起来是哪个界面执行的),您可以拥有相当多的控制权。我很确定您可以做您想做的事,但这确实需要对MSHTML的内部进行处理,并能够实现各种COM接口。
其他一些想法:
http://msdn.microsoft.com/en-us/library/aa770041.aspx
1 2
| IHostDialogHelper
IDocHostShowUI |
这些可能就是您要实现的东西。
防弹警报拦截器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| Browser.Navigated +=
new WebBrowserNavigatedEventHandler(
(object sender, WebBrowserNavigatedEventArgs args) => {
Action<HtmlDocument> blockAlerts = (HtmlDocument d) => {
HtmlElement h = d.GetElementsByTagName("head")[0];
HtmlElement s = d.CreateElement("script");
IHTMLScriptElement e = (IHTMLScriptElement)s.DomElement;
e.text ="window.alert=function(){};";
h.AppendChild(s);
};
WebBrowser b = sender as WebBrowser;
blockAlerts(b.Document);
for (int i = 0; i < b.Document.Window.Frames.Count; i++)
try { blockAlerts(b.Document.Window.Frames[i].Document); }
catch (Exception) { };
}
); |
本示例假定您已添加Microsoft.mshtml参考,"使用mshtml;"。在名称空间中,浏览器是WebBrowser实例。
为什么防弹呢?首先,它处理框架内的脚本。这样,当文档中存在特殊的"杀手frame"时,它就不会崩溃。"杀手框架"是在尝试将其用作HtmlWindow对象时引发异常的框架。 Document.Window.Frames上使用的任何" foreach"都将导致异常,因此必须将更安全的" for"循环与try / catch块一起使用。
也许这不是最易读的代码段,但它适用于现实生活中格式错误的页面。
可以通过实现INewWindowManager接口来阻止window.showModelessDialog和window.showModalDialog,下面的代码另外显示了如何通过实现IDocHostShowUI来阻止警报对话框
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| public class MyBrowser : WebBrowser
{
[PermissionSetAttribute(SecurityAction.LinkDemand, Name ="FullTrust")]
public MyBrowser()
{
}
protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
{
var manager = new NewWindowManagerWebBrowserSite(this);
return manager;
}
protected class NewWindowManagerWebBrowserSite : WebBrowserSite, IServiceProvider, IDocHostShowUI
{
private readonly NewWindowManager _manager;
public NewWindowManagerWebBrowserSite(WebBrowser host)
: base(host)
{
_manager = new NewWindowManager();
}
public int ShowMessage(IntPtr hwnd, string lpstrText, string lpstrCaption, int dwType, string lpstrHelpFile, int dwHelpContext, out int lpResult)
{
lpResult = 0;
return Constants.S_OK; // S_OK Host displayed its UI. MSHTML does not display its message box.
}
// Only files of types .chm and .htm are supported as help files.
public int ShowHelp(IntPtr hwnd, string pszHelpFile, uint uCommand, uint dwData, POINT ptMouse, object pDispatchObjectHit)
{
return Constants.S_OK; // S_OK Host displayed its UI. MSHTML does not display its message box.
}
#region Implementation of IServiceProvider
public int QueryService(ref Guid guidService, ref Guid riid, out IntPtr ppvObject)
{
if ((guidService == Constants.IID_INewWindowManager && riid == Constants.IID_INewWindowManager))
{
ppvObject = Marshal.GetComInterfaceForObject(_manager, typeof(INewWindowManager));
if (ppvObject != IntPtr.Zero)
{
return Constants.S_OK;
}
}
ppvObject = IntPtr.Zero;
return Constants.E_NOINTERFACE;
}
#endregion
}
}
[ComVisible(true)]
[Guid("01AFBFE2-CA97-4F72-A0BF-E157038E4118")]
public class NewWindowManager : INewWindowManager
{
public int EvaluateNewWindow(string pszUrl, string pszName,
string pszUrlContext, string pszFeatures, bool fReplace, uint dwFlags, uint dwUserActionTime)
{
// use E_FAIL to be the same as CoInternetSetFeatureEnabled with FEATURE_WEBOC_POPUPMANAGEMENT
//int hr = MyBrowser.Constants.E_FAIL;
int hr = MyBrowser.Constants.S_FALSE; //Block
//int hr = MyBrowser.Constants.S_OK; //Allow all
return hr;
}
} |
1
| webBrowser1.ScriptErrorsSuppressed = true; |
只需将其添加到您的入门级功能即可。经过大量研究后,我遇到了这种方法,并且一直接触到木材。干杯!!
InjectAlertBlocker是绝对正确的
代码是
1 2 3 4 5 6 7 8
| private void InjectAlertBlocker() {
HtmlElement head = webBrowser1.Document.GetElementsByTagName("head")[0];
HtmlElement scriptEl = webBrowser1.Document.CreateElement("script");
IHTMLScriptElement element = (IHTMLScriptElement)scriptEl.DomElement;
string alertBlocker ="window.alert = function () { }";
element.text = alertBlocker;
head.AppendChild(scriptEl);
} |
需要添加的参考是
添加对MSHTML的引用,该引用在COM引用下将被称为" Microsoft HTML对象库"。
将using mshtml;添加到您的名称空间。
获取对脚本元素的IHTMLElement的引用:
然后,可以将webbrowser的Navigated事件用作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| private void InjectAlertBlocker()
{
HtmlElement head = webBrowser1.Document.GetElementsByTagName("head")[0];
HtmlElement scriptEl = webBrowser1.Document.CreateElement("script");
IHTMLScriptElement element = (IHTMLScriptElement)scriptEl.DomElement;
string alertBlocker ="window.alert = function () { }";
element.text = alertBlocker;
head.AppendChild(scriptEl);
}
private void webDest_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
InjectAlertBlocker();
} |
我刚刚在Code Project上发表了一篇文章,可能会对您有所帮助。
请参阅-http://www.codeproject.com/KB/shell/WebBrowserControlDialogs.aspx
希望这可以帮助。
最简单的方法是:
在:Webbrowser Control中,您具有步骤(标准)BeforeScriptExecute
(BeforeScriptExecute的参数是pdispwindow)
添加:
1
| pdispwindow.execscript("window.alert = function () { }") |
这样,在页面窗口警报上执行任何脚本之前,都将被注入的代码抑制。
只需从浏览器控件属性即可:scriptErrorSupressed = true
我对此有更大的问题:加载一个用于打印的网页,它会显示令人讨厌的"打印"对话框。 InjectBlocker是唯一可行的方法,但相当不可靠。在某些情况下(我正在考虑由于WebBrowser控件使用IE引擎,而这取决于已安装的IE版本),仍然会出现打印对话框。这是一个主要问题,该解决方案适用于安装了IE9的Win7,但是无论如何,带IE8的WinXP都会显示该对话框。
我认为解决方案是在控件呈现页面之前修改源代码并删除打印javascript。但是,我尝试使用:webbrowser控件的DocumentText属性,它不起作用。当我修改源时,该属性不是只读的,但是没有任何作用。
我为问题找到的解决方案是Exec脚本:
1 2
| string alertBlocker ="window.print = function emptyMethod() { }; window.alert = function emptyMethod() { }; window.open = function emptyMethod() { };";
this.Document.InvokeScript("execScript", new Object[] { alertBlocker,"JavaScript" }); |
通过创建扩展的WebBroswer类并覆盖OnNavigated方法,我设法注入了上面的代码。
这似乎工作得很好:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class WebBrowserEx : WebBrowser
{
public WebBrowserEx ()
{
}
protected override void OnNavigated( WebBrowserNavigatedEventArgs e )
{
HtmlElement he = this.Document.GetElementsByTagName("head" )[0];
HtmlElement se = this.Document.CreateElement("script" );
mshtml.IHTMLScriptElement element = (mshtml.IHTMLScriptElement)se.DomElement;
string alertBlocker ="window.alert = function () { }";
element.text = alertBlocker;
he.AppendChild( se );
base.OnNavigated( e );
}
} |
您是否要实施网络机器人?我在使用托管IE控件方面经验很少,但是我确实完成了一些尝试使用IE控件的Win32项目。禁用弹出窗口应通过控件的事件处理程序完成,就像我已经做过的一样,但是我发现您还需要在IE选项中更改"禁用脚本调试xxxx"(或者您可以在代码中修改注册表),如下所示: cjheath已经指出。但是,我还发现,需要检查导航URL中是否有任何可下载的内容,以防止那些打开/保存对话框的出现,需要执行额外的步骤。但是我不知道如何处理流文件,因为我不能仅通过查看URL来跳过它们,最后我转向Indy库,省去了处理IE的所有麻烦。最后,我记得Microsoft确实在网上提到了IE并非旨在用作OLE控件的内容。根据我自己的经验,每次控件导航到新页面时,确实会引入程序的内存泄漏!