Microsoft KB Archive/317024

From BetaArchive Wiki

Article ID: 317024

Article Last Modified on 1/3/2005



APPLIES TO

  • Microsoft Internet Explorer 5.5
  • Microsoft Internet Explorer (Programming) 6.0



This article was previously published under Q317024

SYMPTOMS

When you write a WebBrowser control host in Visual C++, you may use the information in the following Microsoft Knowledge Base article to generate notification of script errors:

261003 How to handle script errors as a WebBrowser control host


However, this notification may be inconsistent: In both Internet Explorer 5.5 and Internet Explorer 6.0, the host may receive the notification on certain installations but not on others. Or, on Microsoft Windows platforms with Internet Explorer 5.5 installed, you may not receive the first notification, yet all subsequent notifications properly trigger the call to the Exec method.

CAUSE

This behavior is by design in Internet Explorer 6.0. The OLECMDID_SHOWSCRIPTERROR command ID does not fire if the Disable Script Debugging check box is cleared (on the Tools menu, click Internet Options, and then click Advanced). The behavior is a bug in Internet Explorer 5.5 that was resolved in Internet Explorer 6.0.

For additional information about this issue, click the following article number to view the article in the Microsoft Knowledge Base:

263100 OL2000: Hyperlink does not open a new instance of your Internet browser


RESOLUTION

Although you can programmatically configure the registry setting behind the Disable Script Debugging check box, this affects the behavior of Internet Explorer and all other WebBrowser hosts on the computer, not just your WebBrowser host. Fortunately, you can guarantee that the OLECMDID_SHOWSCRIPTERROR message fires on every computer, regardless of configuration, by injecting a script-based onerror event handler into the current document. This can be done from your host's DWebBrowser2::DocumentComplete() event handler.

For additional information about how to sink events in both Microsoft Foundation Classes (MFC) and the Active Template Library (ATL), click the following article number to view the article in the Microsoft Knowledge Base:

247073 CustWBC.exe: ATL HTML control customizes the WebBrowser control


For a sample application that demonstrates how to sink events for Internet Explorer from an MFC application, visit the following MSDN Web site:

The following sample code was written for an MFC dialog box application; the body can be cut and pasted, along with the macros, into either an ATL or MFC host:

#define CHECK_HR(hr,label) \ 
if(FAILED(hr)) \ 
{   goto label; \ 
}

#define RRELEASE(ptr) \ 
if(ptr) \ 
{   ptr->Release(); \ 
    ptr = NULL; \ 
}

// Get the DOM associated with the WebBrowser that threw this event, and
// inject an onerror tag into the page in hopes of receiving an 
// OLECMDID_SHOWSCRIPTERROR message. (This is a bug in Internet Explorer 6.)
// NOTE: pBrowser is the IWebBrowser2 for the FRAME, IFRAME, or primary 
// that just finished loading our document. If you have a FRAMESET with 
// three FRAMEs, you will see this handler called four times: once for 
// each FRAME and once for the FRAMESET after all FRAMEs have loaded. 
// We're sinking each individual FRAME in this sample; to sink only the 
// topmost FRAME, test the IUnknown of our m_pBrowser against the IUnknown 
// of this method's pBrowser, and sink only when these two are equal. 
void CSimpleBrowserDlg::OnDocumentComplete(LPDISPATCH pBrowser, LPVARIANT url) 
{
    IWebBrowser2 *thisBrowser       = NULL;
    IDispatch *docDisp          = NULL;
    IHTMLDocument3 *doc     = NULL;
    IHTMLElement *elem          = NULL;
    HRESULT hr = S_OK;

    hr = pBrowser->QueryInterface(IID_IWebBrowser2, reinterpret_cast<void **>(&thisBrowser));
    CHECK_HR(hr, cleanup);
    hr = thisBrowser->get_Document(&docDisp);
    CHECK_HR(hr, cleanup);
    hr = docDisp->QueryInterface(IID_IHTMLDocument3, reinterpret_cast<void**>(&doc));
    CHECK_HR(hr, cleanup);
    RRELEASE(docDisp);

    // Get the documentElement for the document object, and then call 
    // IHTMLElement::insertAdjacentHTML() to add the onerror SCRIPT 
    // handler tag.
    hr = doc->get_documentElement(&elem);
    CHECK_HR(hr, cleanup);
    // NOTE: The &nbsp, or some other visible HTML, is required. Internet Explorer will not
    // parse and recognize the script block without some visual HTML to
    // accompany it.
    hr = elem->insertAdjacentHTML(L"afterBegin", L" <SCRIPT For='window' Event='onerror'>var noOp = null;</SCRIPT>");

    // Cleanup.
cleanup:
    RRELEASE(elem);
    RRELEASE(thisBrowser);
    RRELEASE(doc);
}
                

STATUS

This behavior is by design.

MORE INFORMATION

Steps to reproduce the problem

  1. Create a WebBrowser control host in either an ATL or MFC application.
  2. Use Knowledge Base article Q263100 (linked in the "Cause" section of this article) to implement the IOleCommandTarget interface on your host. MFC users may also want to consult the following Knowledge Base article for tips:

    141277 How to override an interface in an MFC application

  3. Place a breakpoint inside the portion of your Exec method that catches the OLECMDID_SHOWSCRIPTERROR command ID.
  4. Save the following HTML file to the root of your local host Web server as testError.htm:

    <HTML>
    
    <SCRIPT>
    
    function load() {
        /// obj1 is undefined, so this will produce a scripting error.
        obj1.callMethod();
    }
    
    </SCRIPT>
    
    <BODY onload="load();">
    
    
    
    </BODY>
    
    </HTML>
                        
  5. If you have not done so earlier, start Internet Explorer, click Internet Options on the Tools menu, click Advanced, and then click to clear the Disable Script Debugging check box in the Browsing category.
  6. Start your WebBrowser host, and then navigate to the following Web site: Note that the block of code in your Exec implementation that responds to OLECMDID_SHOWSCRIPTERROR is never executed.


Keywords: kbnofix kbprb KB317024