帮我修一个计算注册表项目的Delphi函数

时间:2010-01-02 13:24:04

标签: 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;

2 个答案:

答案 0 :(得分: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;

答案 1 :(得分:3)

在调用RegEnumValue函数时,您需要使用Key变量而不是Root。