Autor |
Beitrag |
D. Annies
      
Beiträge: 1843
windows 7
D6 Enterprise, D7 Pers und TD 2006
|
Verfasst: Do 20.01.11 20:10
Hi, Delpher,
ich kopiere per Delphi-Programm viele Dateien z.B. von D nach H.
Uv's werden angelegt, alles läuft bestens.
Gegen Ende der umfangreichen Transaktion tritt der obige Fehler auf mit der Erläuterung:
Der aktuelle Prozess verwendet alle Handles der zulässigen Höchstanzahl für Windows Managerobjekte
Prozess wurde angehalten ...
Was ist denn da los?
Gruß, Detlef
_________________ ut vires desint, tamen est laudanda voluntas
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 20.01.11 20:53
Das bedeutet wohl, dass du die Dateihandles beim Kopieren nicht wieder freigibst. Und wenn alle verfügbaren Handles von dir in Beschlag genommen sind, ist Schluss.
|
|
D. Annies 
      
Beiträge: 1843
windows 7
D6 Enterprise, D7 Pers und TD 2006
|
Verfasst: Do 20.01.11 21:41
Klingt sehr plausibel!
Woran erkenne ich ein Dateihandle? Wie vergebe / löse ich ein Dateihandle?
Gruß, Detlef
_________________ ut vires desint, tamen est laudanda voluntas
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 20.01.11 21:44
Das kommt ja drauf an wie du kopierst...
Nebenbei zeigen der Taskmanager bzw. der Process Explorer auch an wie viele Handles ein Programm gerade verwendet.
|
|
D. Annies 
      
Beiträge: 1843
windows 7
D6 Enterprise, D7 Pers und TD 2006
|
Verfasst: Do 20.01.11 21:56
Ich kopiere folgendermaßen:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33:
| if (fileexists(home_filename)) and (fileexists(work_filename)) then begin
if (FileDateToDateTime(FileAge(work_filename)) <> FileDateToDateTime(FileAge(home_filename))) and (fileage(work_filename) + 3600 <> FileAge(home_filename)) and (fileage(work_filename) <> FileAge(home_filename) + 3600) then begin erg := xmessagedlg('ArchivBit wurde gesetzt' +#13 + 'Soll ' + work_filename + ' '+#13+ datetimetostr(filedatetodatetime(FileAge(work_filename))) +#13+ 'durch ' + home_filename + ' '+#13+ datetimetostr(filedatetodatetime(FileAge(home_filename))) +#13+ ' ersetzt werden?', mtConfirmation, [mbYes, mbno, mbcancel], ['ja', 'nein', 'Abbrechen'], self.font); case erg of mryes : CopyFile(PChar(home_filename), PChar(work_filename), FALSE); mrcancel : raus := true; end; end end else if (fileexists(home_filename)) and (not fileexists(work_filename)) then begin erg := xmessagedlg('Soll '+ work_filename + #13+ ' angelegt werden?', mtConfirmation, [mbYes, mbNo, mbcancel], ['ja', 'nein', 'Abbrechen'], self.font); case erg of mryes : begin if not directoryexists(ziel+uvname) then CreateDir(ziel+uvname); CopyFile(PChar(home_filename), PChar(work_filename), TRUE); end; mrcancel : raus := true; end; end; |
Das Handle ist wohl der PChar (??)
(Wie) Geht es anders / besser?
Gruß, Detlef
Moderiert von Narses: Delphi-Tag repariert.
_________________ ut vires desint, tamen est laudanda voluntas
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 20.01.11 22:02
Da ist kein Handle, das du explizit benutzt. In den verwendeten Delphifunktionen wird das ziemlich sicher alles richtig freigegeben.
Ich habe aber einen Verdacht:
Ich rate einmal, dass du FindFirst usw. benutzt um nach den Dateien zu suchen. Kann es sein, dass du vergessen hast, diese Suchhandles mit FindClose auch wieder zu schließen? 
|
|
D. Annies 
      
Beiträge: 1843
windows 7
D6 Enterprise, D7 Pers und TD 2006
|
Verfasst: Do 20.01.11 23:05
Ich dachte erst: Volltreffer, aber ich glaube, nicht:
Die komplette Proc:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109:
| Procedure TBuchMain.FindFiles (aPath, aFindMask: String; aWithSub: Boolean); Var FindRec : tSearchRec; home_filename, work_filename, Pfad, uvname, start, ziel : string; n, erg : integer; raus : boolean; Begin raus := false; If (aPath = '') or (aFindMask = '') then Exit; If aPath[Length(aPath)] <> '\' Then aPath := aPath + '\'; Pfad := aPath; If FindFirst (aPath + aFindMask, faAnyFile - faDirectory, FindRec) = 0 Then Repeat If (FindRec.Name <> '.') and (FindRec.Name <> '..') Then begin if aktuser <> 'an s' then begin if (pos('home.', FindRec.Name) > 0) or (pos('.pas', FindRec.Name) > 0) or (pos('.dfm', FindRec.Name) > 0) or (pos('.res', FindRec.Name) > 0) or (pos('.exe', FindRec.Name) > 0) or (pos('.dpr', FindRec.Name) > 0) OR (pos('.ddp', FindRec.Name) > 0) or (pos('.dof', FindRec.Name) > 0) or (pos('.dsk', FindRec.Name) > 0) or (pos('.dcu', FindRec.Name) > 0) or (pos('.cfg', FindRec.Name) > 0) then begin end end else begin if (pos('.ddp', FindRec.Name) > 0) or (pos('.dof', FindRec.Name) > 0) or (pos('.dsk', FindRec.Name) > 0) or (pos('.dcu', FindRec.Name) > 0) or (pos('.cfg', FindRec.Name) > 0) then begin end else if (FindRec.Name[1] = '_') or (pos('.~', FindRec.Name) > 0) or (pos('bestand_', FindRec.Name) > 0) or (pos('temp_', FindRec.Name) > 0) or (pos('Geburtstag_', FindRec.Name) > 0) then begin showmessage(apath + findrec.name + ' wird gelöscht'); DeleteFile(apath + FindRec.name) end else begin uvname := ''; for n := pos('Buecherei\', Pfad)+10 to length(Pfad) do uvname := uvname + apath[n]; if aPath[1] = stdwert[1] then begin start := stdwert; ziel := label30.Caption; home_filename := stdwert + uvname + FindRec.Name; work_filename := label30.caption + uvname + FindRec.name; end else begin start := label30.Caption; ziel := stdwert; home_filename := label30.caption + uvname + FindRec.name; work_filename := stdwert + uvname + FindRec.name; end; if (fileexists(home_filename)) and (fileexists(work_filename)) then begin
if (FileDateToDateTime(FileAge(work_filename)) <> FileDateToDateTime(FileAge(home_filename))) and (fileage(work_filename) + 3600 <> FileAge(home_filename)) and (fileage(work_filename) <> FileAge(home_filename) + 3600) then begin erg := xmessagedlg('ArchivBit wurde gesetzt' +#13 + 'Soll ' + work_filename + ' '+#13+ datetimetostr(filedatetodatetime(FileAge(work_filename))) +#13+ 'durch ' + home_filename + ' '+#13+ datetimetostr(filedatetodatetime(FileAge(home_filename))) +#13+ ' ersetzt werden?', mtConfirmation, [mbYes, mbno, mbcancel], ['ja', 'nein', 'Abbrechen'], self.font); case erg of mryes : CopyFile(PChar(home_filename), PChar(work_filename), FALSE); mrcancel : raus := true; end; end end else if (fileexists(home_filename)) and (not fileexists(work_filename)) then begin erg := xmessagedlg('Soll '+ work_filename + #13+ ' angelegt werden?', mtConfirmation, [mbYes, mbNo, mbcancel], ['ja', 'nein', 'Abbrechen'], self.font); case erg of mryes : begin if not directoryexists(ziel+uvname) then CreateDir(ziel+uvname); CopyFile(PChar(home_filename), PChar(work_filename), TRUE); end; mrcancel : raus := true; end; end; end; end end; Until FindNext(FindRec) <> 0; FindClose(FindRec);
If (Not aWithSub) or (raus) Then Exit; If FindFirst (aPath + '*.*', faAnyFile, FindRec) = 0 Then Repeat If (FindRec.Name <> '.') and (FindRec.Name <> '..') Then If Boolean (FindRec.Attr and faDirectory) Then If ((FindRec.Attr and faDirectory) <> 0) then FindFiles(aPath + FindRec.Name, aFindMask, aWithSub); Until FindNext(FindRec) <> 0; FindClose(FindRec); End; |
Uff, Detlef
_________________ ut vires desint, tamen est laudanda voluntas
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 20.01.11 23:38
Dann bleibt nur im Taskmanager bzw. besser dem Process Explorer auf die Handles zu achten und zu schauen ob und wo deren Anzahl zunimmt.
|
|
D. Annies 
      
Beiträge: 1843
windows 7
D6 Enterprise, D7 Pers und TD 2006
|
Verfasst: Fr 21.01.11 07:42
Ich habe keine Ahnung, wie ich dabei vorgehen könnte.  ((
(Nun, den Process Manager habe ich, aber damit umgehen kann ich nicht)
_________________ ut vires desint, tamen est laudanda voluntas
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 21.01.11 08:08
Im Anhang einmal ein Screenshot. Das sind die Eigenschaften eines Prozesses. Und dort steht die Handleanzahl. Wenn du jetzt im Debugger schrittweise durchgehst, siehst du wo diese steigt oder sinkt.
Und wenn sie bei der selben Operation immer weiter steigt und nie wieder auf den alten Wert zurückgeht, stimmt etwas nicht.
Einloggen, um Attachments anzusehen!
|
|
D. Annies 
      
Beiträge: 1843
windows 7
D6 Enterprise, D7 Pers und TD 2006
|
Verfasst: Fr 21.01.11 10:54
Es läuft doch darauf hinaus, dass ich da im Code einen Logikfehler eingebaut habe,
kann den jemand auch so erkennen? - Ich vermute ihn bei der Rekursion am Proc-Ende.
Ich krieg den Fehler nicht raus  (trotz guter Hilfe bisher)
Detlef
_________________ ut vires desint, tamen est laudanda voluntas
|
|
zuma
      
Beiträge: 660
Erhaltene Danke: 21
Win XP, Win7, Win 8
D7 Enterprise, Delphi XE, Interbase (5 - XE)
|
Verfasst: Fr 21.01.11 11:49
Ich find merkwürdig, das du eine Methode 'FindFiles' hat, die sucht UND kopiert, beides in einem. Mein Lösungsansatz wäre gewesen, 2 Methoden zu haben:
Eine Methode, die die zu kopierenden Dateien ermittelt (und wirklich auch nur das macht) und z.b als Liste wieder gibt
und
eine Methode, die anhand einer übergebenen Liste Dateien kopiert (ala kopiere(xDateiliste, xZiel).
dein Findclose wird erst nach abarbeiten der repeatschleife aufgerufen, du kopierst aber innerhalb der schleife.
_________________ Ich habe nichts gegen Fremde. Aber diese Fremden sind nicht von hier! (Methusalix)
Warum sich Sorgen ums Leben machen? Keiner überlebts!
|
|
D. Annies 
      
Beiträge: 1843
windows 7
D6 Enterprise, D7 Pers und TD 2006
|
Verfasst: Fr 21.01.11 12:36
Hi, zuma,
das ist richtig, aber wenn ich das Findclose in die Schleife setze, wird immer nur eine Datei
pro Verzeichnis kopiert.
Es sind zwar 1348 Dateien insgesamt, aber nicht > 1000 in einem UV!
Detlef
_________________ ut vires desint, tamen est laudanda voluntas
|
|
zuma
      
Beiträge: 660
Erhaltene Danke: 21
Win XP, Win7, Win 8
D7 Enterprise, Delphi XE, Interbase (5 - XE)
|
Verfasst: Fr 21.01.11 14:38
Hallo Detlef,
das ist richtig, aber mein Lösungsvorschlag war ja auch nicht, das FindClose in die Schleife zu verlagern, sondern deine Schleife in 2 aufzuteilen. In der jetzigen Variante wirste das Kopieren raus und merkst dir dort stattdessen die Dateie, die du kopieren möchtest (z.B. in einer Stringlist). Das Ergebnis (also die gefüllte Stringlist) übergibst du dann an die 2te, neu zu erstellende Methode, die dann das eigentliche Copy macht.
_________________ Ich habe nichts gegen Fremde. Aber diese Fremden sind nicht von hier! (Methusalix)
Warum sich Sorgen ums Leben machen? Keiner überlebts!
|
|
D. Annies 
      
Beiträge: 1843
windows 7
D6 Enterprise, D7 Pers und TD 2006
|
Verfasst: Fr 21.01.11 19:45
hab jetzt eine Menge versucht, noch ohne Erfolg: Ich scheitere an der Erstellung der Proc,
die dann für das Kopieren en bloc zuständig sein soll. Wobei ja kopiert oder ersetzt werden soll!
Wie könnte die aussehen, sprich welcher Befehl gilt da? CopyFile(), CopyFileEx() oder was?
_________________ ut vires desint, tamen est laudanda voluntas
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 21.01.11 20:04
An SHFileOperation könntest du auch gleich mehrere Dateien auf einmal übergeben.
Welchen Befehl du da nutzt, ist im Grunde nicht so wichtig. Wobei ich vermute, dass SHFileOperation mit jeweils mehreren Dateien einen Geschwindigkeitsvorteil bringen könnte.
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Fr 21.01.11 20:32
jaenicke hat folgendes geschrieben : | An SHFileOperation könntest du auch gleich mehrere Dateien auf einmal übergeben.
Welchen Befehl du da nutzt, ist im Grunde nicht so wichtig. Wobei ich vermute, dass SHFileOperation mit jeweils mehreren Dateien einen Geschwindigkeitsvorteil bringen könnte. |
Ist in der Regel 5%, teilweise bis zu 15% langsamer als die Dateien selbst mit geeigneter Puffergröße zu kopieren. Hatte da mal selber mir ein Tool geschrieben, was immer Meilenweit vor dem Explorer fertig war.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
D. Annies 
      
Beiträge: 1843
windows 7
D6 Enterprise, D7 Pers und TD 2006
|
Verfasst: Fr 21.01.11 20:40
Aber leider nicht mit D6Enter. 
_________________ ut vires desint, tamen est laudanda voluntas
|
|
D. Annies 
      
Beiträge: 1843
windows 7
D6 Enterprise, D7 Pers und TD 2006
|
Verfasst: Sa 22.01.11 08:17
So, ich hab's gelöst:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| if (fileexists(home_filename)) and (not fileexists(work_filename)) then begin erg := xmessagedlg('Soll '+ work_filename + #13+ ' angelegt werden?', mtConfirmation, [mbYes, mbNo, mbcancel], ['ja', 'nein', 'Abbrechen'], self.font); case erg of mryes : begin if not directoryexists(ziel+uvname) then CreateDir(ziel+uvname); CopyFile(PChar(home_filename), PChar(work_filename), TRUE);
end; mrcancel : raus := true; end; end; |
Ich lasse die xmessagedld-Abfrage weg, nur die drei Zeilen "in der Mitte" lasse ich stehen, damit auf jeden Fall
(ohne Nachfrage) kopiert wird!
Yes! Uff!
Gruß, Detlef
P.S. Weiß jemand, warum das die Handles "spart"?
_________________ ut vires desint, tamen est laudanda voluntas
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 22.01.11 09:10
D. Annies hat folgendes geschrieben : | P.S. Weiß jemand, warum das die Handles "spart"? |
Naja, ich weiß ja nicht was xmessagedlg für eine Funktion ist, aber ich könnte wetten, dass da etwas nicht freigegeben wird...
Vielleicht der angezeigte Dialog selbst? Der beinhaltet natürlich gleich mehrere Handles und Objekte.
Mit FastMM kannst du solche nicht freigegebenen Sachen aber auch finden.
|
|
|