9

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

例如对于“.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 的回答是最好的。从程序的可执行文件中包含的信息中获取可执行文件的名称。


跟进:我找到了David Hefferman 对“如何使用默认文本编辑器打开文件?”的回答。为使用不同扩展的默认程序打开一个程序提供了一个极好的解决方案。

4

6 回答 6

11

当有 API 函数可以满足您的需求时,不要在注册表中进行探索。

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

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

于 2010-04-06T15:19:34.310 回答
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;
于 2010-04-06T01:35:39.850 回答
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;

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

第2步

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

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

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

于 2010-04-05T20:09:15.597 回答
4

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

采取 Rob Kennedy 的回答,并从 Mef 的回答中采取第 2 步。直接读registry不是什么好事,你应该扔掉他的part 1。

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

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

更重要的是:我不确定,但ASSOCSTR_FRIENDLYAPPNAME可能会符合您的需求。在这种情况下,您只能使用 Rob Kennedy 的答案。

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

于 2010-04-12T09:26:02.160 回答
3

这篇文章在这里怎么样:确定关联的应用程序

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

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

于 2010-04-05T07:04:37.820 回答
0

如果用户对 .xls 文件说“始终使用此应用程序”,则信息存储在

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

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

于 2010-07-30T10:08:11.247 回答