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.