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

发布于 2024-08-27 20:54:09 字数 852 浏览 5 评论 0原文

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

例如,对于“.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 对“如何使用默认文本编辑器打开文件?”的回答提供了一个出色的解决方案用于使用不同扩展名的默认程序打开一个程序。

I need to get the name of the program currently associated with a file extension for the current user. If you right-click on a file and select properties, then what I need is the program name that is to the right of the "Opens with" line.

e.g. For ".xls", I want to be able to get the answer "Microsoft Office Excel", or whatever program the user has as their default program to open .xls files.

I have determined it's not as easy as just going into HKEY_CLASSES_ROOT and picking it out, since it may also be specified in HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER or HKEY_USERS.

Maybe all I need to know is the pecking order used by Windows to determine this and how to get to each of the locations. Of course, a Windows API call to do this would be ideal.

This is a similar question to:
How to get icon and description from file extension using Delphi? but that question only answered how to get the description of the extension and the icon of the associated program. I couldn't find a way to extend that to also get the name of the associated program.

I'm using Delphi 2009 and need a solution that works on Windows XP, Vista and 7.


Thank you all for your answers.

It appears my belief that the name of the executable is not in the Registry after all. And after looking around extensively for a Windows API that will give the name, I could not find one.

I think Mef's answer then is the best. To get the name of the executable from the information included in the program's executable.


Followup: I found David Hefferman's answer to "How do I open a file with the default text editor?" gives an excellent solution for opening one program using the default program for a different extension.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

锦上情书 2024-09-03 20:54:09

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

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

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

Don't go spelunking in the registry when there are API functions designed to do what you need.

In your case, you want AssocQueryString. You can give it the file-name extension, and it will tell your the program registered to handle that extension (AssocStr_Executable). If you're planning on running that program to open a document, then you'll really want the command string instead of just the executable; AssocQueryString can give you that, too (AssocStr_Command). It can also tell you the document type like what's displayed in Windows Explorer, like "Text Document" or "Zip Archive" (AssocStr_FriendlyDocName).

That API function is a wrapper for the IQueryAssociations interface. If you're looking for programs from many file types, or lots of strings associated with a single type, you may wish to instantiate that interface and re-use it instead of calling the API function over and over.

爱要勇敢去追 2024-09-03 20:54:09

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;

Delphi comes with a unit ShellApi.pas that is used in the sample code below. The file has to exist.

Here's how to use it:

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;
〃安静 2024-09-03 20:54:09

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

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

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

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

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

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

I think that you need to combine Mef's and Rob Kennedy's answers.

Take Rob Kennedy's answer and take step 2 from Mef's answer. Reading registry directly isn't good thing to do, so you should throw away his part 1.

But I'm not looking for the friendly name of the file type.

AssocQueryString returns not only friendly name for file type (ASSOCSTR_FRIENDLYDOCNAME), but also it can return the name of executable to open file (ASSOCSTR_EXECUTABLE) - that is what you need.

Even more than that: I'm not sure, but may be ASSOCSTR_FRIENDLYAPPNAME will match your needs. In that case, you may use only Rob Kennedy's answer.

The problem with reading registry directly is that it may return wrong info. That's because you read system settings - that is what application registered. But user may override this. For example, he may right click on .xls and select "Open with..." -> "Other app." -> "OpenOffice" -> "Use this app always". Registration info for .xls type will not be altered (user preferences are saved in separate place, so apps can't mess with them), so your code (which reads registry directly) will continue to produce "MS Excel", even though when user double-clicks on file - OpenOffice will be launched.

吻安 2024-09-03 20:54:09

步骤 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 类,例如 此处< /a>.

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

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

Step 1

Get the executable which is assigned to a file extension, for instance with the following function:

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;

(See here, or marc_s' anwser to this question :-)

Step 2

Now you can read out the name of the program from the version information of this executable! The easiest way is using the TVersionInfo class you can find via Google, for instance here.

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

However, you have to be aware that some programs use the description key therefore (like RAD Studio itself or MS Excel), while others use the product name key...

傲娇萝莉攻 2024-09-03 20:54:09

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

以Excel为例,您将在 HKEY_CLASSES_ROOT 下找到 .xls 扩展名 - 该条目的默认值为 Excel.Sheet.8

当您在 HKEY_CLASSES_ROOT 中再次搜索 Excel.Sheet.8 时,您会发现一个默认值为 Microsoft Office Excel 97-2003 Worksheet 的条目 - 可能是这样很好。

How about this article here: Determining the associated application

In the concrete case of Excel, you will find the .xls extension under HKEY_CLASSES_ROOT - the default value of that entry is Excel.Sheet.8.

When you go search for Excel.Sheet.8 again in HKEY_CLASSES_ROOT, you'll find an entry with a default value of Microsoft Office Excel 97-2003 Worksheet - that's probably as good as it gets.

拥抱没勇气 2024-09-03 20:54:09

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

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

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

If the user says "use this app always" for .xls-files the info ist stored in

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

The key has an entry "Application" containing the Application name (e.g. "soffice.exe"). It's correlated to an Applcication key in HK_CR, e.g. HK_CR\Applications\soffice.exe\

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文