2010-04-19 17 views
6

Il seguente esempio di codice utilizzato per restituire l'ID di Windows precedente, ma ora non funziona e restituisce una stringa vuota, non so perché.Il metodo ReadString del Registro di sistema non funziona in Windows 7 in Delphi 7

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; 

Chiunque può aiutare?

risposta

23

Questo perché la chiave virtualizzata '\ Software \ Wow6432Node \ Microsoft \ Windows NT \ CurrentVersion \' non contiene l'elemento 'ProductID'.

modificare il codice per creare l'istanza TRegistry con

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

dove KEY_WOW64_64KEY = $ 0100. Questo ti darà il risultato atteso.

In alternativa, utilizzare DSiWin32 e chiamare

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

informazioni utili. Non avevo sentito parlare di DSiWin32. In che modo è migliore/diverso dalle routine simili nella libreria Jedi? –

1

Direi che questo è causato da Controllo dell'account utente - prova ad avviare come amministratore!

Se funziona quando viene avviato come amministratore, allora avete bisogno di cambiare la vostra richiesta di lettura di utilizzare modalità di sola lettura (non alla scrivania a mo quindi non ricordo esattamente come farlo)

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; 
0

Prova a leggerlo manualmente con RegEdit. Potresti ricevere l'accesso negato a causa di un problema di autorizzazione, nel qual caso verifica il tuo livello e il modo in cui accedici.

1

Si dovrebbe utilizzare questo: TRegistry.Create(KEY_ENUMERATE_SUB_KEYS); Windows Seven UAC non impedisce l'esecuzione di questo

-2

Credo che sia perché

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

fa non generare un'eccezione quando non c'è ProductId. A mio parere onesto, questo è un bug in Delphi.

+0

è il winapi. È pensato per restituire configurazioni. Quando è presente restituisce il valore se non è presente il valore predefinito. – Firo

+0

non è un bug. è un comportamento di Windows come discusso sopra – Jonesome

3

ci sono procedura utile per leggere la chiave Registro in un po 'a 32 bit e 64 enviroment.First guarda che sistema avete

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; 
     {-----------}  
+0

La funzione ReadMultirowKey è mancante nel codice sopra .. [codice] Disponibile all'indirizzo http://www.sql.ru/forum/955383/readmultirowkey [/ code] –

Problemi correlati