如何使用Delphi获取与文件扩展名关联的程序的名称?

我需要获取当前与当前用户的文件扩展名关联的程序的名称。 如果你右键点击一个文件并select属性,那么我需要的是“Opens with”行右边的程序名。

例如,对于“.xls”,我希望能够得到答案“Microsoft Office Excel”,或用户使用其默认程序打开.xls文件的任何程序。

我已经确定它不像进入HKEY_CLASSES_ROOT并挑选它,因为它也可以在HKEY_LOCAL_MACHINE或HKEY_CURRENT_USER或HKEY_USERS中指定。

也许我需要知道的是Windows使用的啄食顺序来确定这个以及如何到达每个位置。 当然,一个Windows API调用来做到这一点是理想的。

这是一个类似的问题: 如何从文件扩展名使用Delphi获取图标和描述? 但是这个问题只回答了如何得到相关程序的扩展名和图标的描述。 我无法find一种方法来扩展,以获得相关的程序的名称。

我使用的是Delphi 2009,需要一个适用于Windows XP,Vista和7的解决scheme。


谢谢大家的答案。

看来我相信,可执行文件的名字毕竟不在registry中。 而广泛的四处寻找一个Windows API的名称,我找不到。

我认为Mef的答案是最好的。 从程序可执行文件中包含的信息中获取可执行文件的名称。

Solutions Collecting From Web of "如何使用Delphi获取与文件扩展名关联的程序的名称?"

步骤1

获取分配给文件扩展名的可执行文件,例如使用以下函数:

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; 

(见这里 ,或者marc_s'anwser这个问题:-)

第2步

现在你可以从这个可执行文件的版本信息中读出程序的名字了! 最简单的方法就是使用可以通过Google找到的TVersionInfo类,例如这里 。

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

然而,你必须知道,有些程序使用描述键因此(如RAD Studio本身或MS Excel),而其他人使用产品名称键…

当有API函数设计用来执行你所需要的功能时,不要在注册表中进行探测。

在你的情况下,你想要AssocQueryString 。 你可以给它的文件扩展名,它会告诉你的程序注册处理该扩展( AssocStr_Executable )。 如果您打算运行该程序来打开文档,那么您确实需要命令字符串,而不仅仅是可执行文件。 AssocQueryString也可以给你( AssocStr_Command )。 它也可以告诉你像Windows资源管理器中显示的文档类型,如“文本文档”或“Zip存档”( AssocStr_FriendlyDocName )。

该API函数是IQueryAssociations接口的包装器。 如果您正在寻找来自多种文件类型的程序或与单个类型关联的大量字符串,您可能希望实例化该接口并重新使用它,而不是一遍又一遍地调用API函数。

Delphi带有一个在下面的示例代码中使用的单元ShellApi.pas。 该文件必须存在。

以下是如何使用它:

 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; 

我认为你需要结合Mef和Rob Kennedy的答案。

拿罗布·肯尼迪的回答,从梅夫的回答中采取第二步。 直接阅读注册表是不好的事情,所以你应该扔掉他的第一部分。

但是我不是在寻找文件类型的好记的名字。

AssocQueryString不仅返回文件类型的友好名称( ASSOCSTR_FRIENDLYDOCNAME ),还可以返回可执行文件的名称以打开文件( ASSOCSTR_EXECUTABLE ) – 这正是您所需要的。

甚至更多:我不确定,但可能是ASSOCSTR_FRIENDLYAPPNAME将符合您的需求。 在这种情况下,你可以只使用Rob Kennedy的答案。

直接读取注册表的问题是,它可能会返回错误的信息。 这是因为你阅读系统设置 – 这是应用程序注册。 但用户可以重写这个。 例如,他可以右键单击.xls并选择“打开…” – >“其他应用程序”。 – >“OpenOffice” – >“永远使用这个应用程序”。 .xls类型的注册信息不会被改变(用户偏好被保存在不同的地方,所以应用程序不能混淆他们),所以你的代码(直接读取注册表)将继续产生“MS Excel”,即使当用户双击文件 – OpenOffice将启动。

这篇文章如何: 确定关联的应用程序

在Excel的具体情况下,您将在HKEY_CLASSES_ROOT下找到.xls扩展名 – 该条目的默认值是Excel.Sheet.8

当您再次在HKEY_CLASSES_ROOT中搜索Excel.Sheet.8时,将会找到一个默认值为Microsoft Office Excel 97-2003 Worksheet的条目 – 这可能就像它得到的那样好。

如果用户说“总是使用这个应用程序”.xls文件的信息存储在

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

该键具有包含应用程序名称(例如“soffice.exe”)的条目“应用程序”。 它与HK_CR中的HK_CR\Applications\soffice.exe\键相关,例如HK_CR\Applications\soffice.exe\