1.什么是javascript脚本错误

1.1    概述

JavaScript脚本错误包含“运行时错误”和“语法错误”。

1.2    JavaScript“语法错误”

JavaScript语法错误是指当 JavaScript语句违反了 JavaScript脚本语言的一条或多条语法规则时导致的错误。JavaScript语法错误发生在程序编译阶段,在开始运行该程序之前。

1.3    JavaScript“运行时错误”

JavaScript运行时错误是指当 JavaScript脚本试图执行一个系统不能运行的动作时导致的错误。当正在运行脚本、计算变量表达式、或者正在动态分配内存时出现 JavaScript运行时错误时。

2.    为什么要屏蔽javascript脚本错误?

由于开发海纳产品时,使用WebBrowser和CHtmlView来展示页面,进行填表等操作;但是由于打开的页面大多是其他用户的CMS页面,所以难免有些有脚本错误,于是决定要来屏蔽脚本错误,提升产品的易用性和友好性。

3.    怎么去屏蔽javascript脚本错误?

3.1    使用SetSilent函数

使用WebBrowser或CHtmlView的SetSilent函数可以达到屏蔽脚本错误的目的,不过这种情况,其它提示信息也都不显示了,例如使用alert进行的错误提示。

如果你觉得这样能满足你,那么推荐使用这种方法,简单啊!

3.2    重载IOleCommandTarget的Exec函数

网上比较多资料都是说重载IOleCommandTarget中的Exec函数来进行屏蔽脚本错,定义如下:

HRESULT  Exec( const GUID* pguidCmdGroup, DWORD nCmdID,

DWORD nCmdexecopt, VARIANTARG* pvaIn, VARIANTARG* pvaOut )

然后通过判断nCmdID是否等于OLECMDID_SHOWSCRIPTERROR(即报javascript脚本错误)来进行屏蔽;由于本人对COM和OLE的知识有限,琢磨了半天也没有想到怎么实现IOleCommandTarget接口中的Exec函数,然后跟我的WebBrowser或是HtmlView挂钩起来,于是决定放弃这种方法,有兴趣的朋友可以查看参考资料的文章继续尝试一下。

3.3    另一种方法

不死心,继续在网上找,突然发现了一篇文章,介绍在html页面中,可以使用javascript的事件来进行javascript脚本错误的屏蔽,于是拷贝下来尝试,果然有用(即使IE浏览器设置了脚本调试,也不会进行提示),经改造的代码如下:

1<html>
 2<head>
 3<script type="text/javascript" >
 4
 5function fnObjNotDefine(){
 6    domethod();
 7}
 8
 9function fnOnError(msg,url,lineno){
10    <!--
11    alert("window.onerror\n\n" +
12    "Error: " + msg + "\n" +
13    "URL:  " + url + "\n" +
14    "Line:  " + lineno);
15    return true; -->
16}
17window.onerror = fnOnError;
18MethodName.badcommand();
19
20function fnOnLoad(){
21    alert("on load!");
22}
23</script>
24</head>
25<body onload="fnOnLoad();">
26<input type="button" value="function not defined" onclick="badcommand();">
27<input type="button" value="object not defined" onclick="fnObjNotDefine();">
28</body>
29</html>
30

通过查看javascript代码,发现是“重载”了window.onerror这个事件,只要它返回true,脚本错误就不显示了,估计这个就是Microsoft自己实现的截取javascript脚本错误信息的接口

,于是就想怎么把它插入到页面当中,其中有篇文章介绍说在OnDocumentComplete时来实现javascript的插入,经实践,这种方法是不行的;经过本人的不断尝试,发现在OnNavigateComplete2或OnNavigateComplete里实现javascript的注入是可行的,这两个函数只要实现一个就行,就看你用的是Navigate2还是Navigate来打开页面了。这里使用Navigate2来做例子,具体代码如下:

1void CMyWebBrowser::OnNavigateComplete2(LPCTSTR strURL)
 2
 3{
 4
 5       CComPtr<IDispatch>   spDisp   =   GetHtmlDocument(); 
 6
 7       if(spDisp   !=   NULL) 
 8
 9       { 
10
11              CComPtr<IHTMLDocument2> doc;
12
13              spDisp->QueryInterface(IID_IHTMLDocument2, reinterpret_cast<void**>(&doc));
14
15              if(doc != NULL)
16
17              {   
18
19                     IHTMLWindow2 * pIhtmlwindow2 = NULL;
20
21                     doc->get_parentWindow(&pIhtmlwindow2);
22
23                     if(pIhtmlwindow2 != NULL)
24
25                     {
26
27                            //屏蔽javascript脚本错误的javascript脚本
28
29                            CString strJavaScriptCode = "function fnOnError(msg,url,lineno){alert('script error:\\n\\nURL:'+url+'\\n\\nMSG:'+msg +'\\n\\nLine:'+lineno);return true;}window.onerror=fnOnError;";
30
31                            BSTR bstrScript = strJavaScriptCode.AllocSysString();
32
33                            CString strLanguage("JavaScript");
34
35                            BSTR bstrLanguage = strLanguage.AllocSysString();
36
37                            long lTime = 1 * 1000;
38
39                            long lTimeID = 0;
40
41                            VARIANT varLanguage;
42
43                            varLanguage.vt = VT_BSTR;
44
45                            varLanguage.bstrVal = bstrLanguage;
46
47                            VARIANT pRet;
48
49                            //把window.onerror函数插入入当前页面中去
50
51                            pIhtmlwindow2->execScript(bstrScript, bstrLanguage, &pRet);
52
53                            ::SysFreeString(bstrScript);
54
55                            ::SysFreeString(bstrLanguage);
56
57 
58
59                            pIhtmlwindow2->Release();
60
61                     }
62
63              }
64
65       }
66
67}

其中,CMyWebBrowser是我自己继承了CHtmlView类的一个实现类, 这个函数可以在你的WebBrowser2或继承了CHtmlView类中实现,编写一个带有脚本错误的页面,打开进行浏览,是不是发现脚本错误被屏蔽了? 哈哈,实现起来也不麻烦。于是就把这个方法贴出来,供大家参考

另: 经测试,发现如果存在iframe嵌套的时候,嵌套的iframe中包含脚本错误,以上方法是不能屏蔽iframe中的脚本错误的,因为window.onerror只针对当前页面有效,因此需要在OnNavigateComplete2函数里加上对当前页面进行递归所有子页面,然后重复执行execScript操作即可。

最终代码为:

1void CMyWebBrowser::OnNavigateComplete2(LPCTSTR strURL)
  2
  3{
  4
  5       CComPtr<IDispatch>   spDisp   =   GetHtmlDocument(); 
  6
  7       if(spDisp   !=   NULL) 
  8
  9       { 
 10
 11              CComPtr<IHTMLDocument2> doc;
 12
 13              spDisp->QueryInterface(IID_IHTMLDocument2, reinterpret_cast<void**>(&doc));
 14
 15              if(doc != NULL)
 16
 17              {   
 18
 19                     CScriptErrHandler scriptHandler;
 20
 21                     scriptHandler.ShieldCurrPage(doc);
 22
 23                     scriptHandler.ShieldAllChildPages(doc);
 24
 25              }
 26
 27       }
 28
 29}
 30
 31ScriptErrHandler.cpp文件:
 32
 33#include "StdAfx.h"
 34
 35#include "ScriptErrHandler.h"
 36
 37CScriptErrHandler::CScriptErrHandler(void)
 38
 39{
 40
 41       CString strJavaScriptCode = "function fnOnError(msg,url,lineno){alert('script error:\\n\\nURL:'+url"
 42
 43              "+'\\n\\nMSG:'+msg +'\\n\\nLine:'+lineno+'\\n\\nframes:' + window.frames.length);return true;}window.onerror=fnOnError;";
 44
 45 
 46
 47       //屏蔽的脚本,可以改进为从文本里读取
 48
 49       m_bstrScript = strJavaScriptCode.AllocSysString();
 50
 51}
 52
 53 
 54
 55CScriptErrHandler::~CScriptErrHandler(void)
 56
 57{
 58
 59       SysFreeString(m_bstrScript);
 60
 61}
 62
 63 
 64
 65 
 66
 67void CScriptErrHandler::ShieldCurrPage(CComPtr<IHTMLDocument2> &doc)
 68
 69{
 70
 71       CComPtr<IHTMLWindow2>  spIhtmlwindow2;
 72
 73       doc->get_parentWindow(reinterpret_cast<IHTMLWindow2**>(&spIhtmlwindow2));
 74
 75       if(spIhtmlwindow2 != NULL)
 76
 77       {
 78
 79              CString strLanguage("JavaScript");
 80
 81              BSTR bstrLanguage = strLanguage.AllocSysString();
 82
 83              long lTime = 1 * 1000;
 84
 85              long lTimeID = 0;
 86
 87              VARIANT varLanguage;
 88
 89              varLanguage.vt = VT_BSTR;
 90
 91              varLanguage.bstrVal = bstrLanguage;
 92
 93              VARIANT pRet;
 94
 95              //把window.onerror函数插入入当前页面中去
 96
 97              spIhtmlwindow2->execScript(m_bstrScript, bstrLanguage, &pRet);
 98
 99              ::SysFreeString(bstrLanguage);
100
101       }
102
103}
104
105 
106
107void CScriptErrHandler::ShieldAllChildPages(CComPtr<IHTMLDocument2> &parentDoc)
108
109{
110
111       WalkAllChildPages(parentDoc);
112
113}
114
115 
116
117void CScriptErrHandler::WalkAllChildPages(CComPtr<IHTMLDocument2> &parentDoc)
118
119{
120
121       CComPtr<IHTMLFramesCollection2> spFramesCol;
122
123       HRESULT hr = parentDoc->get_frames(&spFramesCol);
124
125       if(SUCCEEDED(hr) && spFramesCol != NULL)
126
127       {
128
129              long lSize = 0;
130
131              hr = spFramesCol->get_length(&lSize);
132
133              if (SUCCEEDED(hr))
134
135              {
136
137                     for(int i=0; i<lSize; i++)
138
139                     {
140
141                            VARIANT frameRequested;
142
143                            VARIANT frameOut;
144
145                            frameRequested.vt = VT_UI4;
146
147                            frameRequested.lVal = i;
148
149                            hr = spFramesCol->item(&frameRequested, &frameOut);
150
151                            if(SUCCEEDED(hr) && frameOut.pdispVal != NULL)
152
153                            {
154
155                                   CComPtr<IHTMLWindow2> spChildWindow;
156
157                                  
158
159                                   hr = frameOut.pdispVal->QueryInterface(IID_IHTMLWindow2,reinterpret_cast<void**>(&spChildWindow));
160
161                                   if(SUCCEEDED(hr) && spChildWindow != NULL)
162
163                                   {
164
165                                          CComPtr<IHTMLDocument2> spChildDocument;
166
167                                          hr = spChildWindow->get_document(reinterpret_cast<IHTMLDocument2**>(&spChildDocument));
168
169                                          if(SUCCEEDED(hr) && spChildDocument != NULL)
170
171                                          {
172
173                                                 ShieldCurrPage(spChildDocument);
174
175                                                 WalkAllChildPages(spChildDocument);
176
177                                          }
178
179                                   }
180
181                                   frameOut.pdispVal->Release();
182
183                            }
184
185                     }
186
187              }
188
189       }
190
191}

目前存在的一个缺陷是OnNavigateComplete2会被调用多次,那么嵌入javascript的操作也会被执行多次(不知道会产生什么副作用,目前尚未发现);CMyWebBrowser从CHtmlView类继承,代码在VC2008和VC6.0下调试通过;若需要工程代码,请发送邮件到zhangqingping@hylanda.com 。

4.    参考资料

4.1   How to handle script errors as a WebBrowser control host

http://support.microsoft.com/default.aspx?scid=kb;en-us;261003

4.2   Script error notification is not sent to Exec method of WebBrowser Host

http://support.microsoft.com/kb/317024/en-us#top

4.3   How to Trap JScript Errors in Internet Explorer 4.01 and Earlier

http://support.microsoft.com/kb/183616/en-us

2011-12-08 13:35:02 Angela doudou

这个是成功代码 
void CZCSoftView::OnNavigateComplete2(LPCTSTR strURL) 

// TODO: Add your specialized code here and/or call the base class 
CComPtr<IDispatch> spDisp = GetHtmlDocument(); 
if(spDisp!=NULL) 

CComPtr<IHTMLDocument2> doc; 
spDisp->QueryInterface(IID_IHTMLDocument2, reinterpret_cast<void**>(&doc)); 
if(doc != NULL) 

IHTMLWindow2 * pIhtmlwindow2 = NULL; 
doc->get_parentWindow(&pIhtmlwindow2); 
if(pIhtmlwindow2 != NULL) 
{//"function fnOnError(msg,url,lineno){alert('script error:\\n\\nURL:'+url+'\\n\\nMSG:'+msg +'\\n\\nLine:'+lineno);return true;}window.onerror=fnOnError;"; 
//屏蔽javascript脚本错误的javascript脚本 
CString strJavaScriptCode = "function fnOnError(){return true;}window.onerror=fnOnError;"; 
BSTR bstrScript = strJavaScriptCode.AllocSysString(); 
CString strLanguage("JavaScript"); 
BSTR bstrLanguage = strLanguage.AllocSysString(); 
long lTime = 1 * 1000; 
long lTimeID = 0; 
VARIANT varLanguage; 
varLanguage.vt = VT_BSTR; 
varLanguage.bstrVal = bstrLanguage; 
VARIANT pRet; 
//把window.onerror函数插入入当前页面中去 
pIhtmlwindow2->execScript(bstrScript, bstrLanguage, &pRet); 
::SysFreeString(bstrScript); 
::SysFreeString(bstrLanguage); 
pIhtmlwindow2->Release(); 


}

CHtmlView::OnNavigateComplete2(strURL); 
}

 
 
2011-12-08 13:35:36 Angela doudou

禁止弹出窗口 给你的从CHtmlView派生而来的类加一个成员变量BOOL m_bPop; 
  在构造函数里给m_bPop初始化为:m_bPop = TRUE; 
  重载OnDownloadBegin虚函数,在其中加入:m_bPop = FALSE; 
  重载OnDownloadComplete虚函数,在其中加入:m_bPop = TRUE; 
  重载OnNewWindow2虚函数,在其中加入: 
  Cancel = m_bPop; 
禁止脚本错误 在初始化的时候设置 SetSilent(TRUE);

VC与JavaScript交互(四) --- WebBrowser或CHtmlView中轻松屏蔽脚本错误(JavaScript)的更多相关文章

  1. VB.NET让webbrowser控件中JS脚本错误最新方法(2013-09-16)

    最近也是在项目中遇到了webbrowser控件中想关闭JS脚本错误窗口的问题,所以经过多次测试,终于用一段高效实用的代码完美解决webbrowser控件中JS脚本错误窗口关闭的问题. 通过创建一个子线 ...

  2. VC与JavaScript交互(一) --- 如何实现

    为什么要让VC与JavaScript交互? 1.有时候我们需要让自己的软件打开一个网页,来获取页面上的一些数据.这时,可以用mshtml解析HTML提取出数据,也可以向HTML文档动态写入我们准备好的 ...

  3. VC与JavaScript交互(一) ———— 怎样实现

    为什么要让VC与JavaScript交互? 1.有时候我们须要让自己的软件打开一个网页.来获取页面上的一些数据. 这时,能够用mshtml解析HTML提取出数据.也能够向HTML文档动态写入我们准备好 ...

  4. VC与JavaScript交互(二) --- 调用JS函数

    这一章,我们来动手实践VC调用JS函数. 我们动手写一个HTML,其中包含这样一段JS代码: //[html] <script type="text/javascript"& ...

  5. Qt webKit可以做什么(四)--实现本地QObject和JavaScript交互

    Qt webKit可以做什么(四)--实现本地QObject和JavaScript交互 Qt webKit可以做什么(四)--实现本地QObject和JavaScript交互

  6. WPF加载HTML、WPF与JavaScript交互

    目录 一.WebBrowser加载远程网页 二.WebBrowser加载本地网页,注:不可以加载本地样式CSS和脚本JS文件 三.WebBrowser隐藏网页的JavaScript错误 四.网页屏蔽鼠 ...

  7. Hybrid App: 看看第三方WebViewJavascriptBridge是如何来实现Native和JavaScript交互

    一.简介 在前面两篇文章中已经介绍了Native与JavaScript交互的几种方式,依次是JavaScriptCore框架.UI组件UIWebView.WebKit框架,这几种方式都是苹果公司提供的 ...

  8. Android混合开发之WebView与Javascript交互

    前言: 最近公司的App为了加快开发效率选择了一部分功能采用H5开发,从目前市面的大部分App来讲,大致分成Native App.Web App.Hybrid App三种方式,个人觉得目前以Hybri ...

  9. 移动端基于HTML模板和JSON数据的JavaScript交互

    写本文之前,我正在做一个基于Tab页的订单中心: 每点击一个TAB标签,会请求对应状态的订单列表.之前的项目,我会在js里使用 +  连接符连接多个html内容: var html = ''; htm ...

随机推荐

  1. ExtJs4 SpringMvc3 实现Grid 分页

    新建一个Maven webapp项目,webxml以及spring配置没什么需要注意的,不再赘述. Maven依赖:(个人习惯,有用没用的都加上...) <project xmlns=" ...

  2. application in 2014

    OA WEBSITE ERP ISO ANDROID EF+MVC4+CATCHE+JQuery+js+div+css+web性能优化+webservice+sql2008+设计模式+wcf+多线程 ...

  3. ASP.NET MVC 基础(01)

    [ASP.NET MVC ]系列文章大致会包含这样一些内容: 1.ASP.NET MVC 的一些高级知识点: 2.ASP.NET MVC 的一些最新技术: 3.ASP.NET MVC 网站安全方面的知 ...

  4. spring学习笔记2(转)

    1.在Java开发领域,spring相对于EJB来说是一种轻量级的,非侵入性的Java开发框架,曾经有两本很畅销的书<Expert one-on-one J2EE Design and Deve ...

  5. IREP_SOA Integration SOAP概述(概念)

    20150827 Created By BaoXinjian

  6. poj 3048 Max Factor(素数筛)

    这题就是先写个素数筛,存到prime里,之后遍历就好,取余,看是否等于0,如果等于0就更新,感觉自己说的不明白,引用下别人的话吧: 素数打表,找出20000之前的所有素数,存入prime数组,对于每个 ...

  7. linux命令(5)文件操作:ls命令、显示文件总个数

    一:ls命令是最常用的linux命令了:下面是ls --help里面的用法 在提示符下输入ls --help ,屏幕会显示该命令的使用格式及参数信息: 先介绍一下ls命令的主要参数: -a 列出目录下 ...

  8. 论文他引次数及ESI高被引论文查询方法

    https://yunpan.cn/cS67Z9UEDvc2b 访问密码 f078

  9. UCOS-信号标志组(学习笔记)

    信号标志组即根据各任务的信号进行逻辑运算,根据逻辑运算的结果决定是否进行.发送方指定向那个标志组的哪一位(响应位等于1表明向哪一位发)发1还是0.等待逻辑结果的任务指定等待那个标志组的哪几位.这几位按 ...

  10. mongodb 查询使用

    > db.jd_58tc_raw.findOne() { "_id" : "2659e4e4caf0504ec4362478e2ed57ca", &quo ...