Question

For years I've been using ShellExecute() API to launch the default web browser from within my applications. Like this:

ShellExecute( hwnd, _T("open"), 
    _T("http://www.winability.com/home/"), 
    NULL, NULL, SW_NORMAL );

It's been working fine until a couple of weeks ago, when Google released its Chrome browser. Now, if Chrome is installed on the computer, the ShellExecute API no longer opens a web page.

Has anyone figured out yet how to solve this problem? (Short of detecting Chrome and displaying a message telling the user it's Chrome's fault?)

EDIT: the code provided by Sergey seems to work, so I've accepted it as "the" answer. Except that I don't like the call to WinExec: MSDN reads that WinExec is provided only for compatibility with 16-bit applications. IOW, it may stop working with any Service Pack. I did not try it, but I would not be surprised if it has already stopped working with Windows x64, since it does not support 16-bit applications at all. So, instead of WinExec, I'm going to use ShellExecute, with the path taken from the registry like Sergey's code does, and the URL as the argument. Thanks!

Was it helpful?

Solution

Here is the code that works across all browsers. The trick is to call WinExec if ShellExecute fails.

HINSTANCE GotoURL(LPCTSTR url, int showcmd)
{
    TCHAR key[MAX_PATH + MAX_PATH];

    // First try ShellExecute()
    HINSTANCE result = 0;

    CString strURL = url;

    if ( strURL.Find(".htm") <0 && strURL.Find("http") <0 )
        result = ShellExecute(NULL, _T("open"), url, NULL, NULL, showcmd);

    // If it failed, get the .htm regkey and lookup the program
    if ((UINT)result <= HINSTANCE_ERROR) {

        if (GetRegKey(HKEY_CLASSES_ROOT, _T(".htm"), key) == ERROR_SUCCESS) {
            lstrcat(key, _T("\\shell\\open\\command"));

            if (GetRegKey(HKEY_CLASSES_ROOT,key,key) == ERROR_SUCCESS) {
                TCHAR *pos;
                pos = _tcsstr(key, _T("\"%1\""));
                if (pos == NULL) {                     // No quotes found
                    pos = strstr(key, _T("%1"));       // Check for %1, without quotes
                    if (pos == NULL)                   // No parameter at all...
                        pos = key+lstrlen(key)-1;
                    else
                        *pos = '\0';                   // Remove the parameter
                }
                else
                    *pos = '\0';                       // Remove the parameter

                lstrcat(pos, _T(" \""));
                lstrcat(pos, url);
                lstrcat(pos, _T("\""));
                result = (HINSTANCE) WinExec(key,showcmd);
            }
        }
    }

    return result;
}

OTHER TIPS

After hearing reports of ShellExecute failing on a minority of systems, I implemented a function similar to the example given by Sergey Kornilov. This was about a year ago. Same premise - Do a direct HKCR lookup of the .HTM file handler.

However, it turns out that some users have editors (e.g. UltraEdit) that register themselves to 'open' .htm files (instead of 'edit' them). Thus, if ShellExecute fails, this secondary method will also fail in those cases. It opens the editor, as the shell association errantly instructs.

Thus, the user should use the HTTP handler instead, or at least in preference of the HTML handler.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top