我需要获取当前与当前用户的文件扩展名关联的程序的名称。如果右键单击文件并选择属性,那么我需要的是“打开方式”行右侧的程序名称。
例如对于“ .xls”,我希望能够得到答案“ Microsoft Office Excel”,或者用户拥有的默认程序可以打开.xls文件。
我已经确定,这不像进入HKEY_CLASSES_ROOT并选择它那样容易,因为它也可以在HKEY_LOCAL_MACHINE或HKEY_CURRENT_USER或HKEY_USERS中指定。
也许我只需要知道Windows用来确定该顺序以及如何到达每个位置的啄食顺序即可。当然,执行此操作的Windows API调用将是理想选择。
这是一个类似的问题:How to get icon and description from file extension using Delphi?,但该问题仅回答了如何获取扩展名的描述和关联程序的图标。我找不到一种方法来扩展它,以获取相关程序的名称。
我正在使用Delphi 2009,并且需要一种适用于Windows XP,Vista和7的解决方案。
谢谢大家的回答。
我似乎认为可执行文件的名称毕竟不在注册表中。在广泛浏览了会给出名称的Windows API之后,我找不到一个。
我认为Mef的答案是最好的。从程序的可执行文件中包含的信息中获取可执行文件的名称。
后续:我发现David Hefferman's answer to "How do I open a file with the default text editor?"提供了一种使用默认程序针对不同扩展名打开一个程序的绝佳解决方案。
例如,使用以下功能,获取分配给文件扩展名的可执行文件:
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;
((请参阅here,或marc_s对这个问题的解答:-)
现在您可以从该可执行文件的版本信息中读出程序的名称!最简单的方法是使用可以通过Google找到的TVersionInfo类,例如here。
var VersionInfo: TVersionInfo;
VersionInfo := TVersionInfo.Create('PathToExe\name.exe');
s := VersionInfo.KeyValue['Description'];
但是,您必须知道某些程序因此使用描述键(例如RAD Studio本身或MS Excel),而其他程序则使用产品名称键...
[当有设计用于您所需的API函数时,请不要在注册表中摸索。
根据您的情况,您需要AssocQueryString
。您可以给它指定文件扩展名,它会告诉您注册用于处理该扩展名的程序(AssocQueryString
)。如果您打算在该程序中使用[[running打开文档,那么您真的需要命令字符串而不只是可执行文件。 AssocStr_Executable
也可以给您(AssocQueryString
)。它还可以告诉您文档类型,例如Windows资源管理器中显示的内容,例如“文本文档”或“ Zip存档”(AssocStr_Command
)。
AssocStr_FriendlyDocName
接口的包装。如果要从许多文件类型中查找程序,或者从与一种类型相关联的许多字符串中查找程序,则可能希望实例化该接口并重新使用它,而不是一遍又一遍地调用API函数。这里是使用方法:
取罗伯·肯尼迪(Rob Kennedy)的答案,然后从梅夫(Mef)的答案中执行步骤2。直接阅读注册表不是一件好事,因此您应该丢弃他的第1部分。
但是我不是在寻找文件类型的友好名称。
AssocQueryString不仅返回文件类型(IQueryAssociations
)的友好名称,还可以返回打开文件的可执行文件的名称(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;
)-这正是您所需要的。
甚至不止于此:我不确定,但是ASSOCSTR_FRIENDLYDOCNAME可能会满足您的需求。在这种情况下,您只能使用Rob Kennedy的答案。
直接读取注册表的问题是它可能返回错误的信息。那是因为您阅读了系统设置-这就是应用程序注册的内容。但是用户可以覆盖它。例如,他可以右键单击.xls,然后选择“打开方式为...”->“其他应用程序”。 ->“ OpenOffice”->“始终使用此应用”。 .xls类型的注册信息将不会更改(用户首选项保存在单独的位置,因此应用不会与它们混淆),因此即使在以下情况下,您的代码(直接读取注册表)也将继续生成“ MS Excel”用户双击文件-将启动OpenOffice。
在Excel的具体情况下,您会在HKEY_CLASSES_ROOT下找到ASSOCSTR_FRIENDLYAPPNAME扩展名-该条目的默认值为Determining the associated application。
[当您再次在HKEY_CLASSES_ROOT中搜索.xls
时,会发现一个默认值为Excel.Sheet.8
的条目-可能和它一样好。
Excel.Sheet.8
密钥具有包含应用程序名称(例如“ soffice.exe”)的条目“ Application”。它与HK_CR中的应用密钥相关联,例如Microsoft Office Excel 97-2003 Worksheet