Registry ReadString method does not work on Windows 7 in Delphi 7

The following code sample is used to return the window id earlier, but now it doesn’t work and returns an empty string, I don’t know why.

function GetWindowsID: string; var Registry: TRegistry; str:string; begin Registry := TRegistry.Create(KEY_WRITE); try Registry.Lazywrite := false; Registry.RootKey := HKEY_LOCAL_MACHINE; // Registry.RootKey := HKEY_CURRENT_USER; if CheckForWinNT = true then Begin if not Registry.OpenKeyReadOnly('\Software\Microsoft\Windows NT\CurrentVersion') then showmessagE('cant open'); end else Registry.OpenKeyReadOnly('\Software\Microsoft\Windows\CurrentVersion'); str := Registry.ReadString('ProductId'); result:=str; Registry.CloseKey; finally Registry.Free; end; // try..finally end; 

Can anybody help?

+6
windows-7 delphi registry windows-identity
source share
6 answers

This is because the virtualized key "\ Software \ Wow6432Node \ Microsoft \ Windows NT \ CurrentVersion" does not contain the element "ProductID".

Modify your code to instantiate TRegistry with

 Registry := TRegistry.Create(KEY_WRITE OR KEY_WOW64_64KEY); 

where KEY_WOW64_64KEY = $ 0100. This will give you the expected result.

Alternatively use DSiWin32 and call

 DSiReadRegistry('\Software\Microsoft\Windows NT\CurrentVersion', 'ProductID', '', HKEY_LOCAL_MACHINE, KEY_QUERY_VALUE OR KEY_WOW64_64KEY); 
+23
source share

There is a useful procedure for reading the key register in a 32-bit and 64-bit environment. First look at your system.

 Type TTypWin32Or64 = (Bit32,Bit64); var TypWin32Or64 :TTypWin32Or64; Procedure TypeOS(var TypWin32Or64:TTypWin32Or64 ) ; if DirectoryExists('c:\Windows\SysWOW64') then TypWin32Or64:=Bit64 else TypWin32Or64:=Bit32; Procedure for looking Key or Create it in a Registry procedure TForm1.ReadKeyFromRegister(TypWin32Or64:TTypWin32Or64; TypeKey:Longword; {at once symbol HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER} PathToKey:string; TypeValueRead :Integer; //at once symbols as REG_SZ -- string key , //REG_DWORD A DWORD value, a 32-bit unsigned integer NameValueToRead:string; var ValueStrReaded:Ansistring; //is used if it is key string var ValueByteReaded:Pchar; //is used if it is key Byte ReadOnly:boolean); var Reg : TRegistry; S_TStr : TStrings; VersBios : string; Pos0 : integer; Key : HKEY; Value : Array of Byte; nValueLen : Integer; const KEY_WOW64_64KEY = $0100 ; begin case TypWin32Or64 of Bit32: Reg := TRegistry.Create; Bit64:Reg := TRegistry.Create(KEY_WRITE OR KEY_WOW64_64KEY); //use if if 64 bit enviroment Windows end; try { open key } Reg.RootKey := TypeKey; if ReadOnly then Reg.OpenKeyReadOnly(PathToKey) //not all key can be created or writed ie. ProductId(Serial Key) // name Windows - especially in a 64 bit Windows XP , Win 7 else Reg.OpenKey(PathToKey, false); //CreateKey=True--> if this key is not present will be created case TypeValueRead of REG_SZ: ValueStrReaded:=Reg.ReadString(NameValueToRead); REG_BINARY : begin nValueLen := Reg.GetDataSize(NameValueToRead); ValueByteReaded:=Pchar(Reg.ReadBinaryData(NameValueToRead, PByte(Value), nValueLen)); end; REG_DWORD : begin end; REG_MULTI_SZ: begin S_TStr := ReadMultirowKey(Reg,NameValueToRead); /in a enviroment 64 bit not good work - better use //procedure ReadREG_MULTI_SZ VersBios:=S_TStr.Text; Pos0:=Pos(#0,VersBios); if Pos0 > 0 then begin delete(VersBios,Pos0,1); insert(' ', VersBios,Pos0); end; VersBios := StringReplace(VersBios,#$D#$A, ' ' , [rfReplaceAll, rfIgnoreCase]); ValueStrReaded:=VersBios; end; end; //case Reg.CloseKey; finally Reg.Free; end; end; {------------} Sample for reading system Key from Registry Reading UsedWindowsVersion_Full ReadKeyFromRegister(TypWin32Or64, {TypWin32Or64} HKEY_LOCAL_MACHINE, {TypeKey:Longword;} 'SOFTWARE\Microsoft\Windows NT\CurrentVersion', {PathToKey:string;} REG_SZ, {TypeValueRead :Integer; } 'BuildLabEx', {NameValueToRead:string;} UsedWindowsVersion_Full, {ValueStrReaded:Ansistring;} sPchar ,{ValueByteReaded:Pchar} True {ReadOnly}); {-----------------------} For read ProductId(also called Product Key Windows) ReadKeyFromRegister( TypWin32Or64, HKEY_LOCAL_MACHINE, {TypeKey:Longword;} 'SOFTWARE\Microsoft\Windows NT\CurrentVersion', {PathToKey:string;} REG_SZ, {TypeValueRead :Integer; } 'ProductId', {NameValueToRead:string;} SerialKey, {ValueStrReaded:Ansistring;} sPchar, {ValueByteReaded:Pchar} True {ReadOnly}); {------------------------} For reading Product Name ReadKeyFromRegister(TypWin32Or64, HKEY_LOCAL_MACHINE, {TypeKey:Longword;} 'SOFTWARE\Microsoft\Windows NT\CurrentVersion', {PathToKey:string;} REG_SZ, {TypeValueRead :Integer; } 'ProductName', {NameValueToRead:string;} UsedWindowsName, {ValueStrReaded:Ansistring;} sPchar ,{ValueByteReaded:Pchar} True {ReadOnly}); {-----------------------} Procedure for look miltiline key as ie Version Bios - also 64 envir. procedure TForm1.ReadREG_MULTI_SZ(const CurrentKey: HKey; const Subkey, ValueName: string; Strings: TStrings; var ValueStrRead: String); var valueType: DWORD; valueLen: DWORD; p, buffer: PChar; key: HKEY; begin 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 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 ValueStrRead:=Strings.Text; ValueStrRead:=StringReplace(ValueStrRead,#$D#$A, ' ' , [rfReplaceAll, rfIgnoreCase]); FreeMem(buffer); end end else raise ERegistryException.Create('Stringlist expected') else raise ERegistryException.Create('Cannot Read MULTI_SZ Value/'); end; end; {-----------} 
+3
source share

I would say that this is caused by UAC - try starting with the administrator!

If it works at startup as an administrator, you need to change the read request to use read-only mode (not on the table in mo mode, so you cannot remember exactly how you do it)

edit:

 function GetWindowsID: string; var Registry: TRegistry; str:string; begin Registry := TRegistry.Create(KEY_READ); try Registry.RootKey := HKEY_LOCAL_MACHINE; // Registry.RootKey := HKEY_CURRENT_USER; if CheckForWinNT = true then Begin if not Registry.OpenKeyReadOnly('\Software\Microsoft\Windows NT\CurrentVersion') then showmessage('cant open'); end else Registry.OpenKeyReadOnly('\Software\Microsoft\Windows\CurrentVersion'); str := Registry.ReadString('ProductId'); result:=str; Registry.CloseKey; finally Registry.Free; end; // try..finally end; 
+1
source share

You should use this: TRegistry.Create(KEY_ENUMERATE_SUB_KEYS); Windows 7 UAC will not impede this

+1
source share

Try reading it manually using RegEdit. You may get "Access Denied" because of a permission problem, in which case look at your level and how you access it.

0
source share

I believe because

 str := Registry.ReadString('ProductId'); 

does not throw an exception if there is no ProductId . In my honest opinion, this is a bug in Delphi.

-2
source share

All Articles