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

帮助我修复一个计算注册表项的Delphi函数,delphi,Delphi,我有一个计算注册表项的函数,并添加了一个新选项来检索注册表项的名称和值。不幸的是,我似乎无法理解为什么只检索每个注册表项的第一项,以及为什么所有值都具有相同的名称 有人看到下面的代码有任何明显的问题吗 function CountRegistryItems(Root: HKEY; SubKey: string; var KeysCount: Integer; var ValuesCount: Integer; GetValues: Boolean; const List: TStrings)

我有一个计算注册表项的函数,并添加了一个新选项来检索注册表项的名称和值。不幸的是,我似乎无法理解为什么只检索每个注册表项的第一项,以及为什么所有值都具有相同的名称

有人看到下面的代码有任何明显的问题吗

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;
函数CountRegistryItems(根:HKEY;子键:string;var-KeysCount:Integer;
var-valuescont:Integer;GetValues:Boolean;const-List:TStrings:Boolean;
类型
TRegKeyInfo=记录
NumSubKeys:整数;
MaxSubKeyLen:整数;
NumValues:整数;
MaxValueLen:整数;
MaxDataLen:整数;
FileTime:TFileTime;
结束;
变量
信息:TRegKeyInfo;
i:整数;
SL:TStringList;
状态:整数;
关键词:香港交易所;;
伦:德沃德;
S:字符串;
partialKeyScont:整数;
部分值:整数;
键类型,MaxValLen,MaxValNameLen,ValNameLen,ValLen:Cardinal;
ValName,Val:PChar;
尺寸:德沃德;
ValueName:字符串;
开始
密钥计数:=0;
ValueScont:=0;
结果:=假;
如果GetValues和(列出nil),则
List.BeginUpdate;
SL:=TStringList.Create;
尝试
//打开当前键
状态:=RegOpenKeyEx(根,PChar(子键),0,键读取或键枚举,子键,键);
如果状态=错误\成功,则
尝试
//获取关键信息
FillChar(Info,SizeOf(TRegKeyInfo),0);
状态:=RegQueryInfoKey(Key,nil,nil,nil,@Info.numsubkey,
@Info.MaxSubKeyLen,nil,@Info.NumValues,@Info.MaxValueLen,
@Info.MaxDataLen,nil,@Info.FileTime);
如果状态=错误\成功,则
开始
结果:=真;
//新代码
如果GetValues和(列出nil),则
开始
MaxValNameLen:=Info.MaxValueLen*2+3;
MaxValLen:=Info.MaxDataLen+1;
//获取价值
GetMem(ValName,MaxValNameLen);
GetMem(Val,MaxValLen);
//如果Info.num值为0,则
对于i:=0到Info.NumValues-1 do
开始
//清除缓冲区
ValName^:=#0;
ValNameLen:=MaxValNameLen;
如果Val nil那么
开始
Val^:=#0;
ValLen:=MaxValLen;
结束;
//获取价值信息
如果RegEnumValue(Root,i,ValName,ValNameLen,nil,@KeyType,
PByte(Val),@ValLen)=错误\成功
开始
//如果((KeyType=REG_SZ)或(KeyType=REG_MULTI_SZ)
//或者(KeyType=REG_EXPAND_SZ))然后
开始
如果ValName ^#0,则
List.Add(ValName+'='+Val)
其他的
List.Add('Default'+'='+Val);
结束;
结束;
结束;
//自由缓冲区
//FreeMem(ValName);
//如果Val为nil,则为FreeMem(Val);
结束;
//结束新代码
//枚举子键
设置字符串(S、nil、Info.MaxSubKeyLen+1);
对于i:=0到Info.NumSubKeys-1 do
开始
Len:=Info.MaxSubKeyLen+1;
状态:=RegEnumKeyEx(键,i,PChar,Len,nil,nil,nil,nil);
如果状态错误\u成功,则继续;
SL.Add(PChar(S));
结束;
结束;
如果Info.NumSubKeys>0,则Inc(KeysCount,Info.NumSubKeys);
如果Info.NumValues>0,则Inc(valuescont,Info.NumValues);
最后
RegCloseKey(Key);
结束;
//搜索子键
如果SL.计数>0,则
开始
对于i:=0到SL。计数-1 do
开始
Application.ProcessMessages;
partialKeyScont:=0;
部分价值要素:=0;
CountRegistryItems(根,子键+'\'+SL[i],PartialKeyScont,
PartialValuesCount、GetValues、List);
KeysCount:=KeysCount+partialKeyScont;
ValueScont:=ValueScont+部分ValueScont;
结束;
结束;
最后
SL.免费;
如果GetValues和(列出nil),则
List.EndUpdate;
结束;
结束;
您可以使用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;

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

也许您应该使用TRegistry重写它,而不是使用win32调用。希望这样可以简化代码,使bug的原因更加明显。