When one of the script engines encounters an unhandled error, it forwards the error to the WebBrowser control, which then queries its container to see if the container has implemented
IOleCommandTarget. If the container has implemented
IOleCommandTarget, the WebBrowser control calls the
IOleCommandTarget::Exec method with the command group ID of
CGID_DocHostCommandHandler (which is defined in the Mshtmhst.h file) and a command ID of
OLECMDID_SHOWSCRIPTERROR. If the host does not return
S_OK, MSHTML displays the default "An error has occurred on this page" error message.
The following code illustrates how to implement a handler for this command ID that retrieves the error information from the document object model. This code does not illustrate error handling.
NOTE: This method will not be invoked if the user has cleared the
Disable Script Debugging check box in the
Advanced tab under
Internet Options.
STDMETHODIMP CMyBrowser::Exec( const GUID* pguidCmdGroup, DWORD nCmdID,
DWORD nCmdexecopt, VARIANTARG* pvaIn, VARIANTARG* pvaOut )
{
HRESULT hr = S_OK;
if (pguidCmdGroup && IsEqualGUID(*pguidCmdGroup, CGID_DocHostCommandHandler))
{
switch (nCmdID)
{
case OLECMDID_SHOWSCRIPTERROR:
{
IHTMLDocument2* pDoc = NULL;
IHTMLWindow2* pWindow = NULL;
IHTMLEventObj* pEventObj = NULL;
BSTR rgwszNames[5] =
{
SysAllocString(L"errorLine"),
SysAllocString(L"errorCharacter"),
SysAllocString(L"errorCode"),
SysAllocString(L"errorMessage"),
SysAllocString(L"errorUrl")
};
DISPID rgDispIDs[5];
VARIANT rgvaEventInfo[5];
DISPPARAMS params;
BOOL fContinueRunningScripts = true;
int i;
params.cArgs = 0;
params.cNamedArgs = 0;
// Get the document that is currently being viewed.
hr = pvaIn->punkVal->QueryInterface(IID_IHTMLDocument2, (void **) &pDoc);
// Get document.parentWindow.
hr = pDoc->get_parentWindow(&pWindow);
pDoc->Release();
// Get the window.event object.
hr = pWindow->get_event(&pEventObj);
// Get the error info from the window.event object.
for (i = 0; i < 5; i++)
{
// Get the property's dispID.
hr = pEventObj->GetIDsOfNames(IID_NULL, &rgwszNames[i], 1,
LOCALE_SYSTEM_DEFAULT, &rgDispIDs[i]);
// Get the value of the property.
hr = pEventObj->Invoke(rgDispIDs[i], IID_NULL,
LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYGET, ¶ms, &rgvaEventInfo[i],
NULL, NULL);
SysFreeString(rgwszNames[i]);
}
// At this point, you would normally alert the user with
// the information about the error, which is now contained
// in rgvaEventInfo[]. Or, you could just exit silently.
(*pvaOut).vt = VT_BOOL;
if (fContinueRunningScripts)
{
// Continue running scripts on the page.
(*pvaOut).boolVal = VARIANT_TRUE;
}
else
{
// Stop running scripts on the page.
(*pvaOut).boolVal = VARIANT_FALSE;
}
break;
}
default:
hr = OLECMDERR_E_NOTSUPPORTED;
break;
}
}
else
{
hr = OLECMDERR_E_UNKNOWNGROUP;
}
return (hr);
}