将REG_BINARY读取为String

时间:2012-08-13 09:34:21

标签: winapi registry delphi-7 delphi

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

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;

EDIT2:

使用固定声明的byte / char数组

可以正常工作
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字符,因为我在之前的值中写了一个长文本(带有CR / LF的字符串)。

2 个答案:

答案 0 :(得分:6)

Buffer: array of char;

是chars的动态数组,实际上是指针变量。此字符串将指针重置为Nil:

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

所以动态数组现在无效

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

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

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

答案 1 :(得分:0)

  1. 动态数组就像指针一样。在C / C ++中,它将完全相同。在Delphi中它不是,但你可能会以这种方式思考语义。 @Buffer 不是第一辆车的地址,而是指针本身的地址。 Ib同时调用 FillChar RegQueryValueExW 你应该传递 Buffer [0] @Buffer [0] 而不是< / LI>
  2. 为什么使用Windows API而不是标准TRegistry?或者TNT Unicode控件或某些类似的可能具有现成的unicode感知注册表访问权。
  3. Win API xxxxxxxW 功能可识别unicode。你检查过你的数据了吗?是8位还是16位?将接收到的数据看作HEX中的字节数组 - 它们是否包含$ 00字节?它看起来像是这样,你将unicode数据放入缓冲区。然后,字符串的预期和正确行为只接受1个字母(或0,取决于英特尔或摩托罗拉字节顺序)。检查您在Buffer中获得的二进制数据。
  4. 就个人而言,我将Buffer作为字节数组。然后在注册表访问后我使用 SetString 过程来获取值,如果D7有它。如果没有,那么我会像 SetLength(数据,大小)一样复制它;移动(缓冲区[0],数据[1],大小); 然后我将完全删除FillChar。这样,复制会稍快一些,并且不会在第一个杂散#0字节上中断。
  5. 在进行低级二进制数据类型转换时,我不使用模糊字符和字符串类型,而是使用具体的AnsiString和AnsiChar类型。如果您的代码可以由更新的支持Unicode的Delphi或FreePascal编译,那将使其保持工作。快捷方式“char”和“string”可能会根据编译器版本更改其含义。然后你很难确定它破裂的原因和地点以及做什么。