Mega Code Archive

 
Categories / Delphi / System
 

How to read a REG_MULTI_SZ value From the Registry

Title: How to read a REG_MULTI_SZ value From the Registry uses Registry; procedure ReadREG_MULTI_SZ(const CurrentKey: HKey; const Subkey, ValueName: string; Strings: TStrings); var valueType: DWORD; valueLen: DWORD; p, buffer: PChar; key: HKEY; begin // Clear TStrings Strings.Clear; // open the specified key if RegOpenKeyEx(CurrentKey, PChar(Subkey), 0, KEY_READ, key) = ERROR_SUCCESS then begin // retrieve the type and data for a specified value name SetLastError(RegQueryValueEx(key, PChar(ValueName), nil, @valueType, nil, @valueLen)); if GetLastError = ERROR_SUCCESS then if valueType = REG_MULTI_SZ then begin GetMem(buffer, valueLen); try // receive the value's data (in an array). RegQueryValueEx(key, PChar(ValueName), nil, nil, PBYTE(buffer), @valueLen); // Add values to stringlist p := buffer; while p^ #0 do begin Strings.Add(p); Inc(p, lstrlen(p) + 1) end finally FreeMem(buffer) end end else raise ERegistryException.Create('Stringlist expected/ ') else raise ERegistryException.Create('Cannot Read MULTI_SZ Value'); end; end; Usage Examples: Nr1. by Ralph Friedman procedure TForm1.Button1Click(Sender: TObject); begin ReadREG_MULTI_SZ(HKEY_CURRENT_USER, 'Software\XYZ', 'Test44', Memo1.Lines); end; Question: I want to read out the binary-value "problems" of the path HKEY_DYN_DATA\Config Manager\Enum\[add the key of a hardware component] to detect if a hardware component is troubled and not working right. But I cannot handle the ReadBinaryData-Method of TRegistry correct. Everytime I use it, it always returns "4" as content of the buffer. How do I detect if the content of the binary-key "problems" is not "00 00 00 00" but something else like "16 00 00 00" or such? Answer: Here's an example of ReadBinaryData procedure TFrmReadBinary.Button1Click(Sender: TObject); const CKeyName: string = 'System\Setup'; CValName: string = 'NetcardDlls'; var keyGood: boolean; p: integer; regKey: TRegistry; tmpStr: string; vSize: integer; begin regKey := TRegistry.Create; try regKey.RootKey := HKEY_LOCAL_MACHINE; keyGood := regKey.OpenKey(CKeyName, False); if (keyGood) then begin vSize := regKey.GetDataSize(CValName); if (vSize 0) then begin SetLength(tmpStr, vSize); regKey.ReadBinaryData(CValName, tmpstr[1], vSize); repeat p := Pos(#0, tmpStr); if p 0 then begin Delete(tmpStr, p, 1); Insert(#13#10, tmpStr, p); end; until p = 0; (*StringReplace(tmpStr, #0, #13#10, [rfReplaceAll]); *) ListBox1.Items.Text := tmpStr; end; end; finally regKey.Free; end; end; Nr2. by Michael Winter procedure RaiseWin32Error(Code: Cardinal); var Error: EWin32Error; begin Error := EWin32Error.CreateResFmt(@SWin32Error, [Code, SysErrorMessage(Code)]); Error.ErrorCode := Code; raise Error; end; // Write REG_MULTI_SZ procedure TForm1.Button1Click(Sender: TObject); const Str = 'multiple'#0'strings'#0'in one'#0'registry'#0'value'#0; var Reg: TRegistry; Res: Integer; begin Reg := TRegistry.Create; try Reg.RootKey := HKEY_CURRENT_USER; if not Reg.OpenKey('\Software\Test\RegMultiSzTest', true) then raise Exception.Create('Can''t open key'); Res := RegSetValueEx( Reg.CurrentKey, // handle of key to set value for 'TestValue', // address of value to set 0, // reserved REG_MULTI_SZ, // flag for value type PChar(Str), // address of value data Length(Str) + 1); // size of value data if Res ERROR_SUCCESS then RaiseWin32Error(Res); finally Reg.Free; end; end; // Read REG_MULTI_SZ procedure TForm1.Button2Click(Sender: TObject); var Reg: TRegistry; DataType: Cardinal; DataSize: Cardinal; Res: Integer; Str: String; i: Integer; begin Reg := TRegistry.Create; try Reg.RootKey := HKEY_CURRENT_USER; if not Reg.OpenKeyReadOnly('\Software\Test\RegMultiSzTest') then raise Exception.Create('Can''t open key'); DataSize := 0; Res := RegQueryValueEx( Reg.CurrentKey, // handle of key to query 'TestValue', // address of name of value to query nil, // reserved @DataType, // address of buffer for value type nil, // address of data buffer @DataSize); // address of data buffer size if Res ERROR_SUCCESS then RaiseWin32Error(Res); if DataType REG_MULTI_SZ then raise Exception.Create('Wrong data type'); SetLength(Str, DataSize - 1); if DataSize 1 then begin Res := RegQueryValueEx( Reg.CurrentKey, // handle of key to query 'TestValue', // address of name of value to query nil, // reserved @DataType, // address of buffer for value type PByte(Str), // address of data buffer @DataSize); // address of data buffer size if Res ERROR_SUCCESS then RaiseWin32Error(Res); end; for i := Length(Str) downto 1 do if Str[i] = #0 then Str[i] := #13; ShowMessage(Str); finally Reg.Free; end; end;