2

我使用此代码将二进制数据从注册表读取到字符串

function ReadBinary (RootKey: HKEY; SubKey,ValueName: WideString; var Data : String): Bool;
var
  Key     : HKey;
  Buffer  : array of char;
  Size    : Cardinal;
  RegType : DWORD;
begin
  result  := FALSE;
  RegType := REG_BINARY;
  if RegOpenKeyExW(RootKey, pwidechar(SubKey), 0, KEY_READ, Key) = ERROR_SUCCESS then begin
    if RegQueryValueExW(Key,pwidechar(ValueName),NIL,@RegType, NIL,@Size) = ERROR_SUCCESS then begin
      SetLength (Buffer, Size + 1);
      FillChar(Buffer, SizeOf (Buffer), #0);
      if RegQueryValueExW(Key,pwidechar(ValueName),NIL,@RegType, @Buffer[0],@Size) = ERROR_SUCCESS then begin
        result := TRUE;
        Data := String (Buffer); // Shows empty or sometimes 1 random char.
      end;
    end;        
  end;
  RegCloseKey (Key);
end;

编辑2:

它适用于固定声明的字节/字符数组

function ReadBinary (RootKey: HKEY; SubKey,ValueName: WideString; var Data : String): Bool;
var
  Key     : HKey;
  Buffer  : array [0..200] of char;
  Size    : Cardinal;
  RegType : DWORD;
begin
  result  := FALSE;
  RegType := REG_BINARY;
  if RegOpenKeyExW(RootKey, pwidechar(SubKey), 0, KEY_READ, Key) = ERROR_SUCCESS then begin
    if RegQueryValueExW(Key,pwidechar(ValueName),NIL,@RegType, NIL,@Size) = ERROR_SUCCESS then begin
      FillChar(Buffer, SizeOf (Buffer), #0);
      if RegQueryValueExW(Key,pwidechar(ValueName),NIL,@RegType, @Buffer,@Size) = ERROR_SUCCESS then begin
        result := TRUE;
        Data   := String (Buffer);
      end;
    end;        
  end;
  RegCloseKey (Key);
end;

我被困住了。我做错了什么,解决方案是什么?

谢谢您的帮助。

编辑:

我知道我正在从注册表中读取二进制数据。所以它可能已经 0 终止并且可以返回错误的结果。我可以保证二进制数据中没有 #0 字符,因为我之前在 Value 中写了一个长文本(带有 CR/LF 的字符串)。

4

2 回答 2

6
Buffer: array of char;

是chars的动态数组,其实就是指针变量。这个字符串将指针重置为 Nil:

   FillChar(Buffer, SizeOf (Buffer), #0);

所以动态数组现在无效

要用零填充动态数组的内容,您必须使用

    FillChar(Buffer[0], SizeOf(Buffer[0]) * Length(Buffer), #0)

但这不是必需的,因为 SetLength 完成了这项工作。

于 2012-08-13T11:31:35.077 回答
0
  1. 动态数组类似于指针。在 C/C++ 中它是完全一样的。在 Delphi 中它不是,但你可能会为语义这样认为。@Buffer不是第一辆车的地址,而是指针本身的地址。Ib 对FillCharRegQueryValueExW的调用都应该传递Buffer[0]@Buffer[0 ]
  2. 为什么你使用 Windows API 而不是标准的 TRegistry ?或者也许 TNT Unicode Controls 或类似的东西有现成的 unicode-aware 注册表访问。
  3. Win API xxxxxxxW函数支持 unicode。你检查过你得到了什么数据吗?它是 8 位还是 16 位?将接收到的数据视为 HEX 中的字节数组 - 它们是否包含 $00 字节?看起来他们这样做了,并且您将 unicode 数据放入缓冲区。然后,字符串的预期和正确行为将只接受 1 个字母(或 0,取决于英特尔或摩托罗拉字节顺序)。检查 Buffer 中有哪些二进制数据。
  4. 就个人而言,我将 Buffer 制作为字节数组。然后在注册表访问之后,如果 D7 有它,我会使用SetString过程来获取值。如果没有,那么我会像SetLength(Data, Size);一样复制它。移动(缓冲区[0],数据[1],大小);我会完全删除 FillChar。这种方式复制会稍微快一点,并且不会在第一个杂散#0字节上中断。
  5. 在进行低级二进制数据类型转换时,我不会使用模棱两可的 char 和 string 类型,而是使用具体的 AnsiString 和 AnsiChar 类型。如果您的代码有时会由支持 Unicode 的新 Delphi 或 FreePascal 编译,那将使其继续工作。快捷键“char”和“string”可能会根据编译器版本改变它们的含义。然后你就很难确定它为什么坏了,在哪里坏了,怎么办。
于 2012-08-13T11:50:30.403 回答