0

I'm implementing the Exec method of TWebBrowser based on this answer. This method is triggered whenever a script error occurs. Now I need to get error information.

I first get hold of the event object of the 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;

And then I'm trying to get the information I need (as demonstrated in this link) using GetIDsOfNames and Invoke functions of the interface. A working Delphi code for using these methods are in this documentation link.

Here is how I use these functions on the Event object.

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);

The GetIDsOfNames fuGetIDsOfNames function executes properly, outputs an acceptable integer to DispatchId and returns S_OK.

But the Invoke function just fails. It returns some negative integer as HRESULT and doesn't output anything to MethodResult.

How can I work around this?

Community
  • 1
  • 1
Charlie
  • 22,886
  • 11
  • 59
  • 90

1 Answers1

2

The error values you are trying to access are not object methods, they are properties, so Invoke() is going to fail due to your use of DISPATCH_METHOD. Use DISPATCH_PROPERTYGET instead.

However, OleVariant (and Variant) has built-in support for IDispatch.Invoke(), so you don't need to mess with it manually at all. You can call object methods and read/write object properties normally, and the compiler will produce the necessary IDispatch calls for you.

Try something more like this:

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;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770