我尝试使用Delphi中的TRegistry
组件将值写入HKLM注册表。
由于我作为标准用户在Windows 2000上运行(或者作为标准用户使用XP,或者作为标准用户使用Windows Vista,或者使用标准用户运行Windows 7),我完全希望我无法编写到注册表的HKEY_LOCAL_MACHINE
部分:
reg := TRegistry.Create(KEY_WRITE);
try
reg.Access := KEY_WRITE; //sure, set it again, why not
reg.RootKey := HKEY_LOCAL_MACHINE;
if not reg.OpenKey('\Software\Microsoft\SQMClient', True) then
Exit;
reg.WriteString('MachineId', s);
finally
reg.Free;
end;
不幸的是,WriteString
会引发ERegistryException
:
Failed to set data for 'MachineId`
这是完全可以预料到的,这就是我试图避免异常的原因。我在CanWriteString
中看不到任何TryWriteString
或TRegistry
。
尝试写入HKLM时,如何不触发异常?
不言自明的说明:
在try-except中包含对WriteString
的调用:
reg := TRegistry.Create(KEY_WRITE);
try
reg.RootKey := HKEY_LOCAL_MACHINE;
if not reg.OpenKey('\Software\Microsoft\SQMClient', True) then
Exit;
try
reg.WriteString('MachineId', s);
except
on E:ERegistryException do
{nothing};
end;
finally
reg.Free;
end;
不会阻止异常被抛出。
更新:来自RTL来源:
KEY_WRITE = (STANDARD_RIGHTS_WRITE or
KEY_SET_VALUE or
KEY_CREATE_SUB_KEY) and not
SYNCHRONIZE;
来自MSDN:
KEY_WRITE (0x20006)
结合STANDARD_RIGHTS_WRITE,KEY_SET_VALUE和KEY_CREATE_SUB_KEY访问权限。
答案 0 :(得分:4)
你不能让TRegistry
按照你想要的方式行事。没有TryXXX
方法,也没有禁用异常的参数。您可以确定这是因为TRegistry
方法不提供任何错误或状态代码。
您必须围绕Win32注册表API编写自己的包装器。
顺便说一句,我同意你在评论中表达的意见,TRegistry
在这里缺乏功能。我们希望注册表操作失败,因此我们不应该捕获异常来处理它。
答案 1 :(得分:1)
打开密钥时使用KEY_SET_VALUE
代替KEY_WRITE
,因为KEY_WRITE
包含其他权限。 OpenKey()
成功的事实意味着您的标准用户帐户具有某些权限,因此允许打开密钥,但密钥在您执行此操作之前并不确切知道您要对其执行的操作,因此,如果您不使用它们,它实际上无法事先验证所有权限。如果您仅使用KEY_SET_VALUE
(这是您在示例中真正需要的),如果您的用户帐户没有任何权限将数据写入密钥,则OpenKey()
更有可能立即失败。在访问安全资源时,请始终只请求您实际需要的最低权限。