ShellExecute doesn't work for URLs when called from a multithreaded apartment

27 Feb 2007 12:14

I’ve got a dialog box with a SysLink (WC_SYSLINK) control on it. When the user clicks on the link, it should open our website in the user’s default browser. In my test app, it works. In the production app, it doesn’t.

It turns out that the production app calls CoInitialize(NULL, COINIT_MULTITHREADED), and the test app doesn’t.

ShellExecute doesn’t work from multithreaded apartments. At least, not on Windows XP or 2003. The same code appears to work fine on Vista.

See the following:

If you’ve not already initialized COM, then it works fine. If you call CoInitialize(NULL), then it works fine. It’s only multithreaded apartments that don’t work. Paul DiLascia’s article (the first link above) has the following workaround if you don’t care about the result code:

LPCTSTR url = _T("www.microsoft.com");
CString args;
args.Format(_T("url.dll,FileProtocolHandler %s"), url);
ShellExecute(NULL, _T("open"), _T("rundll32.exe"), args);