The MFC Professional Stingray Software

NEWBIE TIP #8
Finding a File Association in the Registry


I have a program that lists files, like File Manager or Explorer, and I need to be able to let the user double-click on a file, and invoke the proper executable. How can I do this?

This is not really an MFC question, but what the heck. We're not overly formal here -- anything that solves a problem is a good thing, even if it is standard SDK stuff!

First of all, let me say that a few of you have kindly pointed out in the previous version of this tip that you can use the FindExecutable() function provided in the Windows API. It simply takes a file name and returns the fully-qualified path name of the exe file you need to open it. I would definitely recommend that method if you have an existing file that you need to open.

However, I'm still offering the following tip because if you've never programmed for the Registry before, it's not a bad little introduction. I used it in an app recently where I had a list of extensions (not files), and I needed a corresponding list of exe's. It did the trick nicely.

Basically, it's a two-step process, and you can follow along by running RegEdit or RegEdt32. The HKEY_CLASSES_ROOT section contains a long list of file extensions. Each extension is associated with the title of the program associated with it, or often it is a description of the file type. For instance, in my Registry, the default entry for ".html" is "NetscapeMarkup".

That's the first step. The second step is to then look up, in the same list, the entry you just found. In this case, I'd look for "NetscapeMarkup". Under that, you'll probably find several sub-entries in the tree. The entry you're interested in is "shell\open\command" ("command" is an entry beneath "open", which in turn is an entry beneath "shell"). The default value here is the command line that is invoked to edit that file type.

Very often, the executable is followed by %1 or %2, etc. What my routine below does is look for the first "%" character, and then go backwards until it finds a space character. It then places the end of string on top of the space. That should ensure that you're getting just the name of the executable file.

I hope this will enrich your life as much as it has mine!


/////////////////////////////////////////////////////////////////////
// GetRegistryExe
// Returns the full executable file & path name that will open a
// document with a given extension.

void GetRegistryExe (LPCSTR szInput, LPSTR szOut, UINT uiOutSize)
{
    szOut[0] = 0;

    // Copy input extension to our extension.
    // Make sure it begins with '.'
    char szExt[16];
    szExt[0] = 0;
    if (szInput[0] != '.')
        lstrcpy(szExt, ".");
    lstrcat(szExt, szInput);

    // Get title of program assoc with this extension.
    char szName[256];
    GetRegistryEntry(szExt, "", szName, sizeof(szName));
    if (szName[0] == 0) return;

    // Get corresponding exe filename.
    lstrcat(szName, "\\shell\\open\\command");
    GetRegistryEntry(szName, "", szOut, uiOutSize);
    if (szOut[0] == 0) return;

    // Remove everything after the first "%" char
    // in case there's a %1, %2, or other param.
    char *pChar = strchr(szOut, '%');
    if (pChar)
    {
        for (--pChar  ;  pChar > szOut && *pChar != ' '  ;  --pChar)
            ;
        *pChar = 0;
    }
}

/////////////////////////////////////////////////////////////////////
// GetRegistryEntry
// Fetches an HKEY_CLASSES_ROOT registry entry for a given path
// and value.

void GetRegistryEntry ( LPCSTR szInPath, LPCSTR szInValue,
                        LPSTR  szOut,    UINT   uiOutSize )
{
    szOut[0] = 0;
    HKEY hKey;
    if (RegOpenKey(HKEY_CLASSES_ROOT, szInPath, &hKey)
        == ERROR_SUCCESS)
    {
        LONG lSize = (LONG) uiOutSize;
        RegQueryValue(hKey, szInValue, szOut, &lSize);
        RegCloseKey(hKey);
    }
}


Source code is provided for instructional purposes, and is released to the public domain. No claim of ownership is made. Use it at your own risk. No warranties are expressed or implied. The resulting program may not be fully functional. No animals were used to test this code.

| Past Tips | Future Tips | Home |

Comments on this Tip? Send us mail.
(Be sure to put the Tip # in the subject.)

Got an idea for a Tip you'd like us to write? Let us know.

Solved a problem lately that would make a good Tip? PLEASE tell us about it!!!
We'll give you prominent credit, and we'll even buy you a beer next time you're in town.