如何获取TWebBrowser错误信息

How to get TWebBrowser error information

我正在根据 this 答案实现 TWebBrowser 的 Exec 方法。只要发生脚本错误,就会触发此方法。现在我需要获取错误信息。

我先拿到了TWebBrowser的事件对象

var
 Doc: IHTMLDocument2;
 HTMLWindow: IHTMLWindow2;
 Event: IHTMLEventObj;
 MethodName: String;
 MethodResult: OleVariant;
 DispatchId: Integer;
 Param: array of OleVariant;

begin

//Avoid non-error calls
if nCmdID != OLECMDID_SHOWSCRIPTERROR then 
   Exit;

//Get hold of the event object
Doc := MapForm.WebBrowser.Document as IHTMLDocument2;
if not Assigned(Doc) then
  Exit;


HTMLWindow := Doc.parentWindow;
if not Assigned(HTMLWindow) then
  Exit;


//Get the current event
Event := HTMLWindow.event;

然后我尝试获取我需要的信息(如 this link) using GetIDsOfNames and Invoke functions of the interface. A working Delphi code for using these methods are in this 文档 link 中所示。

以下是我如何在 Event 对象上使用这些函数。

MethodName := 'errorMessage';
Result := Event.GetIDsOfNames(GUID_NULL, @MethodName, 1,     SysLocale.DefaultLCID, @DispatchId);

Result := Event.Invoke(DispatchId, GUID_NULL, SysLocale.DefaultLCID, DISPATCH_METHOD, Param, @MethodResult, nil, nil);

GetIDsOfNames fuGetIDsOfNames 函数正确执行,输出一个可接受的整数给DispatchId和returns S_OK.

但是 Invoke 功能失败了。它 returns 一些负整数作为 HRESULT 并且不输出任何东西到 MethodResult.

我该如何解决这个问题?

您尝试访问的错误值不是对象方法,它们是属性,因此 Invoke() 将因您使用 DISPATCH_METHOD 而失败。请改用 DISPATCH_PROPERTYGET

然而,OleVariant(和 Variant)内置了对 IDispatch.Invoke() 的支持,因此您根本不需要手动操作它。您可以正常调用对象方法和 read/write 对象属性,编译器将为您生成必要的 IDispatch 调用。

试试像这样的东西:

function TWebBrowser.Exec(CmdGroup: PGUID; nCmdID, nCmdexecopt: DWORD; 
  const vaIn: OleVariant; var vaOut: OleVariant): HRESULT; stdcall;
var
  Event: OleVariant;
  ErrorLine: Integer;
  ErrorChar: Char;
  ErrorCode: Integer;
  ErrorMsg: String;
  ErrorUrl: String;
begin
  if (CmdGroup = nil) or not IsEqualGUID(CmdGroup^, CGID_DocHostCommandHandler) then
  begin
    Result := OLECMDERR_E_UNKNOWNGROUP;
    Exit;
  end;

  if nCmdID <> OLECMDID_SHOWSCRIPTERROR then
  begin
    Result := OLECMDERR_E_NOTSUPPORTED;
    Exit;
  end;

  Event := (IUnknown(vaIn) as IHTMLDocument2).parentWindow.event;

  ErrorLine := Event.errorLine;
  ErrorChar := Event.errorCharacter;
  ErrorCode := Event.errorCode;
  ErrorMsg := Event.errorMessage;
  ErrorUrl := Event.errorUrl;

  ...

  if (should continue running scripts) then
  begin
    vaOut := True;
  end else
  begin
    vaOut := False;
  end;

  Result := S_OK;
end;