Как я могу получить название программы, связанной с расширением файла, используя 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\