【问题标题】:TWebBrowser crashes with embedded Youtube clipsTWebBrowser 与嵌入的 Youtube 剪辑一起崩溃
【发布时间】:2012-01-02 06:56:11
【问题描述】:

这是我的代码:

type
  TForm1 = class(TForm)
    WebBrowser1: TWebBrowser;
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  end;

implementation
uses ActiveX;

procedure TForm1.Button1Click(Sender: TObject); // method 1
var
  HtmlFile: string;
begin
  HtmlFile := ExtractFilePath(Application.ExeName) + 'test.html';
  WebBrowser1.Navigate(HtmlFile);
end;

procedure LoadHtml(wb: TWebBrowser; HTMLStr: string);
var
  aStream: TMemoryStream;
begin
  wb.Navigate('about:blank'); // reset the webbrowser
  while wb.ReadyState < READYSTATE_INTERACTIVE do // wait to load the empty page
    Application.ProcessMessages;
  if Assigned(wb.Document) then
  begin
    aStream := TMemoryStream.Create;
    try
      aStream.WriteBuffer(Pointer(HTMLStr)^, Length(HTMLStr));
      aStream.Seek(0, soFromBeginning);
      (wb.Document as IPersistStreamInit).Load(TStreamAdapter.Create(aStream));
    finally
      aStream.Free;
    end;
  end;
end;

procedure TForm1.Button2Click(Sender: TObject); // method 2
begin
  LoadHtml(WebBrowser1,
    '<html><head></head><body>'+
    '  <object width="640" height="390"> '+
    '  <param name="movie" value="http://www.youtube.com/v/L7NWdxFAHdY&hl=en_US&feature=player_embedded&version=3"> '+
    '  </param><param name="allowFullScreen" value="true"> '+
    '  </param><param name="allowScriptAccess" value="always"> '+
    '  </param><embed src="http://www.youtube.com/v/L7NWdxFAHdY&hl=en_US&feature=player_embedded&version=3" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="640" height="390"> '+
    '  </embed></object> '+
    '</body></html>'
    );
end;

test.html

<object width="425" height="349">
<param name="movie" value="http://www.youtube.com/v/1hPxGmTGarM?version=3&amp;hl=iw_IL">
</param><param name="allowFullScreen" value="true"></param>
<param name="allowscriptaccess" value="always"></param>
<embed src="http://www.youtube.com/v/1hPxGmTGarM?version=3&amp;hl=iw_IL" type="application/x-shockwave-flash" width="425" height="349" allowscriptaccess="always" allowfullscreen="true">
</embed></object>

我的应用程序在这两种方法中都崩溃了。我得到一个未处理的 win32 异常(由 Flash 播放器Exception EInvalidOp in module Flash10u.ocx at 00108657. Invalid floating point operation 引起)。

  • 我在 D5、D7、D9 上试过这个代码。
  • 我尝试重新导入 SHDocVw.dll。
  • 我还尝试使用 EmbeddedWB 控件而不是 TWebBroser...
  • Internet Explorer/Avant/Maxthon 对此 HTML 没有任何问题(全部基于 IE ActiveX)。

有什么建议或解决办法吗?

我怎样才能捕捉到这个错误,甚至抑制它?

有没有办法通过 TWebBrowser 事件即时操作或更改 HTML,以便我可以显示图像而不是 Flash 播放器,就像 Ad-Blockers 的工作原理一样? (我的客户通过 Internet 在他们的站点中拥有该代码,我的 Delphi 应用程序提供了快速预览)

更新

我使用 TTimer 来启用/禁用 FPU(基于 Arjen 的想法):

function Get8087CW: Word; // for D5
asm
        PUSH    0
        FNSTCW  [ESP].Word
        POP     EAX
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Timer1.Enabled := False;
  Timer1.Interval := 5000; // 5 sec
  Saved8087CW := Get8087CW;
end;

procedure TForm1.WebBrowser1BeforeNavigate2(Sender: TObject;
  const pDisp: IDispatch; var URL, Flags, TargetFrameName, PostData,
  Headers: OleVariant; var Cancel: WordBool);
begin
  Timer1.Enabled := False;
  System.Set8087CW($133F); // Disable all fpu exceptions
end;

procedure TForm1.WebBrowser1DocumentComplete(Sender: TObject;
  const pDisp: IDispatch; var URL: OleVariant);
begin
   Timer1.Enabled := True;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Timer1.Enabled := False;
  Set8087CW(Saved8087CW);
end;

更新 (2)

我最终在应用程序启动时屏蔽了 FPU 异常。从那以后,对我的申请没有(已知的)影响。

【问题讨论】:

  • 如果您提供有关异常的更多信息,它会。确切的消息、代码和行。
  • Exception EInvalidOp in module Flash10u.ocx at 00108657. Invalid floating point operation.我也更新到最新的flash player了。
  • @kobik,您是否尝试过 &lt;iframe&gt; 的嵌入代码?
  • @TLama,是的,我做到了,结果相同。实际上,我无法控制我的客户使用什么代码。他们嵌入 iframe(这是他们默认从 youtube 获取的代码),还嵌入了 YouTube 旧代码。
  • @kobik,我已经在 Windows XP、IE7 和 Flash Player 11.1.102.55(当前版本)上使用 D2009 尝试过你的代码,它工作正常。在我看来,这里提供的解决方案只是抑制真正问题的解决方法(恕我直言,您只需要更新 Flash Player;TWebBrowser 使用的 IWebBrowser2 接口从 Internet Explorer 4.0 开始就在这里)。但我建议你以某种方式处理错误,而不是压制它们。

标签: delphi webbrowser-control delphi-5 twebbrowser flashplayer-10


【解决方案1】:

尝试使用 Set8087CW(0x133f) 暂时禁用 FPU 异常; info

【讨论】:

  • 这个方法确实有效。在启动时为我的整个应用程序关闭 FPU 异常有多安全?看来我无法暂时禁用它,因为OnDownloadComplete 在加载剪辑之前触发。 ://
  • 它会影响应用程序其余部分中的舍入模式、精度和浮点异常。如果这不是问题,请为您的整个应用程序关闭它
  • 因为我不知道 8087 FPU 控制器会对我的应用程序产生什么影响(我的应用程序使用了大量的算术计算等),所以我在全球范围内使用它还不舒服。我读到的其他线程也建议我们在完成我们的应用程序时需要使用ClearPending8087Exceptions (Jcl8087)。我将对此进行更多调查......
  • OnDownloadComplete 触发多次!使用 OnBeforeNavigate2(开始)和 OnDocumentComplete(结束)设置和重置 8087CW。
  • 我非常确信 FPU 异常是问题所在。我不知道您的应用程序的线程安排是什么,但我想知道 Web 浏览器是否可以放在一个单独的线程中,这样您就可以将 FPU CW 更改隔离到该线程。
【解决方案2】:

更漂亮的解决方案:

Math.SetExceptionMask([exInvalidOp, exDenormalized, exZeroDivide, exOverflow,
  exUnderflow, exPrecision]);

如果我正确阅读了文档,Math.SetExceptionMask 会在提到的每个 exception 中保持沉默。

但是,它只是@Arjen 方法的更清洁、更漂亮的版本。

【讨论】:

  • 我在我的应用程序中使用 D5,所以 Math.SetExceptionMask 在 D5 中不可用。我检查了 D9 来源,该功能基本上是这样做的:Set8087CW((Get8087CW and $FFC0) or $3F)。让我有点烦恼的是,Get8087CW 返回 1372 美元而不是 1332 美元。导致 FPU 字为 $137F(或者我只是太迂腐了:/)
  • @kobik $1332 vs $1372 只是保留了一些 CW 位的事实。不用担心。
  • @kobik 我认为这是“为了避免在更改 FPU 操作模式时引发异常”参见Intel's doc,第“Vol. 2A 3-385”页
  • 现在在 2019 年这个解决方案更可取,因为它适用于 32 位和 64 位程序。虽然 @ArjenvanderSpek 仅适用于 32 位模式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-16
  • 2011-03-28
相关资源
最近更新 更多