【问题标题】:How can I get the Name of the Program associated with a file extension using Delphi?如何使用 Delphi 获取与文件扩展名关联的程序名称?
【发布时间】:2020-02-23 04:10:13
【问题描述】:

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

例如对于“.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?" 提供了一个很好的解决方案,可以使用默认程序为不同的扩展程序打开一个程序。

【问题讨论】:

    标签: windows delphi registry file-type file-association


    【解决方案1】:

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

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

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

    【讨论】:

    • @Rob:我同意我宁愿使用 API 函数而不是注册表。但我不是在寻找文件类型的友好名称。我正在寻找文件类型的默认应用程序的友好名称。我希望能够告诉用户 .xls 的默认应用程序是“Microsoft Office Excel”或 .txt 的默认应用程序是“记事本”。不知道有没有获取应用名称的API。
    • 这是正确答案。传入 ASSOCSTR_FRIENDLYAPPNAME 将为您提供应用程序名称。
    【解决方案2】:

    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;
    

    【讨论】:

    • 与使用注册表相比,这是获取可执行文件路径的好选择。但它确实需要将实际文件传递给它,而不仅仅是扩展名。但是它仍然没有给出运行扩展程序的名称。
    • 是的,你是对的 - 正如我的 OP 中所述,它需要一个实际文件,而不仅仅是扩展名。不确定“但是它仍然没有给出运行扩展程序的程序名称”是什么意思。如果我用“Workbook1.xls”调用它,它会返回:“C:\Program Files (x86)\Microsoft Office\Office12\EXCEL.EXE”
    • 他不是在寻找 excel.exe,而是在寻找 Microsoft Office Excel。
    【解决方案3】:

    步骤 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;
    

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

    第二步

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

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

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

    【讨论】:

    • @Mef:这是一个有趣的想法 - 将名称从可执行文件本身的版本信息中提取出来,考虑到您提到的警告,这可能会起作用。我不确定 Windows 是否在其“打开方式”对话框中使用它。 ...但在内心深处,我仍然认为应用程序名称本身隐藏在注册表中的某个地方并且可以获取。它有点复杂,例如:msdn.microsoft.com/en-us/library/ee872122(VS.85).aspxmsdn.microsoft.com/en-us/library/ee330739(v=VS.85).aspx
    • @lkessler:您可以在注册扩展时指定文件描述(和 ext 描述)(marc_s 描述的内容) - 我认为 that 是 Windows 在 Open使用 Dialog... 但我可能错了。我想了想,得出的结论是,在注册表中不能有存储应用程序名称的特定位置 - 因为“打开方式”适用于不向注册表自身写入任何内容的 exe,您可以用一个简单的空白 WinForm 进行测试;-) 有趣的部分是显示的名称,我不知道 =)
    • 我认为它必须使用注册表中的某些内容。否则,我看不到位于 winhelponline.com/blog/openwithadd-12-supports-windows-vista 的 OpenWithAdd 工具如何工作。
    • @lkessler:我不明白你的意思。此工具将您之前输入的名称写入提到的注册表键 marc_s。这不是程序本身定义的......
    • .xlsx扩展文件和Excel怎么样?
    【解决方案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。

    【讨论】:

    • @亚历山大。如果用户说“始终使用这个应用程序”,那么该信息必须存储在某个地方,这就是我想要的。无论它是否存储在注册表中,我都需要知道该用户将使用哪个应用程序打开此文件扩展名。
    • 嗯...所以?这就是为什么我建议您使用 API 而不是手动搜索此信息的原因。
    【解决方案5】:

    这篇文章怎么样:Determining the associated application

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

    当您在 HKEY_CLASSES_ROOT 中再次搜索 Excel.Sheet.8 时,您会找到一个默认值为 Microsoft Office Excel 97-2003 Worksheet 的条目 - 这可能已经达到了最佳效果。

    【讨论】:

    • 谢谢。我在搜索中没有看到那篇文章。但实际上有两个问题。 (1) 它只使用 HKEY_CLASSES_ROOT 并且不一定是 Windows 将使用的位置(请参阅我在问题中提到的其他位置),以及 (2) 它提供了可执行程序的路径。但我实际上需要该程序的名称,而不是它的路径。
    • 实际上 HKEY_CLASSES_ROOT 是 HKEY_CURRENT_USER\Software\Classes 和 HKEY_LOCAL_MACHINE\SOFTWARE\Classes 的合并视图(按此顺序),因此它 Windows 将使用的位置。
    • @marc_s:你的想法是对的。但是您获得的“Microsoft Office Excel 97-2003 Worksheet”的价值仍然描述了该文档。我需要程序名称。当我搜索时,我可以在以下位置找到它:“HKCR\Local Settings\Software\Microsoft\Windows\Shell\MuiCache”,并且它具有与文件路径关联的“Microsoft Office Excel”的值。它也在我的 64 位机器上的“\HKCR\Wow6432Node\Local Settings\Software\Microsoft\Windows\SHell\MuiCache”,它也在 HKCU 和其他地方。问题是如何从“.xls”追踪到“Microsoft Office Excel”?
    • 链接已失效,存档万岁:web.archive.org/web/20080511193532/http://… :)
    • 注册表项HKEY_CLASSES_ROOT\Excel.Sheet.12(由HKEY_CLASSES_ROOT\.xlsx引用),真的是[HKEY_CLASSES_ROOT\Excel.Sheet.12\shell\Open\command],我得到@="\"C:\\Program Files\\Microsoft Office 15\\Root\\Office15\\EXCEL.EXE\" /dde"的值。
    【解决方案6】:

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

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

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

    【讨论】:

    • 我没有查看应用程序HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.xlsxOpenWithListOpenWithProgids
    猜你喜欢
    • 2011-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多