2010-01-02 65 views
-1

我有一個函數可以對註冊表項目進行計數並添加一個新選項以檢索註冊表項目名稱和值。不幸的是,我似乎無法理解爲什麼只有每個註冊表項的第一項被檢索,並且爲什麼這些值都具有相同的名稱。幫助我修復Delphi函數來計算註冊表項目

任何人都可以看到下面的代碼的任何明顯的問題?

function CountRegistryItems(Root: HKEY; SubKey: string; var KeysCount: Integer; 
    var ValuesCount: Integer; GetValues: Boolean; const List: TStrings): Boolean; 
type 
    TRegKeyInfo = record 
    NumSubKeys: Integer; 
    MaxSubKeyLen: Integer; 
    NumValues: Integer; 
    MaxValueLen: Integer; 
    MaxDataLen: Integer; 
    FileTime: TFileTime; 
    end; 

var 
    Info: TRegKeyInfo; 
    i: integer; 
    SL: TStringList; 
    Status: Integer; 
    Key: HKEY; 
    Len: DWORD; 
    S: string; 

    PartialKeysCount: Integer; 
    PartialValuesCount: Integer; 

    KeyType, MaxValLen, MaxValNameLen, ValNameLen, ValLen: Cardinal; 
    ValName, Val: PChar; 

    Size: DWORD; 
    ValueName: string; 
begin 
    KeysCount := 0; 
    ValuesCount := 0; 
    Result := False; 

    if GetValues and (List <> nil) then 
    List.BeginUpdate; 

    SL := TStringList.Create; 
    Try 
    // open current key 
    Status := RegOpenKeyEx(Root, PChar(SubKey), 0, KEY_READ or KEY_ENUMERATE_SUB_KEYS, Key); 
    if Status = ERROR_SUCCESS then 
    Try 
     // get key info 
     FillChar(Info, SizeOf(TRegKeyInfo), 0); 
     Status := RegQueryInfoKey(Key, nil, nil, nil, @Info.NumSubKeys, 
       @Info.MaxSubKeyLen, nil, @Info.NumValues, @Info.MaxValueLen, 
       @Info.MaxDataLen, nil, @Info.FileTime); 
     if Status = ERROR_SUCCESS then 
     begin 
     Result := True; 

     // NEW CODE 
     if GetValues and (List <> nil) then 
     begin 
      MaxValNameLen := Info.MaxValueLen*2+3; 
      MaxValLen := Info.MaxDataLen+1; 
      // Get values 
      GetMem(ValName, MaxValNameLen); 
      GetMem(Val, MaxValLen); 

      //if Info.NumValues <> 0 then 
      for i := 0 to Info.NumValues-1 do 
      begin 
      // Clear buffers 
      ValName^ := #0; 
      ValNameLen := MaxValNameLen; 
      if Val <> nil then 
      begin 
       Val^ := #0; 
       ValLen := MaxValLen; 
      end; 

      // Get value information 
      if RegEnumValue(Root, i, ValName, ValNameLen, nil, @KeyType, 
       PByte(Val), @ValLen) = ERROR_SUCCESS then 
      begin 
       //if ((KeyType = REG_SZ) or (KeyType = REG_MULTI_SZ) 
       //or (KeyType = REG_EXPAND_SZ)) then 
       begin 
       if ValName^ <> #0 then 
        List.Add(ValName + '=' + Val) 
       else 
        List.Add('Default' + '=' + Val); 
       end; 
      end; 
      end; 
      // Free buffers 
      //FreeMem(ValName); 
      //if Val <> nil then FreeMem(Val); 
     end; 
     // END NEW CODE 

     // enum subkeys 
     SetString(S, nil, Info.MaxSubKeyLen + 1); 
     for i := 0 to Info.NumSubKeys - 1 do 
     begin 
      Len := Info.MaxSubKeyLen + 1; 
      Status := RegEnumKeyEx(Key, i, PChar(S), Len, nil, nil, nil, nil); 
      if Status <> ERROR_SUCCESS then Continue; 
      SL.Add(PChar(S)); 
     end; 
     end; 

     if Info.NumSubKeys > 0 then Inc(KeysCount, Info.NumSubKeys); 
     if Info.NumValues > 0 then Inc(ValuesCount, Info.NumValues); 

    Finally 
     RegCloseKey(Key); 
    End; 

    // search subkeys 
    if SL.Count > 0 then 
    begin 
     for i := 0 to SL.Count - 1 do 
     begin 
     Application.ProcessMessages; 
     PartialKeysCount := 0; 
     PartialValuesCount := 0; 
     CountRegistryItems(Root, SubKey + '\' + SL[i], PartialKeysCount, 
      PartialValuesCount, GetValues, List); 
     KeysCount := KeysCount + PartialKeysCount; 
     ValuesCount := ValuesCount + PartialValuesCount; 
     end; 
    end; 

    Finally 
    SL.Free; 

    if GetValues and (List <> nil) then 
     List.EndUpdate; 
    End; 
end; 
+5

也許你應該使用TRegistry而不是使用win32調用來重寫它。希望這會簡化代碼,使錯誤的原因更加明顯。 – 2010-01-02 15:03:29

回答

5

您可以使用TRegistry:

uses Registry; 

function CountRegistryItems(Root: HKEY; 
          SubKey: string; 
          var KeysCount: Integer; 
          var ValuesCount: Integer; 
          GetValues: Boolean; 
          const List: TStrings): Boolean; 
var 
    Reg : TRegistry; 
    KeyInfo : TRegKeyInfo; 
begin 
    Reg := TRegistry.Create; 
    try 
    Reg.RootKey := Root; 
    if Reg.OpenKey(SubKey,False) then 
    begin 
     Reg.GetKeyInfo(KeyInfo); 
     ValuesCount := KeyInfo.NumValues; 
     KeysCount := KeyInfo.NumSubKeys; 
     if (GetValues) and (Assigned(List)) then 
     begin 
     List.Clear; 
     Reg.GetValueNames(List); 
     end; 
    end; 
    Result := True; 
    finally 
    Reg.Free; 
    end; 
end; 
3

你需要調用RegEnumValue函數時要使用的關鍵變量,而不是根。