n_vcplus 0 Newbie Poster

Hello All,

I've been through this article and found it very helpful {http://msdn.microsoft.com/en-us/library/bb250489(VS.85).aspx}. I have a 'static' callback method in my BHO dll which is called whenever 'some' event on the computer happens. I need to call a javascript method on all open browser instances when that happens (or do nothing if no such javascript method exists on the page).

I need to access all BHO objects from that static method to call the javascript method on the page. My approach has been to store all IWebBrowser2 pointer variables from every BHO in a global vector (STL). In my static method i access the global vector, enumerate through all the IWebBrowser2 pointers. Then, while trying to access the IHTMLWindow object my IE throws a runtime error at the red line.

...
For every IWebBrowser2 object in the vector = m_spWebBrowser
HRESULT hr = S_OK;
CComPtr<IDispatch> spDispDoc;
hr = m_spWebBrowser->get_Document(&spDispDoc);
if (SUCCEEDED(hr)) {
	CComQIPtr<IHTMLDocument2> spHTMLDoc = spDispDoc;
	if (spHTMLDoc != NULL) {
		CComPtr<IHTMLWindow2> HTML2Wind;
		hr = spHTMLDoc->get_parentWindow(&HTML2Wind);
		if ( hr == S_OK ) {
			static const CComBSTR funcStr(L"method('param');");
			static const CComBSTR langStr(L"JavaScript");
			VARIANT vEmpty = {0};
			CComPtr<IHTMLWindow2> HTML2Wind;
			hr = spHTMLDoc->get_parentWindow(&HTML2Wind);
			if ( hr == S_OK ) {
				hr = HTML2Wind->execScript(funcStr, langStr, &vEmpty);
				if ( hr == S_OK ) {
				}
			}
		}
	}
}
...

This approach doesn't seem to work. Any comments on a better approach to achieve this or a potential fix?

I can post any specific part of code if explanation is not clear.

~Thanks

Dani AI

Generated

Likely cause: the static callback runs on a different thread than the IE/BHO UI apartment, and the raw COM pointers in your global vector were not marshaled. Apartment-threaded COM objects (IWebBrowser2 / MSHTML interfaces) must either be used from the thread that created them or properly marshaled to the caller thread. Dereferencing them from the wrong thread commonly causes the kind of runtime crash you describe.

Two practical fixes that work reliably:

  • Dispatch to the browser/UI thread (recommended). Have each BHO instance create or expose an HWND (a small hidden window is common). Store those HWNDs in a thread-safe container. When your static callback fires, PostMessage a custom message to each HWND. The BHO instance’s window proc runs on the correct thread and can safely call into the DOM and execute script (and can check for the JS function’s existence before calling). This avoids COM marshaling and reentrancy/message-pump pitfalls.

  • Marshal the COM pointer to the callback thread (when you must run there). On the UI thread call CoMarshalInterThreadInterfaceInStream for the IWebBrowser2 (store the IStream*). In the callback thread call CoInitializeEx, then CoGetInterfaceAndReleaseStream to obtain a thread-appropriate proxy before calling methods. Release the proxy and call CoUninitialize when done.

Example sketch for marshaling/unmarshaling:

// UI thread: marshal and store the stream
IStream* pStream = nullptr;
CoMarshalInterThreadInterfaceInStream(IID_IWebBrowser2, spWebBrowser, &pStream);
// store pStream in a thread-safe container

// Callback thread:
CoInitializeEx(NULL, COINIT_MULTITHREADED);
IWebBrowser2* pWeb = nullptr;
CoGetInterfaceAndReleaseStream(pStreamFromContainer, IID_IWebBrowser2, (void**)&pWeb);
if (pWeb) {
    // use pWeb (or better: post to UI thread to run execScript)
    pWeb->Release();
}
CoUninitialize();

Cautions: always CoInitializeEx/CoUninitialize in the calling thread, release streams and interfaces, avoid holding raw interface pointers across threads, and prefer posting to the UI thread if execScript must run synchronously in page context. See Microsoft documentation on COM apartments and marshaling for details: and CoMarshalInterThreadInterfaceInStream / CoGetInterfaceAndReleaseStream.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.