2010-04-19 4 views
6

Следующий пример кода, который использовался для возврата мне id окна раньше, но теперь он не работает и возвращает пустую строку, а не почему.Метод Registry ReadString не работает в Windows 7 в 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; 

Любой может помочь?

ответ

23

Это потому, что виртуализованный ключ «\ Software \ Wow6432Node \ Microsoft \ Windows NT \ CurrentVersion» не содержит элемент «ProductID».

Измените код, чтобы создать экземпляр TRegistry с

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

где KEY_WOW64_64KEY = $ 0100. Это даст вам ожидаемый результат.

В качестве альтернативы, используйте DSiWin32 и вызовите

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

Полезная информация. Я не слышал о DSiWin32. Как это лучше/отличается от аналогичных процедур в библиотеке джедаев? –

1

Я бы сказал, что это вызвано UAC - попробуйте начать с администратора!

Если он работает при запуске от имени администратора, то вам необходимо изменить свой запрос на чтение, чтобы использовать режим только для чтения (не на столе в мес так точно не помню, как это сделать)

редактировать:

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

Попробуйте прочитать его вручную с помощью RegEdit. Вы можете получить «Access Denied» из-за проблемы с разрешением, и в этом случае посмотрите на свой уровень и то, как вы обращаетесь к нему.

1

Вы должны с помощью этого: TRegistry.Create(KEY_ENUMERATE_SUB_KEYS); окна семь UAC не будет препятствовать выполнения этого

-2

Я считаю, это потому, что

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

делает не создавать исключение, если нет ProductId. По моему честному мнению, это ошибка в Delphi.

+0

это winapi. Он предназначен для возврата конфигураций. При наличии возвращается значение, если оно не указано по умолчанию. – Firo

+0

это не ошибка. это поведение окон, как обсуждалось выше – Jonesome

3

Есть полезная процедура для чтения ключей реестра в 32 бит и 64 бит на enviroment.First посмотреть, что система у вас есть

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

Функция ReadMultirowKey отсутствует в коде выше. [код] Доступно по адресу http://www.sql.ru/forum/955383/readmultirowkey [/ code] –