9

I need to get the name of the program currently associated with a file extension for the current user. If you right-click on a file and select properties, then what I need is the program name that is to the right of the "Opens with" line.

e.g. For ".xls", I want to be able to get the answer "Microsoft Office Excel", or whatever program the user has as their default program to open .xls files.

I have determined it's not as easy as just going into HKEY_CLASSES_ROOT and picking it out, since it may also be specified in HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER or HKEY_USERS.

Maybe all I need to know is the pecking order used by Windows to determine this and how to get to each of the locations. Of course, a Windows API call to do this would be ideal.

This is a similar question to: How to get icon and description from file extension using Delphi? but that question only answered how to get the description of the extension and the icon of the associated program. I couldn't find a way to extend that to also get the name of the associated program.

I'm using Delphi 2009 and need a solution that works on Windows XP, Vista and 7.


Thank you all for your answers.

It appears my belief that the name of the executable is not in the Registry after all. And after looking around extensively for a Windows API that will give the name, I could not find one.

I think Mef's answer then is the best. To get the name of the executable from the information included in the program's executable.


Followup: I found David Hefferman's answer to "How do I open a file with the default text editor?" gives an excellent solution for opening one program using the default program for a different extension.

lkessler
  • 19,819
  • 36
  • 132
  • 203

6 Answers6

11

Don't go spelunking in the registry when there are API functions designed to do what you need.

In your case, you want AssocQueryString. You can give it the file-name extension, and it will tell your the program registered to handle that extension (AssocStr_Executable). If you're planning on running that program to open a document, then you'll really want the command string instead of just the executable; AssocQueryString can give you that, too (AssocStr_Command). It can also tell you the document type like what's displayed in Windows Explorer, like "Text Document" or "Zip Archive" (AssocStr_FriendlyDocName).

That API function is a wrapper for the IQueryAssociations interface. If you're looking for programs from many file types, or lots of strings associated with a single type, you may wish to instantiate that interface and re-use it instead of calling the API function over and over.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • @Rob: I agree I'd sooner use an API function than the registry. But I'm not looking for the friendly name of the file type. I'm looking for the friendly name of the default application for the file type. I want to be able to tell the user that the default application for .xls is "Microsoft Office Excel" or for .txt is "Notepad". I don't know that there's an API to get the application name. – lkessler Apr 06 '10 at 19:00
  • 1
    This is the correct answer. Passing in ASSOCSTR_FRIENDLYAPPNAME will give you the application name. – Peter Ruderman Mar 19 '12 at 17:54
5

Delphi comes with a unit ShellApi.pas that is used in the sample code below. The file has to exist.

Here's how to use it:

function MyShellFindExecutable(const aFileName: string): string;
var
  Buffer: array[0..WINDOWS.MAX_PATH] of Char;
begin
  Result := '';
  FillChar(Buffer, SizeOf(Buffer), #0);
  if (SHELLAPI.FindExecutable(PChar(aFileName), nil, Buffer) > 32) then
    Result := Buffer;
end;
RobertFrank
  • 7,332
  • 11
  • 53
  • 99
  • That's a good alternative to get the path of the executable as opposed to using the Registry. But it does require that an actual file be passed to it rather than just the extension. However it still does not give the name of the program to run the extension. – lkessler Apr 06 '10 at 14:49
  • Yes, you're correct - as noted in my OP, it requires an actual file, not just an extension. Not sure what you mean by "However it still does not give the name of the program to run the extension." if I call it with "Workbook1.xls" it returns: "C:\Program Files (x86)\Microsoft Office\Office12\EXCEL.EXE" – RobertFrank Apr 06 '10 at 15:40
  • He is not looking for excel.exe, he is looking for Microsoft Office Excel. – Leo Apr 06 '10 at 21:54
4

Step 1

Get the executable which is assigned to a file extension, for instance with the following function:

uses Registry, Windows, SysUtils;

function GetAssociation(const DocFileName: string): string;
var
  FileClass: string;
  Reg: TRegistry;
begin
  Result := '';
  Reg := TRegistry.Create(KEY_EXECUTE);
  Reg.RootKey := HKEY_CLASSES_ROOT;
  FileClass := '';
  if Reg.OpenKeyReadOnly(ExtractFileExt(DocFileName)) then
  begin
    FileClass := Reg.ReadString('');
    Reg.CloseKey;
  end;
  if FileClass <> '' then begin
    if Reg.OpenKeyReadOnly(FileClass + '\Shell\Open\Command') then
    begin
      Result := Reg.ReadString('');
      Reg.CloseKey;
    end;
  end;
  Reg.Free;
end;

(See here, or marc_s' anwser to this question :-)

Step 2

Now you can read out the name of the program from the version information of this executable! The easiest way is using the TVersionInfo class you can find via Google, for instance here.

var VersionInfo: TVersionInfo;  
VersionInfo := TVersionInfo.Create('PathToExe\name.exe');  
s := VersionInfo.KeyValue['Description'];

However, you have to be aware that some programs use the description key therefore (like RAD Studio itself or MS Excel), while others use the product name key...

Community
  • 1
  • 1
Leo
  • 37,640
  • 8
  • 75
  • 100
  • @Mef: That's an interesting idea - to pull the name out of the version info in the executable itself, and that could work given the caveats you mention. I'm not sure if Windows uses that in its "Open With" dialog or not. ... But deep down I still think the application name itself is buried somewhere in the Registry and can be got at. It is somewhat complex, e.g.: http://msdn.microsoft.com/en-us/library/ee872122(VS.85).aspx and http://msdn.microsoft.com/en-us/library/ee330739(v=VS.85).aspx – lkessler Apr 05 '10 at 22:26
  • @lkessler: You can specify a file description (and an ext description) when registering an extension (what marc_s described) - I thought **that** is what Windows uses in the Open With Dialog... But I may be wrong. I thought about it, and I came to the conclusion that there can't be a specific place in the Registry where Application Names are stored - because "Open With" works with exes that don't write anything to Registry semselfs as well, you can test this with a simple blank WinForm ;-) The interesting part is what name is displayed, I don't know =) – Leo Apr 06 '10 at 11:48
  • I think it must use something in the Registry. Otherwise, I don't see how the OpenWithAdd tool at: http://www.winhelponline.com/blog/openwithadd-12-supports-windows-vista/ can work. – lkessler Apr 07 '10 at 14:53
  • @lkessler: I don't understand what you mean. This tool writes the name you entered before to the registry key marc_s mentioned. That's nothing the programs themselfs define... – Leo Apr 08 '10 at 14:51
  • How about ***.xlsx extension file and Excel***? – Kiquenet Mar 09 '17 at 11:08
  • To check whether a file has an association you can use the native function ***FindExecutable*** which is basically what _Windows Explorer_ uses internally... it gives a nice error code (`SE_ERR_NOASSOC`) if there is no association. Upon success it gives a path to the respective executable. View http://stackoverflow.com/a/9540278/206730 – Kiquenet Mar 10 '17 at 13:19
4

I think that you need to combine Mef's and Rob Kennedy's answers.

Take Rob Kennedy's answer and take step 2 from Mef's answer. Reading registry directly isn't good thing to do, so you should throw away his part 1.

But I'm not looking for the friendly name of the file type.

AssocQueryString returns not only friendly name for file type (ASSOCSTR_FRIENDLYDOCNAME), but also it can return the name of executable to open file (ASSOCSTR_EXECUTABLE) - that is what you need.

Even more than that: I'm not sure, but may be ASSOCSTR_FRIENDLYAPPNAME will match your needs. In that case, you may use only Rob Kennedy's answer.

The problem with reading registry directly is that it may return wrong info. That's because you read system settings - that is what application registered. But user may override this. For example, he may right click on .xls and select "Open with..." -> "Other app." -> "OpenOffice" -> "Use this app always". Registration info for .xls type will not be altered (user preferences are saved in separate place, so apps can't mess with them), so your code (which reads registry directly) will continue to produce "MS Excel", even though when user double-clicks on file - OpenOffice will be launched.

Alex
  • 5,477
  • 2
  • 36
  • 56
  • @Alexander. If the user says "Use this app always", then that info has to be stored somewhere, and that's what I want. Whether or not it is stored in the Registry, I need to know what application this user will open this file extension with. – lkessler Apr 12 '10 at 18:45
  • Ummm... so? That's why I suggested you to use API and not hunt for this info manually. – Alex Apr 12 '10 at 19:11
3

How about this article here: Determining the associated application

In the concrete case of Excel, you will find the .xls extension under HKEY_CLASSES_ROOT - the default value of that entry is Excel.Sheet.8.

When you go search for Excel.Sheet.8 again in HKEY_CLASSES_ROOT, you'll find an entry with a default value of Microsoft Office Excel 97-2003 Worksheet - that's probably as good as it gets.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • Thanks for that. I hadn't seen that article in my search. But there's actually 2 problems with it. (1) It only uses HKEY_CLASSES_ROOT and that won't necessarily be the location that Windows will use (see the other locations I mention in my question), and (2) It gives the path to the executable program. But I actually need the name of that program, not the path to it. – lkessler Apr 05 '10 at 07:13
  • 2
    Actually HKEY_CLASSES_ROOT is a merged view of HKEY_CURRENT_USER\Software\Classes and HKEY_LOCAL_MACHINE\SOFTWARE\Classes (in that order) so it *IS* the location Windows will use. – Remko Apr 05 '10 at 08:17
  • @marc_s: You've got the right idea. But the value you've got of "Microsoft Office Excel 97-2003 Worksheet" still describes the document. I need the program name. When I search, I can find it at: "HKCR\Local Settings\Software\Microsoft\Windows\Shell\MuiCache" and it has the value of "Microsoft Office Excel" associated with the file path. It's also at "\HKCR\Wow6432Node\Local Settings\Software\Microsoft\Windows\SHell\MuiCache" on my 64-bit machine, and it's also in HKCU and maybe elsewhere. The question is how do I trace my way from ".xls" to "Microsoft Office Excel"? – lkessler Apr 05 '10 at 17:34
  • Link is dead, long live the archive: https://web.archive.org/web/20080511193532/http://www.latiumsoftware.com/en/delphi/00005.php :) – WiredPrairie Dec 05 '13 at 19:52
  • the registry key `HKEY_CLASSES_ROOT\Excel.Sheet.12` (referenced by `HKEY_CLASSES_ROOT\.xlsx`), really `[HKEY_CLASSES_ROOT\Excel.Sheet.12\shell\Open\command]` and I get `@="\"C:\\Program Files\\Microsoft Office 15\\Root\\Office15\\EXCEL.EXE\" /dde"` value. – Kiquenet Mar 09 '17 at 16:42
  • For **ShellNew** extension under `HKEY_CLASSES_ROOT\.xlsx\Excel.Sheet.12` , has value REG_SZ _FileName_ like _C:\Program Files\Microsoft Office 15\Root\VFS\Windows\ShellNew\excel12.xlsx_ – Kiquenet Mar 09 '17 at 16:44
  • The registry key `[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Extensions]` has `"xlsx"="C:\\Program Files\\Microsoft Office 15\\Root\\Office15\\EXCEL.EXE"` – Kiquenet Mar 09 '17 at 16:46
  • The registry key `[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.xlsx\OpenWithList]` has `"a"="EXCEL.EXE"` and `[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.xlsx\OpenWithProgids]` has `"Excel.Sheet.12"=hex(0):` – Kiquenet Mar 09 '17 at 16:57
0

If the user says "use this app always" for .xls-files the info ist stored in

HK_CU\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.xls

The key has an entry "Application" containing the Application name (e.g. "soffice.exe"). It's correlated to an Applcication key in HK_CR, e.g. HK_CR\Applications\soffice.exe\

  • I have not view _Application_. `HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.xlsx` has ***OpenWithList*** and ***OpenWithProgids*** – Kiquenet Mar 09 '17 at 11:31