Delphi 导出 HKEY_CURRENT_USER 密钥无效 - 结果文件为空

Delphi export HKEY_CURRENT_USER key not working - empty result file

我正在尝试使用 TRegistry.SaveKey 或 RegSaveKey 函数导出注册表项,但没有成功。我得到的只是一个 0 字节的空文件。我在网上看到例子 none 似乎正在 Windows10.

  reg := TRegistry.Create;

  reg.RootKey := HKEY_CURRENT_USER;
  reg.Access := KEY_ALL_ACCESS;

  if reg.OpenKey('\Software\MyCompanyName\MyApplication\', True) then
  begin
    reg.WriteInteger('background', Self.Color);

    reg.SaveKey('HKEY_CURRENT_USER\Software\MyCompanyName\MyApplication', 'test.txt'); //not working
    RegSaveKey(reg.CurrentKey, 'test.reg', nil); //creates empty file
  end;
  reg.CloseKey;
  reg.Free;

此外,如果我从 RegEdit 中提取现有密钥,然后尝试使用 TRegistry.LoadKey 或 RegLoadKey 将其加载到应用程序中,则没有任何反应

我在 运行 这台机器上确实有管理员权限。

有人熟悉这个问题吗?

来自 RegSaveKey 的文档:

The calling process must have the SE_BACKUP_NAME privilege enabled.

我的猜测是 RegSaveKey 返回了一个不同于 ERROR_SUCCESS 的值。你的代码没有检查。

另请参阅:

RegSaveKey returns ERROR_PRIVILEGE_NOT_HELD

另一件要检查的事情是在你尝试保存之前目标文件不存在,否则函数将失败(这在文档中也有提到),显然你对该文件有写权限位置。

这是一个工作示例。 请注意,您必须 运行 程序 作为管理员

program SO59753973;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  Registry,
  Windows,
  System.SysUtils;



function NTSetPrivilege(sPrivilege: string; bEnabled: Boolean): Boolean;

var
 hToken: THandle;
 TokenPriv: TOKEN_PRIVILEGES;
 PrevTokenPriv: TOKEN_PRIVILEGES;
 ReturnLength: Cardinal;
 errval:Cardinal;
begin
 Result := True;
 errval:=0;
 // Only for Windows NT/2000/XP and later.
 if not (Win32Platform = VER_PLATFORM_WIN32_NT) then Exit;
 Result := False;
 // obtain the processes token
 if OpenProcessToken(GetCurrentProcess(),
 TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken) then
  try
  // Get the locally unique identifier (LUID) .
  if LookupPrivilegeValue(nil, PChar(sPrivilege),TokenPriv.Privileges[0].Luid) then
  begin
   TokenPriv.PrivilegeCount := 1; // one privilege to set
   case bEnabled of
    True: TokenPriv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
    False: TokenPriv.Privileges[0].Attributes := 0;
   end;

  ReturnLength := 0; // replaces a var parameter
  PrevTokenPriv := TokenPriv;
   // enable or disable the privilege
  if AdjustTokenPrivileges(hToken, False, TokenPriv, SizeOf(PrevTokenPriv),PrevTokenPriv, ReturnLength) then
   Result := True
  else
   begin
    errval:= GetLastError;
    Result := errval = 0;
   end;
  end;
 finally
  CloseHandle(hToken);
 end;
 // test the return value of AdjustTokenPrivileges.
 //Result := GetLastError = ERROR_SUCCESS;
 if not Result then
 raise Exception.Create(SysErrorMessage(errval));
end;

var
  Reg: TRegistry;
  sKeyFileName: String;

begin
 try
  if not NTSetPrivilege('SeBackupPrivilege',true) then
    Exit;
  sKeyFileName := 'C:\temp\tempReg.reg';
  if FileExists(sKeyFileName) then
    DeleteFile(sKeyFileName);
  Reg := TRegistry.Create(KEY_ALL_ACCESS);
   try
    Reg.RootKey := HKEY_CURRENT_USER;
    if Reg.SaveKey('\Software\Microsoft', sKeyFileName)
    then
     Writeln('Registry has been saved!')
    else
     Writeln('Failed to save registry, received error: ' + IntToStr(Reg.LastError) + '!');
   finally
    Reg.Free;
   end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
 Readln;
end.

要恢复注册表,除了 SE_BACKUP_NAME 权限外,您还必须启用 SE_RESTORE_NAME

代码已从 this old forum post

中获取(并改编)