1

I am trying to get the reg_binary as string from a registry key.

This is my function

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;

and here is my registry key Export :

 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

the problem is , the function returns empty string

I even tried running as administrator to make sure that it is not permissions.

Any help ?

2
  • 2
    Don't use KEY_WRITE. Remove that. Use OpenKeyReadOnly. Stop using GetDataAsString. Use GetData instead and then TEncoding to decode the ANSI byte array Commented Feb 23, 2016 at 13:12
  • 1
    For the record, you should also get in the habit of debugging. Commented Feb 23, 2016 at 13:21

2 Answers 2

5

Expanding on my comment to the question, I'd use code like so:

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;

For your data you would call it like so:

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

Notes:

  • I have avoided hard-coding the root key.
  • I have used TEncoding to decode the byte array to text. This is far more effective than GetDataAsString.
  • I have allowed the caller to specify the encoding to be used.
  • I have allowed the caller to specify the access flags.
  • I have used OpenKeyReadOnly because we do not require write access.
Sign up to request clarification or add additional context in comments.

Comments

0

Thanks to David Heffernan I came with this solution:

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;

Thanks to David Heffernan again ... this worked for me :

    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;

2 Comments

GetDataAsString() is designed to return the raw bytes as a hex-encoded comma-delimited string. You are decoding that back to the raw bytes and then converting those values as-is into string characters. To simplify that, you really should be using ReadBinaryData() instead to read the raw bytes directly, and then you can convert those to a String using TEncoding.GetString(). Like DavidHeffernan showed you.
Now, KEY_READ is needless, there is potential for leaking, i.e. Free might not be called, the CloseKey call is needless. I'm not sure what this adds beyond my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.