Создать запись реестра, чтобы связать расширение файла с приложением в C++
Я хотел бы знать самый простой способ регистрации расширения файла в моем приложении C++, чтобы при двойном щелчке файла данных, связанного с моей программой, приложение открывалось, а имя файла передавалось приложению в качестве параметра.
В настоящее время я делаю это через мой установщик wix, но в некоторых случаях приложение не будет установлено на компьютере пользователя, поэтому мне также нужна опция создания раздела реестра через приложение.
Кроме того, будет ли это означать, что если приложение будет удалено, неиспользуемые записи в реестре останутся валяться?
3 ответа
Ваш основной обзор процесса находится в этой статье MSDN. Ключевые части находятся внизу списка:
- Зарегистрировать ProgID
ProgID (по сути, раздел реестра типа файла) - это то, что содержит важные свойства типа файла, такие как значок, описание и элементы контекстного меню, включая приложение, используемое при двойном щелчке файла. Многие расширения могут иметь одинаковый тип файла. Это сопоставление выполняется на следующем шаге:
- Зарегистрируйте расширение имени файла для типа файла
Здесь вы устанавливаете значение реестра для вашего расширения, устанавливая тип файла этого расширения в ProgID, который вы создали на предыдущем шаге.
Минимальный объем работы, необходимый для открытия файла в вашем приложении, - это установка / создание двух ключей реестра. В этом примере .reg
файл, я создаю тип файла (blergcorp.blergapp.v1
) и связать расширение файла (.blerg
) с этим.
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Classes\blergcorp.blergapp.v1\shell\open\command]
@="c:\path\to\app.exe \"%1\""
[HKEY_CURRENT_USER\Software\Classes\.blerg]
@="blergcorp.blergapp.v1"
Теперь вы, вероятно, хотите сделать это программно. Чтобы быть абсолютно кошерным, вы можете проверить наличие этих ключей и соответствующим образом изменить поведение вашей программы, особенно если вы берете под контроль какое-то общее расширение файла. Однако цель может быть достигнута путем установки этих двух клавиш с помощью функции SetValue.
Я не уверен в точном синтаксисе C++, но в C# синтаксис выглядит примерно так:
Registry.SetValue(@"HKEY_CURRENT_USER\Software\Classes\blergcorp.blergapp.v1\shell\open\command", null, @"c:\path\to\app.exe \"%1\"");
Registry.SetValue(@"HKEY_CURRENT_USER\Software\Classes\.blerg", null, "blergcorp.blergapp.v1");
Конечно, вы можете вручную открыть каждый вложенный ключ, вручную создать ProgID и дополнительный ключ расширения, а затем установить значение ключа, но приятно отметить, что SetValue
Функция в том, что если ключи или значения не существуют, они будут созданы автоматически. Очень кстати.
Теперь быстрое слово о том, какой улей использовать. Многие примеры сопоставления файлов в Интернете, в том числе на MSDN, показывают, что эти ключи установлены в HKEY_CLASSES_ROOT
, Я не рекомендую делать это. Этот улей представляет собой объединенный, виртуальный вид HKEY_LOCAL_MACHINE\Software\Classes
(система по умолчанию) и HKEY_CURRENT_USER\Software\Classes
(настройки для каждого пользователя) и записи в любой подраздел в кусте перенаправляются на тот же ключ в HKEY_LOCAL_MACHINE\Software\Classes
, Теперь нет прямой проблемы с этим, но вы можете столкнуться с этой проблемой: если вы пишете в HKCR (перенаправленный в HKLM), и пользователь указал те же ключи с разными значениями в HKCU, значения HKCU будут иметь приоритет. Поэтому ваши записи будут успешными, но вы не увидите никаких изменений, потому что HKEY_CURRENT_USER
настройки имеют приоритет над HKEY_LOCAL_MACHINE
Настройки.
Поэтому вы должны принять это во внимание при разработке вашего приложения. Теперь, с другой стороны, вы можете написать только HKEY_CURRENT_USER
Как показывают мои примеры здесь. Однако этот параметр сопоставления файлов будет загружен только для текущего пользователя, и если ваше приложение установлено для всех пользователей, оно не запустится, когда этот другой пользователь откроет файл в Windows.
Это должно быть достойным учебником для того, что вы хотите сделать. Для дальнейшего чтения предлагаю
- Лучшие практики для ассоциации файлов
- Типы файлов и ассоциации файлов, особенно
- Как работают файловые ассоциации
И посмотрите также мой аналогичный ответ на похожий вопрос:
Это двухэтапный процесс:
1. Определите программу, которая позаботится о расширении: (если вы не хотите использовать существующую) 1.1 создать ключ в "HKCU\\Software\\Classes\\", например "Software\\ \\ Классы YourProgramName.file.ext" 1.2 создать подраздел "Software\\Classes\\YourProgramName.file.ext\\DefaultIcon" 1.2.1 установить значение по умолчанию ("") для полного пути вашего приложения, чтобы получить значок из ресурсов 1.3 создать подраздел "Программное обеспечение \\Classes\\YourProgramName.file.ext\\Shell\\OperationName\\Command" OperationName = например Open, Print или Other 1.3.1 установить значение по умолчанию ("") для полного пути вашего приложения + необязательные параметры времени выполнения (имя файла) 2. Ассоциируйте расширение файла с программой. 2.1 создать ключ HKCU\\Software\\Classes\\. Ext - здесь идет ваше расширение 2.2 установить значение по умолчанию для ключа определения программы ("YourProgramName.file.ext")
Ниже приведена часть программы, написанная на C#, которая ассоциирует расширение файла. Это не C++, но я думаю, что достаточно просто объяснить себя, и AFAIK это verv simmilar, если не идентично коду в C++
1.
RegistryKey keyPFCTExt0 = Registry.CurrentUser.OpenSubKey("Software\\Classes\\PFCT.file.enc", true);
if (keyPFCTExt0 == null)
{
keyPFCTExt0 = Registry.CurrentUser.CreateSubKey("Software\\Classes\\PFCT.file.enc");
keyPFCTExt0.CreateSubKey("DefaultIcon");
RegistryKey keyPFCTExt0ext = Registry.CurrentUser.OpenSubKey("Software\\Classes\\PFCT.file.enc\\DefaultIcon", true);
keyPFCTExt0ext.SetValue("", Application.ExecutablePath +",0");
keyPFCTExt0ext.Close();
keyPFCTExt0.CreateSubKey("Shell\\PFCT_Decrypt\\Command");
}
keyPFCTExt0.SetValue("", "PFCT.file.enc");
keyPFCTExt0.Close();
2.
RegistryKey keyPFCTExt1 = Registry.CurrentUser.OpenSubKey("Software\\Classes\\PFCT.file.enc\\Shell\\PFCT_Decrypt\\Command", true);
if (keyPFCTExt1 == null)
keyPFCTExt1 = Registry.CurrentUser.CreateSubKey("Software\\Classes\\PFCT.file.enc\\Shell\\PFCT_Decrypt\\Command");
keyPFCTExt1.SetValue("", Application.ExecutablePath + " !d %1"); //!d %1 are optional params, here !d string and full file path
keyPFCTExt1.Close();
Я не знаю, почему люди продолжают так говорить HKEY_CURRENT_USER\Software\Classes\<.ext>
Значение по умолчанию (которое перенаправит вас в другой (созданный программным обеспечением) класс.
Это работает, но будет переопределено
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\<.ext>\UserChoice
И я полагаю, что Microsoft рекомендует вторую практику - потому что это то, что делает встроенный "открытый с". Значение Progid
"ключ равен значению по умолчанию HKEY_CURRENT_USER\Software\Classes\<.ext>
в этом случае.
Я нашел следующее при попытке манипулировать ассоциациями с помощью C#:
- hkcu \ software \ microsoft \ windows \ currentVersion \ explorer \ fileexts.reg \ userchoice -> для пользовательских настроек. Значения в ключе openWithProgIds указывают на ключи в hkcr.
- Значение hkcr\xfile\shell\open\muiVerb или hkcr\xfile\shell\open\command\default value -> влияет на открытый обработчик. Это значение, которое содержит путь к программе.
- hkcr \.x -> влияет на контекстное меню (новое x) среди прочего, связанного с меню.
Я не знаю кода C++, но, учитывая эту информацию, вы должны иметь возможность манипулировать реестром с помощью API реестра.