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

lke*_*ler 9 windows delphi registry file-type file-association

我需要获取当前与当前用户的文件扩展名相关联的程序的名称.如果右键单击文件并选择属性,那么我需要的是"打开方式"行右侧的程序名称.

例如,对于".xls",我希望能够得到答案"Microsoft Office Excel",或者用户拥有的任何程序作为打开.xls文件的默认程序.

我已经确定它并不像进入HKEY_CLASSES_ROOT并选择它那么容易,因为它也可以在HKEY_LOCAL_MACHINE或HKEY_CURRENT_USER或HKEY_USERS中指定.

也许我需要知道的是Windows用来确定这个以及如何到达每个位置的啄食顺序.当然,执行此操作的Windows API调用将是理想的.

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

我正在使用Delphi 2009,需要一个适用于Windows XP,Vista和7的解决方案.


谢谢大家的答案.

我认为可执行文件的名称毕竟不在注册表中.在广泛浏览了将提供名称的Windows API之后,我找不到一个.

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

Rob*_*edy 11

当存在旨在满足您需求的API函数时,不要在注册表中进行搜索.

在你的情况下,你想要AssocQueryString.您可以为其指定文件扩展名,它将告诉您注册的程序处理该扩展名(AssocStr_Executable).如果您计划运行该程序来打开文档,那么您真的需要命令字符串而不仅仅是可执行文件; AssocQueryString也可以给你那个(AssocStr_Command).它还可以告诉您文档类型,如Windows资源管理器中显示的内容,如"文本文档"或"Zip存档"(AssocStr_FriendlyDocName).

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


Rob*_*ank 5

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;
Run Code Online (Sandbox Code Playgroud)


Ale*_*lex 5

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

采用 Rob Kennedy 的答案并执行 Mef 答案中的步骤 2。直接读取注册表并不是一件好事,所以你应该扔掉他的第 1 部分。

但我并不是在寻找文件类型的友好名称。

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

更重要的是:我不确定,但ASSOCSTR_FRIENDLYAPPNAME可能会满足您的需求。在这种情况下,您只能使用罗布·肯尼迪的答案。

直接读取注册表的问题是它可能会返回错误的信息。那是因为您读取系统设置 - 这就是应用程序注册的内容。但用户可以覆盖它。例如,他可以右键单击 .xls 并选择“打开方式...”->“其他应用程序”。->“OpenOffice”->“始终使用此应用程序”。.xls 类型的注册信息不会更改(用户首选项保存在单独的位置,因此应用程序无法干扰它们),因此您的代码(直接读取注册表)将继续生成“MS Excel”,即使当用户双击文件 - OpenOffice 将启动。


Leo*_*Leo 4

步骤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;
Run Code Online (Sandbox Code Playgroud)

(请参阅此处,或 marc_s 对这个问题的回答:-)

第2步

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

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

但是,您必须注意,某些程序因此使用描述键(例如 RAD Studio 本身或 MS Excel),而其他程序则使用产品名称键...