【问题标题】:Read REG_BINARY to String将 REG_BINARY 读入字符串
【发布时间】:2012-08-13 09:34:21
【问题描述】:

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

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:

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

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 的字符串)。

【问题讨论】:

  • 如果您在Data := String(Buffer) 赋值上设置了一个调试断点,然后查看Buffer,它实际上是什么?
  • 看起来我什至无法访问它。但我认为它的#0。如果我尝试这样的事情,我会遇到很多访问冲突: if buffer[0] = '' then messagebox (0, 'ERROR', '', 0);
  • 编辑:我得到 000000 消息框 (0, pchar(Format('%8p', [@buffer[0]])), '', 0);

标签: winapi registry delphi-7 delphi


【解决方案1】:
Buffer: array of char;

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

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

所以动态数组现在无效

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

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

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

【讨论】:

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

【讨论】:

  • -1。虽然其中大部分都是很好的信息,但它并不能回答这里提出的问题。
  • @KenWhite:他在这里有一些有效的观点(恕我直言,他仍然服用太多药物)......
  • @whosrdaddy,我是这么说的。但是,关键仍然是,就提供解决方案而言,没有一件事可以解决这个问题。 (完全没有提到导致buffer为零的FillChar的不当使用。)
  • "made buffer nil" 似乎过于简单化了。看看那个 显示空字符或有时 1 个随机字符。 备注。如果缓冲区只是 nilled,为什么会有一个字符?
猜你喜欢
  • 2020-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-25
相关资源
最近更新 更多