尝试在标准用户上写入HKLM时如何不触发异常?

Ian*_*oyd 5 delphi security registry uac

试图使用TRegistryDelphi中的组件将值写入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;
Run Code Online (Sandbox Code Playgroud)

不幸的是,WriteString抛出一个ERegistryException:

Failed to set data for 'MachineId`
Run Code Online (Sandbox Code Playgroud)

这是完全可以预料到的,这就是我试图避免异常的原因.我没有看到任何CanWriteStringTryWriteStringTRegistry.

我怎么能试图写入HKLM时触发异常?


不言而喻的笔记:

  • 如果用户实际上是管理员,则写入应该能够成功
  • 将调用包装WriteString在try-except中:

    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;
    
    Run Code Online (Sandbox Code Playgroud)

    不会阻止异常被抛出.

更新:来自RTL源:

KEY_WRITE          = (STANDARD_RIGHTS_WRITE or
                        KEY_SET_VALUE or
                        KEY_CREATE_SUB_KEY) and not
                        SYNCHRONIZE;
Run Code Online (Sandbox Code Playgroud)

来自MSDN:

KEY_WRITE (0x20006)  
Run Code Online (Sandbox Code Playgroud)

结合STANDARD_RIGHTS_WRITE,KEY_SET_VALUE和KEY_CREATE_SUB_KEY访问权限.

Dav*_*nan 4

你无法按照TRegistry自己想要的方式行事。没有TryXXX禁用异常的方法和参数。您可以确定确实如此,因为这些TRegistry方法不提供任何错误或状态代码。

您必须围绕 Win32 注册表 API 编写自己的包装器。

顺便说一句,我同意你在评论中表达的观点,即TRegistry这里缺乏功能。我们预计注册表操作会失败,因此我们不必捕获异常来处理该问题。