Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.07.11;
Скачать: CL | DM;

Вниз

Проблема обхода реестра Windows (TRegistry).   Найти похожие ветки 

 
mmn   (2004-05-27 15:06) [0]

Обхожу реестр рекурсивной процедурой такого вида:
procedure TForm1.ReadAllKeys(RootNode: string; NewNodeLevel: Cardinal);
var LocalSL: TStringList;
   i: Integer;
begin
 if MaxNodeLevel > 100 then Exit; // Это чтобы программа не работала бесконечно.
 LocalSL := TStringList.Create;
 try
   if not Reg.OpenKeyReadOnly(RootNode) then Exit;
   Reg.GetKeyNames(LocalSL);
   for i := 0 to LocalSL.Count - 1 do
   begin
     WriteLn(F,NewNodeLevel," ",LocalSL[i]);
     if MaxNodeLevel < NewNodeLevel then MaxNodeLevel := NewNodeLevel;
     ReadAllKeys(RootNode + "\" + LocalSL[i],NewNodeLevel + 1);
   end;
   Reg.CloseKey;
 finally
   LocalSL.Free;
 end;
end;


В результате, когда выполнение программы прерывается из-за поставленного мной ограничения на 100 уровней вложений, в созданном файле вижу такую картину перечня просмотренных ключей реестра:

HKEY_LOCAL_MACHINE\SYSTEM\...\PrivateProperties\MIDI\Ports
HKEY_LOCAL_MACHINE\SYSTEM\...\PrivateProperties\MIDI\Ports\
HKEY_LOCAL_MACHINE\SYSTEM\...\PrivateProperties\MIDI\Ports\\
HKEY_LOCAL_MACHINE\SYSTEM\...\PrivateProperties\MIDI\Ports\\\
HKEY_LOCAL_MACHINE\SYSTEM\...\PrivateProperties\MIDI\Ports\\\\
и т.д. до бесконечности :(
Хотя, если посмотреть через Regedt32, ключ Ports содержит только 7 вложенных ключей.

Такая ситуация возникает каждый раз именно в этой ветке реестра. Все остальные проходятся без таких глюков.

На другом компьютере происходит то же самое, но под другим ключём.
Может кто-нибудь сталкивался с подобным и объяснит в чём тут дело?


 
VMcL ©   (2004-05-27 16:11) [1]

>>mmn  (27.05.04 15:06)

Попробуй так:

procedure TForm1.ReadAllKeys(RootNode: string; NewNodeLevel: Cardinal);
var LocalSL: TStringList;
 i: Integer;
begin
if MaxNodeLevel > 100 then Exit; // Это чтобы программа не работала бесконечно.
LocalSL := TStringList.Create;
try
 if not Reg.OpenKeyReadOnly(RootNode) then Exit;
 Reg.GetKeyNames(LocalSL);
 for i := 0 to LocalSL.Count - 1 do
 begin
  if LocalSL[i] = "" then Continue;

  WriteLn(F,NewNodeLevel," ",LocalSL[i]);
  if MaxNodeLevel < NewNodeLevel then MaxNodeLevel := NewNodeLevel;
  ReadAllKeys(RootNode + "\" + LocalSL[i],NewNodeLevel + 1);
 end;
 Reg.CloseKey;
finally
 LocalSL.Free;
end;
end;


 
mmn   (2004-05-27 16:55) [2]

>> VMcL
Пустые значения имён я таким образом отсекал.
В результате таких цепочек пустых ключей не выводилось, но и тех вложенных ключей, которые видны при просмотре через Regedt32, тоже не обнаруживалось.


 
mmn   (2004-05-31 09:16) [3]

Или я чего-то не понимаю, или одно из двух.
Попробовал обход не через компонент TRegistry, а через функции API. Начинаю работу с реестром так:

i := RegOpenKeyEx(HKEY_LOCAL_MACHINE,"",0,KEY_ENUMERATE_SUB_KEYS,RootKey);
if i <> ERROR_SUCCESS then Exit;
i := 0;
while RegEnumKeyEx(RootKey,i,PChar(KName),KNSize,nil,nil,nil,nil) <> ERROR_NO_MORE_ITEMS do
begin
 SL.Add(KName);
 Inc(i);
end;


В компонент SL (который TStringList) заносятся пустые строчки, но их количество совпадает с числом существующих ключей. Кто-нибудь подскажет как это понимать?


 
Cobalt ©   (2004-05-31 09:56) [4]

Обяви Reg как локальную переменную процедуры.
Ты же её в конце процедуры киляешь! вот и создавай в начале процедуры.
А так она у тебя получается общей на сотню уровней вложенности.


 
mmn   (2004-05-31 10:27) [5]

>> Cobalt
> Обяви Reg как локальную переменную процедуры.


Результат не изменился.


 
mmn   (2004-06-01 09:26) [6]

А просто через функции API без использования TRegistry таких глюков не возникло. Просто так сказал.


 
NAlexey ©   (2004-06-01 11:58) [7]

Да вроде нормально все работает:

var
 Log : TextFile;

procedure LogFile(FileName, Msg: string);
begin
 {$I-}
 AssignFile(Log, FileName);
 Reset(Log);
 {$I+}
 if IOResult <> 0 then
 begin
   Rewrite(Log);
   Writeln(Log , Msg);
   Writeln(Log , "");
 end else
 begin
   Append(Log);
   Writeln(Log , Msg);
   Writeln( Log , "");
 end;
 CloseFile(Log);
end;

procedure ProcessChilds(ParentNode: TRegistry);
var
 I: Integer;
 sList: TStringList;
 Reg: TRegistry;
 CurrPath: string;
begin
 sList := TStringList.Create;
 try
   ParentNode.GetKeyNames(sList);
   Reg := TRegistry.Create;
   try
     Reg.RootKey := HKEY_LOCAL_MACHINE;
     CurrPath := "";
     for I := 0 to sList.Count - 1 do
     begin
       if ParentNode.CurrentPath = "" then
         CurrPath := "\" + sList[I]
       else
         CurrPath := "\" + ParentNode.CurrentPath + "\" + sList[I];
       if not Reg.OpenKeyReadOnly(CurrPath) then
         Continue;
       LogFile("C:\Reg.txt", CurrPath);
       if Reg.HasSubKeys then
         ProcessChilds(Reg);
     end;
     Reg.CloseKey;
   finally
     Reg.Free;
   end;
 finally
   sList.Free;
 end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 Reg: TRegistry;
begin
 Reg := TRegistry.Create;
 try
   Reg.RootKey := HKEY_LOCAL_MACHINE;
   if not Reg.OpenKeyReadOnly("") then
     Exit;
   ProcessChilds(Reg);
   Reg.CloseKey;
 finally
   Reg.Free;
 end;
end;


 
mmn   (2004-06-01 13:24) [8]

>> NAlexey
Попробовал.
Та же самая фигня, что и раньше, в том же самом ключе. Причём, я опять попробовал и на другом компьютере - и там то же самое (но в другом ключе).


 
NAlexey ©   (2004-06-01 14:08) [9]

>mmn   (01.06.04 13:24) [8]
Да, я тоже напаролся на это когда весь реестр пробежал, потом подправил как сказал VMcL ©   (27.05.04 16:11) [1] .
И все нормально. Попробуй:

procedure ProcessChilds(ParentNode: TRegistry);
var
I: Integer;
sList: TStringList;
Reg: TRegistry;
CurrPath: string;
begin
sList := TStringList.Create;
try
  ParentNode.GetKeyNames(sList);
  Reg := TRegistry.Create;
  try
    Reg.RootKey := HKEY_LOCAL_MACHINE;
    CurrPath := "";
    for I := 0 to sList.Count - 1 do
    begin
      if sList[I] = "" then
        Continue;
      if ParentNode.CurrentPath = "" then
        CurrPath := "\" + sList[I]
      else
        CurrPath := "\" + ParentNode.CurrentPath + "\" + sList[I];
      if not Reg.OpenKeyReadOnly(CurrPath) then
        Continue;
      Memo1.Lines.Add(CurrPath);
      if Reg.HasSubKeys then
        ProcessChilds(Reg);
    end;
    Reg.CloseKey;
  finally
    Reg.Free;
  end;
finally
  sList.Free;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
Reg: TRegistry;
begin
Reg := TRegistry.Create;
try
  Reg.RootKey := HKEY_LOCAL_MACHINE;
  if not Reg.OpenKeyReadOnly("") then
    Exit;
  ProcessChilds(Reg);
  Reg.CloseKey;
finally
  Reg.Free;
end;
end;


 
NAlexey ©   (2004-06-01 14:10) [10]

>mmn   (27.05.04 16:55) [2]
Блин, чтото торможу, извини. Тоже не уловил в чем дело.


 
NAlexey ©   (2004-06-01 14:31) [11]

Попробуй так:

procedure ProcessChilds(ParentNode: TRegistry);

 procedure InternalGetKeyNames(Strings: TStrings);
 var
   Len: DWORD;
   I: Integer;
   Info: TRegKeyInfo;
   S: string;
 begin
   Strings.Clear;
   if ParentNode.GetKeyInfo(Info) then
   begin
     SetString(S, nil, 255 + 1);
     for I := 0 to Info.NumSubKeys - 1 do
     begin
       Len := 255 + 1;
       RegEnumKeyEx(ParentNode.CurrentKey, I, PChar(S), Len, nil, nil, nil, nil);
       Strings.Add(PChar(S));
     end;
   end;
 end;

var
 I: Integer;
 sList: TStringList;
 Reg: TRegistry;
 CurrPath: string;
begin
 sList := TStringList.Create;
 try
   InternalGetKeyNames(sList);
   Reg := TRegistry.Create;
   try
     Reg.RootKey := HKEY_LOCAL_MACHINE;
     CurrPath := "";
     for I := 0 to sList.Count - 1 do
     begin
       if sList[I] = "" then
       begin
         ParentNode.GetKeyNames(sList);
         Continue;
       end;
       if ParentNode.CurrentPath = "" then
         CurrPath := "\" + sList[I]
       else
         CurrPath := "\" + ParentNode.CurrentPath + "\" + sList[I];
       if not Reg.OpenKeyReadOnly(CurrPath) then
         Continue;
       Form1.Memo1.Lines.Add(CurrPath);
       if Reg.HasSubKeys then
         ProcessChilds(Reg);
     end;
     Reg.CloseKey;
   finally
     Reg.Free;
   end;
 finally
   sList.Free;
 end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 Reg: TRegistry;
begin
 Reg := TRegistry.Create;
 try
   Reg.RootKey := HKEY_LOCAL_MACHINE;
   if not Reg.OpenKeyReadOnly("System") then
     Exit;
   ProcessChilds(Reg);
   Reg.CloseKey;
 finally
   Reg.Free;
 end;
end;


 
mmn   (2004-06-01 16:35) [12]

Т.е. получается, что метод GetKeyNames компонента TRegistry в некоторых случаях срабатывает неправильно. И похоже из-за того, что в методе GetKeyInfo неправильно определяется значение максимальной длины имени ключа (MaxSubKeyLen). А вот почему это происходит я не понял.



Страницы: 1 вся ветка

Текущий архив: 2004.07.11;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.048 c
14-1087476394
Рамиль
2004-06-17 16:46
2004.07.11
Software Update Services


1-1087988428
Сашка
2004-06-23 15:00
2004.07.11
Отлов расстыковки


1-1088078327
ThermiT
2004-06-24 15:58
2004.07.11
Работа с MS Word (генерация отчетов)


4-1083161649
Бегун
2004-04-28 18:14
2004.07.11
Как запретить двигать форму?


3-1087143909
mafuka
2004-06-13 20:25
2004.07.11
InterBase