Как я могу получить название программы, связанной с расширением файла, используя Delphi?

Мне нужно получить название программы, в настоящее время связанной с расширением файла для текущего пользователя. Если вы щелкнете правой кнопкой мыши по файлу и выберете свойства, тогда мне нужно имя программы, которое находится справа от строки "Opens with".

Например, для ".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, который даст имя, я не смог найти его.

Я думаю, что ответ Меф тогда самый лучший. Получить имя исполняемого файла из информации, включенной в исполняемый файл программы.

6 ответов

Решение

Шаг 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

Теперь вы можете прочитать название программы из информации о версии этого исполняемого файла! Самый простой способ - использовать класс TVersionInfo, который вы можете найти через Google, например, здесь.

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

Однако вы должны знать, что некоторые программы используют ключ описания (например, сама RAD Studio или MS Excel), в то время как другие используют ключ имени продукта...

Не засиживайтесь в реестре, когда есть функции API, разработанные для того, что вам нужно.

В вашем случае вы хотите AssocQueryString, Вы можете дать ему расширение имени файла, и оно сообщит вашей программе, зарегистрированной для обработки этого расширения (AssocStr_Executable). Если вы планируете запустить эту программу для открытия документа, тогда вам действительно понадобится командная строка, а не просто исполняемый файл; AssocQueryString могу тебе тоже это дать (AssocStr_Command). Он также может указать тип документа, например, отображаемый в проводнике Windows, например "Текстовый документ" или "Zip-архив" (AssocStr_FriendlyDocName).

Эта функция API является оберткой для IQueryAssociations интерфейс. Если вы ищете программы из разных типов файлов или множества строк, связанных с одним типом, вы можете создать экземпляр этого интерфейса и использовать его повторно, а не вызывать функцию API снова и снова.

Я думаю, что вам нужно объединить ответы Меф и Роба Кеннеди.

Возьмите ответ Роба Кеннеди и сделайте шаг 2 из ответа Мефа. Чтение реестра напрямую не очень хорошая вещь, поэтому вы должны выбросить его часть 1.

Но я не ищу понятное имя типа файла.

AssocQueryString возвращает не только понятное имя для типа файла ( ASSOCSTR_FRIENDLYDOCNAME), но также может возвращать имя исполняемого файла для открытия файла ( ASSOCSTR_EXECUTABLE) - это то, что вам нужно.

Более того: я не уверен, но может быть ASSOCSTR_FRIENDLYAPPNAME будет соответствовать вашим потребностям. В этом случае вы можете использовать только ответ Роба Кеннеди.

Проблема с чтением реестра напрямую заключается в том, что он может возвращать неверную информацию. Это потому, что вы читаете системные настройки - это то, что приложение зарегистрировано. Но пользователь может переопределить это. Например, он может щелкнуть правой кнопкой мыши на.xls и выбрать "Открыть с помощью..." -> "Другое приложение". -> "OpenOffice" -> "Используйте это приложение всегда". Информация о регистрации для типа.xls не будет изменена (пользовательские настройки сохраняются в отдельном месте, поэтому приложения не могут связываться с ними), поэтому ваш код (который читает реестр напрямую) будет продолжать создавать "MS Excel", даже если пользователь дважды щелкает файл - OpenOffice будет запущен.

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;

Как насчет этой статьи здесь: Определение связанного приложения

В конкретном случае Excel вы найдете .xls расширение под HKEY_CLASSES_ROOT - значение по умолчанию для этой записи Excel.Sheet.8,

Когда вы идете искать Excel.Sheet.8 снова в HKEY_CLASSES_ROOT, вы найдете запись со значением по умолчанию Microsoft Office Excel 97-2003 Worksheet - это, вероятно, так же хорошо, как это получается.

Если пользователь говорит "используйте это приложение всегда" для.xls-файлов, информация сохраняется в

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

Ключ имеет запись "Приложение", содержащую имя приложения (например, "soffice.exe"). Это связано с ключом Applcication в HK_CR, например HK_CR\Applications\soffice.exe\

Другие вопросы по тегам