我的应用程序是用Delphi XE编写的,可以处理PDF文件。 Applicaiton是Win32。一开始,我想确保在PDF文件的资源管理器上下文菜单中有我的项目。我希望能够指定是仅应为活动用户还是为所有用户添加(使用UAC我需要使用管理员权限重新启动,但没关系)。
我从How to associate a Delphi program with a file type, but only for the current user?和How to add item to windows explorer content menu in delphi?开始。我通过regedit手动注册表编辑测试它,它适用于“新”扩展。但对于.pdf来说,它更复杂,因为它很可能已经存在于注册表中。
在我的电脑上,.pdf键引用了AcroExch.Document。但是将shell / something子项添加到AcroExch.Document键是行不通的,因为它具有引用AcroExch.Document.7的CurVer子项。然而,另一台与另一个Acrobat版本的PC有这个名字有点不同。我遵循CurVer参考是没有问题,但这是一个正确的方法吗?那么没有安装PDF阅读器的情况如何,我应该如何命名我的密钥以便Acrobat在安装时不会覆盖它们?
但更紧迫的问题是我应该把根放在哪根? How to associate a Delphi program with a file type, but only for the current user?提及HKLM(本地机器)和HKCU(现有用户)。它似乎相当简单,但我无法在Delphi中设置HKLM的值。奇怪的是我可以创建密钥:
var reg:TRegistry;
key := '\Software\Classes\'+keyname+'\shell\'+name+'\command';
reg.CreateKey(key);
但是在尝试写实际值时我得到拒绝访问:
reg.OpenKey(key,false);
reg.WriteString('',command);
即使在WinXP上我也得到相同的Access Denied异常,无论应用程序是否以Admin(Win7)运行,我甚至尝试通过regedit为密钥设置权限(Everyone完全控制)(我可以编辑该值通过regedit没有问题)。我尝试使用不同的访问模式创建注册表,所有这些都没有运气:
reg := TRegistry.Create(KEY_WRITE or KEY_WOW64_64KEY);
reg := TRegistry.Create(KEY_ALL_ACCESS or KEY_WOW64_64KEY);
reg.Access := KEY_ALL_ACCESS;
reg.Access := KEY_WRITE or KEY_WOW64_64KEY;
reg.Access := KEY_ALL_ACCESS or KEY_WOW64_64KEY;
HKCU一切正常。
所以我尝试写入HKEY_CLASSES_ROOT并且它可以工作,并且如果以Admin身份运行,它实际上将键完全放在我想要的位置(进入HKLM)。但根据http://msdn.microsoft.com/en-us/library/windows/desktop/ms724475.aspx
HKEY_CLASSES_ROOT(HKCR)键包含文件扩展名关联和COM类注册信息,如ProgID,CLSID和IID。它主要用于与16位Windows中的注册表兼容。
我不喜欢有关与16位Windows兼容的主要用途的说明。并且写入更改的实际条件比我想要的更复杂。
基本上我有这些问题:
使用AcroExch.Document和CurVer而不是直接指向AcroExch.Document.7有什么好处?将键添加到此结构中时,“最佳方式”是什么?当.pdf尚未与任何内容相关联时,该怎么办?
我应该把钥匙放在哪里以及为什么我不能写入HKLM?
编辑: 写入HKLM时访问被拒绝的问题是由我的错误引起的。我在之前的代码openKeyReadOnly中使用过,我没有注意到它会将Access属性切换为readonly以用于所有后续调用。
答案 0 :(得分:2)
你问过两个不同的问题。既然我知道一个而不是另一个的答案,我只会回答一个。为了将来参考,我建议您一次提出一个问题。
我应该把钥匙放在哪里?
您确定不应使用HKCR
,这是正确的。 HKCR
的文档说:
类注册和文件扩展名信息存储在 HKEY_LOCAL_MACHINE和HKEY_CURRENT_USER键。该 HKEY_LOCAL_MACHINE \ Software \ Classes键包含默认设置 可以应用于本地计算机上的所有用户。该 HKEY_CURRENT_USER \ Software \ Classes键包含适用的设置 仅限交互式用户。 HKEY_CLASSES_ROOT键提供了一个 合并来自这两者的信息的注册表视图 源。 HKEY_CLASSES_ROOT还提供此合并视图 为以前版本的Windows设计的应用程序。
...
如果您将密钥写入HKEY_CLASSES_ROOT下的密钥,系统将存储 HKEY_LOCAL_MACHINE \ Software \ Classes下的信息。如果你 将值写入HKEY_CLASSES_ROOT下的密钥,并且密钥已经存在 存在于HKEY_CURRENT_USER \ Software \ Classes下,系统将存储 那里的信息而不是 HKEY_LOCAL_MACHINE \ Software \ Classes下。
因此,使用HKCR
进行阅读是合理的,但是对于写作,您通常需要控制是否写入HKLM
或HKCU
。这意味着你无法写信HKCR
。
因此,写入HKLM\Software\Classes
以获取机器范围的设置,并HKCU\Software\Classes
写入用户特定的设置。
请注意,在Windows 7及更高版本中,这些密钥都不是redirected,因此您无需担心使用KEY_WOW64_64KEY
。但是,在Vista和XP64以及等效的服务器版本中,这些键被重定向和反映。这意味着使用KEY_WOW64_64KEY
可能是谨慎的。
答案 1 :(得分:2)
要回答您的其他问题,如果尚未安装Adobe,那么显然注册表中可能不存在PDF密钥,因此您必须创建自己的.pdf和ProgID密钥,以便可以附加Shell命令它。如果之后安装了Adobe,则可能会清除密钥并将其替换为自己的密钥,因此您必须在Adobe的密钥结构中重新创建Shell命令。您的应用程序可以查询注册表以定期检查该条件,例如在启动时。