【问题标题】:Read reg_binary as string using Tregistry Class in delphi在 delphi 中使用 Tregistry 类将 reg_binary 读取为字符串
【发布时间】:2016-02-23 13:04:46
【问题描述】:

我正在尝试将 reg_binary 作为字符串从注册表项中获取。

这是我的功能

function ReadBinString(key: string; AttrName: string): string;
var
 ReadStr: TRegistry;

begin
// Result := '';
ReadStr := TRegistry.Create(KEY_WRITE OR KEY_WOW64_64KEY);
ReadStr.RootKey := HKEY_LOCAL_MACHINE;

   if ReadStr.OpenKey(key, true) then
begin

  Result := ReadStr.GetDataAsString(AttrName);
end;

ReadStr.CloseKey;
ReadStr.Free;
end;

这是我的注册表项导出:

 Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\ZES\ACINFO]
"iamthere"=dword:00000001
"ArrayOrder"=hex:4d,79,45,78,63,6c,75,64,65

问题是,函数返回空字符串

我什至尝试以管理员身份运行以确保它不是权限。

有什么帮助吗?

【问题讨论】:

  • 不要使用KEY_WRITE。删除它。使用OpenKeyReadOnly。停止使用GetDataAsString。改为使用GetData,然后使用TEncoding 解码ANSI 字节数组
  • 为了记录,你也应该养成调试的习惯。

标签: delphi registry


【解决方案1】:

扩展我对该问题的评论,我会使用如下代码:

function ReadBinString(RootKey: HKEY; Access: LongWord; const KeyName,
  ValueName: string; Encoding: TEncoding): string;
var
  Registry: TRegistry;
  Bytes: TBytes;
begin
  Registry := TRegistry.Create(Access);
  try
    Registry.RootKey := RootKey;
    if Registry.OpenKeyReadOnly(KeyName) then begin
      SetLength(Bytes, Registry.GetDataSize(ValueName));
      Registry.ReadBinaryData(ValueName, Pointer(Bytes)^, Length(Bytes));
      Result := Encoding.GetString(Bytes);
    end else begin
      Result := '';
    end;
  finally
    Registry.Free;
  end;
end;

对于您的数据,您可以这样称呼它:

Value := ReadBinString(HKEY_LOCAL_MACHINE, KEY_WOW64_64KEY, 'Software\ZES\ACINFO', 
  'ArrayOrder', TEncoding.ANSI);

注意事项:

  • 我避免对根密钥进行硬编码。
  • 我使用TEncoding 将字节数组解码为文本。这比GetDataAsString 有效得多。
  • 我已允许调用者指定要使用的编码。
  • 我已允许调用者指定访问标志。
  • 我使用了OpenKeyReadOnly,因为我们不需要写权限。

【讨论】:

    【解决方案2】:

    感谢 David Heffernan,我提出了这个解决方案:

    function ReadBinString(key: string; AttrName: string): string;
    var
    ReadStr: TRegistry;
    hexStr : string;
    I : Integer;
    begin
    // Result := '';
     ReadStr := TRegistry.Create(KEY_READ OR KEY_WOW64_64KEY);
     ReadStr.RootKey := HKEY_LOCAL_MACHINE;
    
     if ReadStr.OpenKey(key, true) then
     begin
    
    hexStr := ReadStr.GetDataAsString(AttrName);
    
    hexStr := hexStr.Replace(',','');
    for I := 1 to length (hexStr) div 2 do
    Result:= Result+Char(StrToInt('$'+Copy(hexStr,(I-1)*2+1,2)));
    
    end;
    
    ReadStr.CloseKey;
    ReadStr.Free;
    end;
    

    再次感谢 David Heffernan ...这对我有用:

        function ReadBinString(key: string; AttrName: string): string;
        var
          ReadStr: TRegistry;
          hexStr: string;
          I: Integer;
          Bytes: TBytes;
          Encoding: TEncoding;
        begin
    
          Encoding :=  TEncoding.ANSI;
    
          Result := '';
          ReadStr := TRegistry.Create(KEY_READ OR KEY_WOW64_64KEY);
          ReadStr.RootKey := HKEY_LOCAL_MACHINE;
          try
    
            if ReadStr.OpenKeyReadOnly(key ) then
            begin
    
              SetLength(Bytes, ReadStr.GetDataSize(AttrName));
              ReadStr.ReadBinaryData(AttrName, Pointer(Bytes)^, Length(Bytes));
              Result := Encoding.GetString(Bytes);
    
              // hexStr := ReadStr.GetDataAsString(AttrName);
              //
              // hexStr := hexStr.Replace(',','');
              // for I := 1 to length (hexStr) div 2 do
              // Result:= Result+Char(StrToInt('$'+Copy(hexStr,(I-1)*2+1,2)));
    
            end;
    
          except
    
          end;
          ReadStr.CloseKey;
          ReadStr.Free;
        end;
    

    【讨论】:

    • GetDataAsString() 旨在将原始字节作为十六进制编码的逗号分隔字符串返回。您将其解码回原始字节,然后将这些值按原样转换为字符串字符。为了简化这一点,您确实应该使用ReadBinaryData() 来直接读取原始字节,然后您可以使用TEncoding.GetString() 将它们转换为字符串。就像大卫赫弗南向你展示的那样。
    • 现在,KEY_READ 是不必要的,有泄漏的可能性,即Free 可能不会被调用,CloseKey 调用是不必要的。我不确定这超出了我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-03
    • 1970-01-01
    • 2021-08-18
    • 2016-11-04
    • 1970-01-01
    • 1970-01-01
    • 2013-06-04
    相关资源
    最近更新 更多