Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Registry ReadString method is not working in Windows 7 in Delphi 7

The following code sample used to return me windows id before, but now it doesn't work, and returns empty string, dunno 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;

Anybody can help?

like image 893
Tofig Hasanov Avatar asked Apr 19 '10 11:04

Tofig Hasanov


2 Answers

That is because the virtualized key '\Software\Wow6432Node\Microsoft\Windows NT\CurrentVersion\' doesn't contain the 'ProductID' item.

Modify your code to create the TRegistry instance with

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

where KEY_WOW64_64KEY = $0100. That 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);
like image 92
gabr Avatar answered Sep 18 '22 07:09

gabr


There are usefull procedure to read Key Register in a 32 bit and 64 bit enviroment.First look what system you have

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 i.e 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'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
                      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;
      {-----------}     
like image 38
sp9auv Avatar answered Sep 21 '22 07:09

sp9auv