Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Ordner rekursiv durchsuchen bis zu maximaler Tiefe (https://www.delphipraxis.net/145252-ordner-rekursiv-durchsuchen-bis-zu-maximaler-tiefe.html)

Flodding 27. Dez 2009 23:25


Ordner rekursiv durchsuchen bis zu maximaler Tiefe
 
Guten Abend zusammen...

ich arbeite grade an einem kleinen Projekt für das MMORPG "World of Warcraft".

Eigentlich macht dieses kleine Tool nichts weiter als den "Cache" Ordner und *.bak's aud diversen Unterordnern des WoW Verzeichnisses zu löschen um die Ladezeiten zu verkürzen... danach startet es dann den normalen WoW-Launcher und beendet sich danach selber.

bis jetzt hat alles gut geklappt...

sachen wie:

Delphi-Quellcode:
reg.Access := KEY_READ;
Reg.OpenKey('\Software\Blizzard Entertainment\World of Warcraft\', false);
GamePath:=Reg.ReadString('InstallPath');
und so liefen wie geschmiert...

auch

Delphi-Quellcode:
procedure TForm1.FileSearch(const PathName, FileName : string; const InDir : boolean);
var Rec : TSearchRec;
    Path : string;
begin
Path := IncludeTrailingBackslash(PathName);
if FindFirst(Path + FileName, faAnyFile - faDirectory, Rec) = 0 then
 try
   repeat
   DeleteFile(Path + Rec.Name);
   if not FileExists(Path + Rec.Name) then form3.ListBox1.Items.Add(Path + Rec.Name);
   if form3.ListBox1.Items.count > 2 then form3.Label1.Caption:= inttostr(form3.ListBox1.Items.Count) + ' Dateien gelöscht';
   if form3.ListBox1.Items.count = 1 then form3.Label1.Caption:= inttostr(form3.ListBox1.Items.Count) + ' Datei gelöscht';
   SetHorizontalScrollBar(form3.ListBox1) ;
   form3.Button1.Enabled:=false;
   until FindNext(Rec) <> 0;
 finally
   FindClose(Rec);
 end;

If not InDir then Exit;

if FindFirst(Path + '*.*', faDirectory, Rec) = 0 then
 try
   repeat
    if ((Rec.Attr and faDirectory) <> 0) and (Rec.Name<>'.') and (Rec.Name<>'..') then
     FileSearch(Path + Rec.Name, FileName, True);
   until FindNext(Rec) <> 0;
 finally
   FindClose(Rec);
 end;
form3.Button1.Enabled:=true;
end;
funktioniert ganz okay... auch wenns bestimmt besser geht... es erfüllt seinen Zweck.

Doch jetzt bin ich an dem Punkt, wo ich die "procedure TForm1.FileSearch" umbasteln muss, oder ne ganz andere brauche, denn ich möchte jetzt im "Path\Interface\Addons\" nach den *.toc's der installierten Addons suchen und diese dann auflisten um sie auf aktualität zu überprüfen... für die die nicht wissen wie so eine TOC aufgebaut ist:

---
## Interface: 30300
## Title: TweakWoW
## Author: xXx
## Version: 1.0
## Notes: ...
## DefaultState: Enabled
## LoadOnDemand: 0
## SavedVariables: AutoSellGreys, AutoRepair
TweakWoW.xml
---

Jetzt erkennt man schon dass ich in der zeile die zeichen nach "## Version: " suchen muss... das sollte später auch nicht das problem sein...

Jetzt also zu meinem Problem.

Wie gesagt ich befinde mich zurzeit im Ordner "Path\Interface\Addons\". Wenn ich jetzt die TOC von oben finden möchte muss ich in "Path\Interface\Addons\TweakWoW\" suchen und ich werde fündig. Jedoch gibt es andere Addons die weitere Unterordner beinhalten und in diesen befinden sich auch TOC's. Diese möchte ich aber bei einer Suche NICHT finden. Es geht mir nur um diese:

"Path\Interface\Addons\ADDONNAME\ADDONNAME.TOC "

Ich bin mir ziemlich sicher, dass ich mit der rekursiven Suche relativ nahe dran bin, jedoch habe ich nichts gefunden, womit ich die Unterordnertiefe bei einer suche einstellen kann...

Vielen Dank schonmal an hilfreiche Antworten :)

MFG

Floddy

sx2008 27. Dez 2009 23:47

Re: Ordner rekursiv durchsuchen bis zu maximaler Tiefe
 
Statt dem Parameter InDir:Boolean nimmst du einfach den Parameter Tiefe:integer.
Jedesmal, wenn du rekursiv ein Verzeichnis hinabsteigst wird die Tiefe ums Eins verringert.
Delphi-Quellcode:
// procedure TForm1.FileSearch(const PathName, FileName : string; const InDir : boolean); // alt
procedure TForm1.FileSearch(const PathName, FileName : string; Tiefe:integer); // neu
...
// If not InDir then Exit; // alt
if Tiefe <= 0 then Exit; // neu
...
// FileSearch(Path + Rec.Name, FileName, True); // alt
FileSearch(Path + Rec.Name, FileName, Tiefe-1); // neu

Progman 28. Dez 2009 07:54

Re: Ordner rekursiv durchsuchen bis zu maximaler Tiefe
 
Ich würde so vorgehen:
Alle Verzeichnisse des Ordners AddOns, die nicht mit "Blizzard_" beginnen, in eine TStringList einlesen und diese dann durchgehen und in jedem dieser Verzeichnisse nach *.toc suchen.

neo4a 28. Dez 2009 08:12

Re: Ordner rekursiv durchsuchen bis zu maximaler Tiefe
 
Die Komponente TFindFile sollte das bieten, was Du suchst. Hier kannst Du nicht nur mit dem Parameter "Filters" schon vieles erschlagen:
Zitat:

>*delphi* Includes all files that contain 'delphi' in their full path
>\\Server\*.txt Includes all text files on computer named 'Server'
C:\Windows\*\*.txt Excludes all text files in the second level subfolders of 'C:\Windows' directory
>*\src\*.txt Includes all text files in 'src' subfolder of any folder of any drive and network location
?:*\lib\*.txt Excludes all text files in 'lib' subfolder of any folder of any drive
?*\readme.txt Excludes all readme.txt files

sondern auch diese Parameter dürften Dir gefallen:

Zitat:

# MinLevel: Word
Determines the minimum directory level from the base folder for the target files. Set this property to zero if you do not need this feature.
To know how to set MinLevel on every individual folder see Folder Meta Parameters.
# MaxLevel: Word
Determines the maximum directory level from the base folder for the target files. Set this property to zero if you do not need this feature.
To know how to set MinLevel on every individual folder see Folder Meta Parameters.
weil sich damit die Suchtiefen beeinflussen lassen. Ach, und Inhalte-Suche geht wohl auch.

--
Andreas

Flodding 28. Dez 2009 10:20

Re: Ordner rekursiv durchsuchen bis zu maximaler Tiefe
 
Zitat:

Zitat von sx2008
Statt dem Parameter InDir:Boolean nimmst du einfach den Parameter Tiefe:integer.
Jedesmal, wenn du rekursiv ein Verzeichnis hinabsteigst wird die Tiefe ums Eins verringert.
Delphi-Quellcode:
// procedure TForm1.FileSearch(const PathName, FileName : string; const InDir : boolean); // alt
procedure TForm1.FileSearch(const PathName, FileName : string; Tiefe:integer); // neu
...
// If not InDir then Exit; // alt
if Tiefe <= 0 then Exit; // neu
...
// FileSearch(Path + Rec.Name, FileName, True); // alt
FileSearch(Path + Rec.Name, FileName, Tiefe-1); // neu

das hört sich gut an... werde ich heute probieren :)

Zitat:

Zitat von Progman
Ich würde so vorgehen:
Alle Verzeichnisse des Ordners AddOns, die nicht mit "Blizzard_" beginnen, in eine TStringList einlesen und diese dann durchgehen und in jedem dieser Verzeichnisse nach *.toc suchen.

In den "Blizzard_" Ordnern befinden sich keine TOCs, somit werden die bei einer Suche nach TOCs so oder so gefiltert... trotzdem kann man das vorbeugend mit einbauen um die Suche, wenn auch nur wenig, zu verkürzen :)

Zitat:

Zitat von neo4a
Die Komponente TFindFile sollte das bieten, was Du suchst. Hier kannst Du nicht nur mit dem Parameter "Filters" schon vieles erschlagen:

werde ich auch suchen, finden und probieren...

Vielen dank nochmal an die guten antworten. Ich meld mich nochmal wenn ich mich entschieden habe wie ichs mach...

Flodding 29. Dez 2009 12:51

Re: Ordner rekursiv durchsuchen bis zu maximaler Tiefe
 
Hallo nochmal... wie versprochen jetzt nochmal meine Lösung wie ich sie am leichtesten und meiner meinung nach am sinnvollsten umgesetzt habe...

Delphi-Quellcode:
procedure TForm5.FormShow(Sender: TObject);
var
searchResult : TSearchRec;
begin
  SetCurrentDir(form1.gamepath + '\Interface\Addons');
listbox1.Clear;
  if FindFirst('*.*', faDirectory, searchResult) = 0 then
  begin
    repeat
      if (searchResult.attr and faDirectory) = faDirectory then
    if LeftStr(searchResult.Name, 9)='Blizzard_' then else ListBox1.Items.Add(searchResult.Name);
    until FindNext(searchResult) <> 0;
    FindClose(searchResult);
    ListBox1.Items.Delete(0);
    ListBox1.Items.Delete(0);
  end;
end;
bewusst im FormShow, damit wirklich jedes mal nach neuen Ordnern gesucht wird...
natürlich hab ich die "Blizzard_" ordner überspringen lassen ;)

und nun zu den TOCs um die es ja eigentlich geht...

Delphi-Quellcode:
procedure TForm5.ListBox1Click(Sender: TObject);
var
i: integer;
versioncheck: integer;
begin
[b]if FileExists(form1.gamepath + 'Interface\Addons\' + ListBox1.Items[ListBox1.ItemIndex] + '\' + ListBox1.Items[ListBox1.ItemIndex] + '.toc') then[/b]
begin
LabeledEdit1.Text:='';
memo1.Lines.Clear;
[b]tocpath:=form1.gamepath + 'Interface\Addons\' + ListBox1.Items[ListBox1.ItemIndex] + '\' + ListBox1.Items[ListBox1.ItemIndex] + '.toc';[/b]
memo1.Lines.LoadFromFile(tocpath);
for i:= 0 to Memo1.Lines.Count-1 do begin
if LeftStr(memo1.Lines[i], 14)='## Interface: ' then
begin
LabeledEdit1.Text:=MidStr(Memo1.Lines[i], 15, Length(memo1.Lines[i]));
versioncheck:=strtoint(LabeledEdit1.Text);
if versioncheck <> 30300 then LabeledEdit1.Color:= clRed else LabeledEdit1.Color:= clGreen;
versionline:=i;
end;
if LeftStr(memo1.Lines[i], 17)='&#65279;## Interface: ' then
begin
LabeledEdit1.Text:=MidStr(Memo1.Lines[i], 18, Length(memo1.Lines[i]));
versioncheck:=strtoint(LabeledEdit1.Text);
if versioncheck <> 30300 then LabeledEdit1.Color:= clRed else LabeledEdit1.Color:= clGreen;
versionline:=i;
end;
end
end

end;
interesant dafür sind hier nur die fett markierten zeilen... der rest dient eigentlich nur dazu, aus der TOC dann die Interfaceversion zu lesen und diese dann in einem LabeledEdit darzustellen um sie nach einem interfaceveränderndem Patch nicht umständlich toc für toc ändern zu müssen über einen texteditor.
blöd daran ist nur, dass beim Speichern...

Delphi-Quellcode:
procedure TForm5.Button2Click(Sender: TObject);
begin
if LabeledEdit1.Text<>'' then memo1.Lines.Delete(versionline);
memo1.Lines.Add('## Interface: ' + LabeledEdit1.Text);
Memo1.Lines.SaveToFile(tocpath);
end;
...die neue Zeile ans Ende der TOC gehängt wird und ich keine Möglichkeit gefunden habe die zeile aus der die interfaceversion gelesen wird einfach zu überschreiben... beeinflusst nicht die Funktionalität, sieht aber unschön aus am ende ;)

Wem dazu noch etwas einfällt der kanns ja gerne hier posten.

MFG

Floddy

EDIT:::

sorry übrigens fürs Doppelpost.

Micha88 29. Dez 2009 13:02

Re: Ordner rekursiv durchsuchen bis zu maximaler Tiefe
 
Zitat:

Eigentlich macht dieses kleine Tool nichts weiter als den "Cache" Ordner und *.bak's aud diversen Unterordnern des WoW Verzeichnisses zu löschen um die Ladezeiten zu verkürzen
Ich empfehle ein BATCH-File!

Das selbe mache ich auch, wenn ich Google Earth starte.
Ich starte erst ein Batch-File, dieses löscht den Cache, startet dan Google Earth und dann beendet sich es wieder.

Weniger als 5 Zeilen :D

Progman 29. Dez 2009 15:48

Re: Ordner rekursiv durchsuchen bis zu maximaler Tiefe
 
Delphi-Quellcode:
procedure TForm5.Button2Click(Sender: TObject);
begin
if LabeledEdit1.Text<>'' then memo1.Lines[versionline]:='## Interface: ' + LabeledEdit1.Text;
//memo1.Lines.Add('## Interface: ' + LabeledEdit1.Text);
Memo1.Lines.SaveToFile(tocpath);
end;
Wäre das nicht möglich?
Dann stände es anstelle des alten Textes in der originalen Zeile :)

Gravitar 31. Dez 2009 14:13

Re: Ordner rekursiv durchsuchen bis zu maximaler Tiefe
 
Hi,

schau mal hier (http://www.delphipraxis.net/internal...660&highlight=) nach. Dort werden Verzeichnisse bis zu einer bestimmten Ordnertiefe angezeigt.

Gruß, Andreas


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:46 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz