EmbeddedWb不能完全屏蔽脚本错误的修改

  EmbeddedWb的版本有点看不懂。。。。。。

 EmbeddedWb v14是可以完全屏蔽脚本错误,但问题多多,在多人使用环境下错误多多。



不得已用v13,稳定,但脚本错误经常跳出来。



  找了很多地方,也改了不少属性,失败。

  看到这篇,是好方法:

  http://www.winu.cn/space-14160-do-blog-id-14070.html###





-----------------------------------------------------------------------------

    EmbeddedWb(ver 1.16b)的一个BUG



按照文档,当有脚本错误产生时EmbeddedWb会触发OnScriptError事件. 这个问题好模拟,顺便建个文本文件,改名.html,然后输入:
<script language="JavaScript">
  alert("Hello!")111;
</script>
最后用EmbeddedWb来访问这个HTML,就可以在它的OnScriptError中抓到这个事件.

这是最一般的情况.如果我们把这个HTML作为一个帧(Frame)给其它的HTML用,然后让EmbeddedWb访问那个HTML,这时候就抓不到错误了,只能由IE的来弹出错误对话框.

我开始不知道问题出在哪,不停地去盯EmbeddedWb的那些属性,看有没有相关的东西.最后找到眼睛痛也没结果.

后来跟踪了OnScriptError里边的代码才总算知道原因在哪了:
  case nCmdID of
  OLECMDID_SHOWSCRIPTERROR:
  if Assigned(FOnScriptError)
  then begin
  pEventObj := (Document as IHTMLDocument2).parentWindow.event;
  if pEventObj <> nil then
  begin
  ...
这段代码在EmbeddedWb.pas大概2000行的位置.我的已经改过所以只好说"大概".
当错误的脚本在Frame中时,pEventObj得到的总是nil,所以程序根本没跑下去就出去了.

这显然是EmbeddedWb的一个BUG,哈哈

我当时以为Document就是产生错误的那个HTML,并且以为parentWindow.event里的event应该是最顶层的window里的event,所以用了parentWindow.top.event来取值,结果没取到.
接下来以为这个top有问题,改用循环,也就是
  htmlWin2 := (Document as IHTMLDocument2).parentWindow;
  while htmlWin2.parent <> htmlWin2 do
  htmlWin2 := htmlWin2.parent;
  pEventObj := htmlWin2.event;
来取值,还是没有取到.

:(

后来把document的内容显示出来,发现这个document就是最顶层的那个:
  Dialogs.ShowMessage((Document as IHTMLDocument2).body.innerHTML);

这样思路就清晰了,只要从这个document开始找它的event,如果找不到就看它有没有Frame,遍历每个Frame,包括Frame下面的Frame,这样最终就能够把产生脚本错误的那个Document找出来.

用一个递归来实现上面的思路:
  function GetEventObj(htmlDoc2: IHTMLDocument2; EventType: WideString): IHTMLEventObj;
  var
  i: Integer;
  OleIndex: OleVariant;
  frameDispatch: IDispatch;
  pEvent: IHTMLEventObj;
  begin
  Result := nil;
  //先判断它自己有没有事件发生
  pEvent := htmlDoc2.parentWindow.event;
  if pEvent <> nil then
  if pEvent.type_ = EventType then
  begin
  Result := pEvent;
  Exit;
  end;
  //如果没有,就找它的帧
  for i := 0 to htmlDoc2.Frames.Length - 1 do
  begin
  OleIndex := i;
  frameDispatch := htmlDoc2.Frames.Item(OleIndex);
  if Assigned(frameDispatch) then
  begin
  pEvent := GetEventObj((frameDispatch as IHTMLWindow2).document, EventType);
  if pEvent <> nil then
  begin
  Result := pEvent;
  Break;
  end;
  end;
  end;
  end;

最后改一下调用:
  case nCmdID of
  OLECMDID_SHOWSCRIPTERROR:
  if Assigned(FOnScriptError)
  then begin
  //pEventObj := (Document as IHTMLDocument2).parentWindow.event;
  pEventObj := GetEventObj(Document as IHTMLDocument2, 'error');
  if pEventObj <> nil then
  begin
  ...

问题终于解决. 嘿嘿...



-----------------------------------------------------------------------------





问题是,我按文中所写加入GetEventObj,运行,竟然出现“拒绝访问”,
按说是跨域问题,但我的应用不是跨域。

反复试验不得解决。


后来想,是因为pEventObj=nil才不会触发事件,那我自已处理它就
可以了。所以,按下面改了一下,可以了!

原文:


  pEventObj := (Document as IHTMLDocument2).parentWindow.event;
   
  if pEventObj <> nil then
  begin
  FContinueScript := True;
  FShowDialog := False;
  FOnScriptError(self,
  GetProperty('errorline'),
  GetProperty('errorCharacter'),
  GetProperty('errorCode'),
  GetProperty('errorMessage'),
  GetProperty('errorUrl'),
  FContinueScript, FShowDialog);
  TVariantArg(vaOut).vt := VT_BOOL;
  TVariantArg(vaOut).vbool := FContinueScript;
  if not FShowDialog then Result := S_OK;
  end ;


改后:


  pEventObj := (Document as IHTMLDocument2).parentWindow.event;
   
  if pEventObj <> nil then
  begin
  FContinueScript := True;
  FShowDialog := False;
  FOnScriptError(self,
  GetProperty('errorline'),
  GetProperty('errorCharacter'),
  GetProperty('errorCode'),
  GetProperty('errorMessage'),
  GetProperty('errorUrl'),
  FContinueScript, FShowDialog);
  TVariantArg(vaOut).vt := VT_BOOL;
  TVariantArg(vaOut).vbool := FContinueScript;
  if not FShowDialog then Result := S_OK;
  end else
  begin

  FContinueScript := True;
  FShowDialog := False;
  FOnScriptError(self,
  '',
  '',
  '',
  '未知的错误(我的:))',
  self.LocationURL,
  FContinueScript, FShowDialog);
  TVariantArg(vaOut).vt := VT_BOOL;
  TVariantArg(vaOut).vbool := FContinueScript;
  if not FShowDialog then Result := S_OK;
  end;


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值