Delphi写入注册表失败:IE插件中OpenKey(true)无法创建键返回false
嘿,这个坑我之前踩过!OpenKey传了true却没创建注册表项还返回false,大概率是这几个原因,咱们一个个排查:
1. 权限不够是头号嫌疑
IE相关的系统级注册表项(比如HKLM\Software\Microsoft\Internet Explorer这类)需要管理员权限才能修改。如果你的插件是在普通用户权限下运行的,就算你传了创建参数,系统也会直接拒绝写操作,返回false。
试试右键以管理员身份启动IE(或者你的插件宿主程序),再执行操作,看能不能成功创建项。
2. 64位系统的注册表重定向坑
如果你的系统是64位,而插件是32位的,Windows会自动把注册表访问重定向到Wow6432Node分支。比如你想操作HKLM\Software\Microsoft\Internet Explorer,32位插件实际访问的是HKLM\Software\Wow6432Node\Microsoft\Internet Explorer——可能你在注册表编辑器里找错地方了,以为没创建,其实已经在重定向路径里了。
如果要强制访问64位注册表分支,需要在OpenKey时指定额外的标志,比如在C#里要加上RegistryView.Registry64参数:
using (var key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64) .OpenSubKey(@"Software\Microsoft\Internet Explorer", true)) { // 后续操作 }
3. OpenKey的权限参数没给全
有些语言的OpenKey API默认权限是只读的,就算你传了true(可写),如果没明确指定创建子项的权限,也会失败。比如C#的OpenSubKey方法,第三个参数要包含RegistryRights.CreateSubKey和RegistryRights.SetValue:
using (var key = Registry.LocalMachine.OpenSubKey( @"Software\Microsoft\Internet Explorer", RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.CreateSubKey | RegistryRights.SetValue)) { if (key != null) { key.SetValue("YourCustomValue", "TestValue", RegistryValueKind.String); } }
4. 查错误码精准定位
如果上面的方法都没用,直接拿系统错误码说话!调用OpenKey失败后,用Marshal.GetLastWin32Error()(C#)或者对应语言的错误获取方法,拿到具体错误码:
- 错误码5(ERROR_ACCESS_DENIED):肯定是权限问题;
- 错误码2(ERROR_FILE_NOT_FOUND):可能路径里的父项都不存在,或者重定向导致路径不对;
- 其他错误码可以查Win32错误对照表,快速定位问题。
内容的提问来源于stack exchange,提问作者Brian

