创建注册表项以将文件扩展名与 C++ 中的应用程序相关联
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1387769/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Create registry entry to associate file extension with application in C++
提问by Seth
I would like to know the cleanest way of registering a file extension with my C++ application so that when a data file associated with my program is double clicked, the application is opened and the filename is passed as a parameter to the application.
我想知道用我的 C++ 应用程序注册文件扩展名的最干净的方法,这样当与我的程序关联的数据文件被双击时,应用程序被打开,文件名作为参数传递给应用程序。
Currently, I do this through my wix installer, but there are some instances where the application will not be installed on ths user's computer, so I also need the option of creating the registry key through the application.
目前,我通过我的 wix 安装程序执行此操作,但在某些情况下,该应用程序不会安装在用户的计算机上,因此我还需要通过该应用程序创建注册表项的选项。
Additionally, will this also mean that if the application is removed, unused entries in the registry will be left lying around?
此外,这是否也意味着如果应用程序被删除,注册表中未使用的条目将被留下?
回答by Factor Mystic
Your basic overview of the process is found in this MSDN article. The key parts are at the bottom of the list:
您可以在这篇 MSDN 文章中找到该过程的基本概述。关键部分位于列表底部:
- Register the ProgID
- 注册 ProgID
A ProgID (essentially, the file type registry key) is what contains your important file type properties, such as icon, description, and context menu items including application used when the file is double clicked. Many extensions may have the same file type. That mapping is done in the next step:
ProgID(本质上是文件类型注册表项)包含重要的文件类型属性,例如图标、描述和上下文菜单项,包括双击文件时使用的应用程序。许多扩展名可能具有相同的文件类型。该映射在下一步中完成:
- Register the file name extension for the file type
- 注册文件类型的文件扩展名
Here, you set a registry value for your extension, setting that extension's file type to the ProgID you created in the previous step.
在这里,您为扩展设置了一个注册表值,将该扩展的文件类型设置为您在上一步中创建的 ProgID。
The minimum amount of work required to get a file to open with your application is setting/creating two registry keys. In this example .reg
file, I create an file type (blergcorp.blergapp.v1
) and association a file extension (.blerg
) with it.
使用应用程序打开文件所需的最少工作是设置/创建两个注册表项。在此示例.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"
Now, you probably want to accomplish this programmatically. To be absolutely kosher, you could check for the existence of these keys, and change your program behavior accordingly, especiallyif you're assuming control of some common file extension. However, the goal can be accomplished by setting those two keys using the SetValue function.
现在,您可能希望以编程方式完成此操作。为了绝对的犹太洁食,您可以检查这些键是否存在,并相应地更改您的程序行为,尤其是在您控制某些常见文件扩展名的情况下。但是,可以通过使用 SetValue 函数设置这两个键来实现目标。
I'm not positive of the exact C++ syntax, but in C# the syntax looks something like this:
我对确切的 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");
Of course you could manually open each sub key, manually create the ProgID and extension subkey, and thenset the key value, but a nice thing about the SetValue
function is that if the keys or values don't exist, they will automatically be created. Very handy.
当然你可以手动打开每个子键,手动创建ProgID和扩展子键,然后设置键值,但是这个SetValue
功能的一个好处是,如果键或值不存在,它们会自动创建。非常便利。
Now, a quick word about which hive to use. Many file association examples online, including ones on MSDN, show these keys being set in HKEY_CLASSES_ROOT
. I don't recommend doing this. That hive is a merged, virtual view of HKEY_LOCAL_MACHINE\Software\Classes
(the system defaults) and HKEY_CURRENT_USER\Software\Classes
(the per-user settings), and writes to any subkey in the hive are redirected to the same key in HKEY_LOCAL_MACHINE\Software\Classes
. Now, there's no direct problem doing this, but you may run into this issue: If you write to HKCR (redirected to HKLM), and the user has specified the same keys with different values in HKCU, the HKCU values will take precedence. Therefore, your writes will succeed but you won't see any change, because HKEY_CURRENT_USER
settings take precedence over HKEY_LOCAL_MACHINE
settings.
现在,简要介绍一下使用哪个蜂巢。许多在线文件关联示例,包括 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
设置。
Therefore, you should take this into consideration when designing your application. Now, on the flip side you can write to only HKEY_CURRENT_USER
, as my examples here show. However, that file association setting will only be loaded for the current user, and if your application has been installed for all users, your application won't launch when that other user opens the file in Windows.
因此,您在设计应用程序时应该考虑到这一点。现在,另一方面,您只能写入HKEY_CURRENT_USER
,正如我在此处的示例所示。但是,该文件关联设置只会为当前用户加载,如果您的应用程序已为所有用户安装,当其他用户在 Windows 中打开文件时,您的应用程序将不会启动。
That should be a decent primer for what you want to do. For further reading I suggest
对于您想要做的事情,这应该是一本不错的入门书。为了进一步阅读,我建议
- Best Practices for File Association
- File Types and File Association, especially
- How File Associations Work
And see also my similar answer to a similar question:
另请参阅我对类似问题的类似回答:
回答by fireattack
I don't know why people keep saying that HKEY_CURRENT_USER\Software\Classes\<.ext>
's Default value (which will redirect you into another (software-created) class.
我不知道为什么人们一直说这HKEY_CURRENT_USER\Software\Classes\<.ext>
是默认值(这会将您重定向到另一个(软件创建的)类。
It does work, but it will be overridden by
它确实有效,但会被覆盖
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\<.ext>\UserChoice
And I believe Microsoft recommends the second practice- because it's what the built-in "open with" is doing. The value of Progid
" key is equal to default value of HKEY_CURRENT_USER\Software\Classes\<.ext>
in this case.
我相信微软推荐第二种做法——因为这是内置的“开放方式”正在做的。在这种情况下,Progid
" 键的值等于默认值HKEY_CURRENT_USER\Software\Classes\<.ext>
。
回答by beermann
This is a two step process:
这是一个两步过程:
1. Define a program that would take care of extension: (unless you want to use existing one) 1.1 create a key in "HKCU\Software\Classes\" for example "Software\Classes\YourProgramName.file.ext" 1.2 create subkey "Software\Classes\YourProgramName.file.ext\DefaultIcon" 1.2.1 set default value ("") to your application full path to get icon from resources 1.3 create a subkey "Software\Classes\YourProgramName.file.ext\Shell\OperationName\Command" OperationName = for example Open, Print or Other 1.3.1 set default value ("") to your application full path +optional runtime params (filename) 2.Associate file extension with program. 2.1 create a key HKCU\Software\Classes\.ext - here goes your extension 2.2 set default value to the program definition key ("YourProgramName.file.ext")
Below is part of the program written in c# which associate file extension. It is not c++ but i think it is simple enought to explain itself and AFAIK it is verv simmilar if not identical to the code in c++
下面是用 c# 编写的程序的一部分,它关联了文件扩展名。它不是 C++,但我认为它很简单,可以解释自己,AFAIK 如果与 C++ 中的代码不相同,它就是 verv simmilar
1.
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.
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();
回答by Meghdad
I found the following while trying to manipulate associations using C#:
我在尝试使用 C# 操作关联时发现以下内容:
- hkcu\software\microsoft\windows\currentVersion\explorer\fileexts.reg\userchoice -> for user specific settings. The values in the openWithProgIds key point to the keys in the hkcr.
- hkcr\xfile\shell\open\muiVerb value or hkcr\xfile\shell\open\command\default value -> affects open handler. This is the value that contains the path to a program.
- hkcr\ .x -> affects context menu (new x) among other things related to the menus.
- hkcu\software\microsoft\windows\currentVersion\explorer\fileexts.reg\userchoice -> 用于用户特定设置。openWithProgIds 键中的值指向 hkcr 中的键。
- hkcr\xfile\shell\open\muiVerb 值或 hkcr\xfile\shell\open\command\default 值 -> 影响打开处理程序。这是包含程序路径的值。
- hkcr\ .x -> 影响上下文菜单(新 x)以及与菜单相关的其他内容。
I don't know the C++ code, but given these info you must be able to manipulate the registry using the registry API.
我不知道 C++ 代码,但鉴于这些信息,您必须能够使用注册表 API 操作注册表。