Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Dateien mit Pfad kopieren (https://www.delphipraxis.net/206538-dateien-mit-pfad-kopieren.html)

Willie1 2. Jan 2021 17:08

Dateien mit Pfad kopieren
 
Hallo Leute,
ich bin mit dem Umbenennen der Dateien fertig, um die Bilder auf dem Bilderrahmen in der gewünschten Reihenfolge zu zeigen.
Jetzt will ich diese Struktur auf die SD-Karte kopieren unter Beibehalt der Ordner.
Beispiel: Bild.Rahmen\Aachen1\Bilddateien Bild.Rahmen\HochzeitOllie\... usw.
Das habe ich noch nie gemacht. Ich benutze SHFileOperation. Als pFrom gebe ich die Dateien mit vollem Pfad, als pTo die (Ziel-)Pfade an. Das gibt zwar keine Fehlermeldung aber es wird nur eine Datei Aachen1 angelegt.
Was mache ich falsch, geht das überhaupt mit SHFileOperation ?
Gruß Willie.

zeras 2. Jan 2021 18:43

AW: Dateien mit Pfad kopieren
 
Versuche es doch mal so. Ich hoffe, dass es diese Funktionen schon in deiner Delphi Version gibt.
Delphi-Quellcode:

uses
 System.IOUtils;

procedure TForm29.Button1Click(Sender: TObject);
begin
  TDirectory.copy(Src, Dst);
end;

mmw 2. Jan 2021 18:54

AW: Dateien mit Pfad kopieren
 
Hallo,

Delphi-Quellcode:
TDirectory.Copy();


sollte nicht funktionieren.

lt. Online-Hilfe "Copy löst eine Exception aus, wenn die angegebenen Pfade ungültig oder nicht vorhanden sind, oder wenn kein Zugriff auf sie möglich ist. "

Im Prinzip sollte es mit SHFileOperation aber funktionieren.

aber ohne SRC kann man das natuerlich schwer sagen.

Gruß

Poelser 2. Jan 2021 19:12

AW: Dateien mit Pfad kopieren
 
Hab' jetzt zwar kein Delphi zur Hand, aber in 10.1 gibt's TDirectory.
Damit sollte Copy gehen. Um eine Exception zu vermeiden, falls dst nicht existiert, vorher Pfad extrahieren und mit ForceDirectory drauf los.

Gruß aus dem hohen Norden, Edmund

gast2019 2. Jan 2021 20:42

AW: Dateien mit Pfad kopieren
 
https://www.wintotal.de/tipp/xcopy-parameter/

wenn's auch ohne Delphi sein darf :wink:

Ein gutes Neues wünsche ich!

Willie1 3. Jan 2021 18:09

AW: Dateien mit Pfad kopieren
 
Hallo, zunächst vielen Dank für eure schnellen Antworten.
Mit TDirectory.Copy(src, dest) geht es, wenn man bei dest den Ordner anhängt. Es gibt keine Exception, auch wenn der Zielordner nicht existiert.
Aber dann müsste es doch auch mit SHFileOperation klappen. Da gibt es Fortschrittsbalken, ich will sehr viele Bilder auf ein langsames Medium (SD) kopieren.
Delphi-Quellcode:
procedure TForm1.Button4Click(Sender: TObject);
var
  dir, pa, fi, s: string;
  i: Integer;
begin
  if SelectDirectory('Zielordner auswhlen','Computer',Dir,[sdNewUI,sdNewFolder]) then begin
    Dir := IncludeTrailingPathDelimiter(Dir);
    for i:=0 to NewList.Count - 1 do begin
      s := ExcludeTrailingPathDelimiter(NewList.GetPath(i));
      s := Copy(s, LastDelimiter('\', s)+1, MAXINT);
      pa := Dir + s + '\';
      fi := NewList.GetPathName(i);
      CopyFiles(pa, fi ,false);
    end;
  end;
end;
Delphi-Quellcode:
 function CopyFiles(DestFolder: string; const Files: array of string; WithConfirm: Boolean;
                     Move: Boolean=false): Boolean;
    var
      SHFOS: TSHFileOpStruct;
      i: Integer;
      s: string;
  begin
    s:='';
    for i:=Low(Files) to High(Files) do s:=s + Files[i] + #0;
    s:=s + #0;
    with SHFOS do begin
      Wnd:=0;
      if Move then wFunc:=FO_MOVE else wFunc:=FO_COPY;
      pFrom:=PChar(s);
      pTo:=PChar(DestFolder);
      fFlags:=FOF_NOCONFIRMATION;    //ohne Rückfrage
      if WithConfirm then fFlags:=0;
      fAnyOperationsAborted:=false;
      hNameMappings:=nil;
    end;
    Result:=(ShFileOperation(SHFOS) = 0) and (SHFOS.fAnyOperationsAborted = LongBool(false));
  end; {CopyFiles}
Willie.
Nachtrag: Wenn ich das Kopieren des Ordner mit dem Explorer ausführe, geht es doch auch!

mmw 3. Jan 2021 18:45

AW: Dateien mit Pfad kopieren
 
hallo,

Delphi-Quellcode:
 for i:=Low(Files) to High(Files) do s:=s + Files[i] + #0;
    s:=s + #0;
wäre es nicht besser so -

Delphi-Quellcode:
  for i:=Low(Files) to High(Files) do begin
     s:=''
     s:=s + Files[i] + #0#0
  CopyFiles(...)
   end;
wäre einfacher der Funktion nur die Datei zu übergeben die kopiert werden soll.

gruß

Willie1 5. Jan 2021 11:12

AW: Dateien mit Pfad kopieren
 
Hallo Leute,
ich habe im Explorer schon oft einen Ordner (mit Unterordnern) in ein Verzeichnis eines anderen Laufwerks kopiert, z.B. Delphi-Projekte.
Das muss doch auch programmgesteuert gehen! Mit TDirectory.Copy läuft es nicht. Ich kann zwar einen Unterordner benennen, er wird auch angelegt, aber nicht die gesamte Ordnerstruktur.
Meine Funktion CopyFiles benutze ich seit 15 Jahren.
Ich bin sicher, einer oder mehr von euch wissen, wie es geht.

Übrigens, wünsche ich euch noch ein gutes, neues Jahr.
Willie.

himitsu 7. Jan 2021 21:23

AW: Dateien mit Pfad kopieren
 
Zitat:

Das gibt zwar keine Fehlermeldung
Hast du den auch die Rückgaben geprüft, ob es nicht doch einen Fehler gab?
Von selbst passiert da nix.

Delphi-Referenz durchsuchenTDirectory.GetFiles


Zitat:

Delphi-Quellcode:
SHFOS.fAnyOperationsAborted = LongBool(false)

Niemals mit Booleans vergleichen ... immer nur als Zuweisung.
Ach ja, auch wenn es beim "False" gehen wird, aber beim True knallt es gern schnell.
PS: Es ist schon ein "Bool".

Delphi-Quellcode:
not SHFOS.fAnyOperationsAborted



Ach ja, ist denn bei einem Fehler überhaupt fAnyOperationsAborted "gültig"?

mmw 8. Jan 2021 17:25

AW: Dateien mit Pfad kopieren
 
hallo,

laut Online -Hilfe (MS)

Note This string must be double-null terminated.

das gilt für quelle und ziel

das scheint bei pa nicht der Fall zu sein.

ich habs mal so umgesetzt. (auszug)

Delphi-Quellcode:
     source_file:= src_file+#0#0;
     destination_file:= dest_file+#0#0;

     with SHFOS do begin
       Wnd:=0;
       pFrom:=PChar(source_file);
       pTo:=PChar(destination_file);
vielleicht hilft's
gruß

himitsu 8. Jan 2021 17:59

AW: Dateien mit Pfad kopieren
 
Zitat:

Zitat von mmw (Beitrag 1480610)
laut Online -Hilfe (MS)

Note This string must be double-null terminated.

Das ist kein Problem.

Delphi-Strings haben bereits eine integrierte Doppel-0 am Ende, nach dem letzten Char, welche beim Cast in den PChar ebenfalls drin bleiben.
Ausnahme ist der ShortString. (der hat ausschließlich ein Längenbyte davor und keine #0 dahinter)
Beim WideString weiß ich es grade nicht, aber vermutlich auch. (genaueres siehe BSTR von Microsoft ... #0 ist drin, aber bei #0#0 bin ich nicht sicher)


Man kann also selbst die Null(en) anhängen, oder kann es beruhigt weglassen und die impliziten #0#0 verwenden.


Die Beiden sind "String-Listen", also #0 zwischen den einzelnen Einträgen und #0#0 (also ein Leerstring #0''#0 ) als Ende.

mmw 8. Jan 2021 18:28

AW: Dateien mit Pfad kopieren
 
Hallo,
stimmt. wäre jetzt auch nur wegen dem s:=s + #0;

Bei mir funktioniert's mit SHFileOperation mit oder ohne.

Gruß

himitsu 9. Jan 2021 00:17

AW: Dateien mit Pfad kopieren
 
Hast du dir mal überlegt genausoviele Einträge ins TO einzufügen, wie ins FROM?
In der Hilfe steht nichts davon, dass "ein" Ziel für mehrere/alle Quellen gilt. (auch wenn es zu praktisch wäre, wenn es so sein sollte)

Wenn du nicht alle Felder im Record zuweist, dann solltest du den Record am Anfang unbedingt mit Nullen initialisieren.
FillChar bzw. FillMemory
Auch wenn man alles zuweist, so sollte/könnte man es dennoch immer machen ... einmal kann man es so nie vergessen, wenn man es immer macht und auch eventuelle FillBytes (allignment) werden mit geleert.


Warum eigentlich
Delphi-Quellcode:
Copy(s, LastDelimiter('\', s)+1, MAXINT)
anstatt einem einfachem ExtractFileName?

Reinhold 9. Jan 2021 08:59

AW: Dateien mit Pfad kopieren
 
Hallo,

wenn ich, Dich richtig verstanden habe hast du eine Verzeichnisstruktur der folgenden Art hast:
C:\Bilder\Delphi\Programmme
in der sich mehere Dateien befinden und in
F:\Bilder\Delphi\Programme
speichern möchtest.

Um dies zu machen mußt Du als erstes dir die Verzeichniststruktur vom Zielsystem zusammen bauen und danach kopieren.
Das ich wie folgt machen würde.

Delphi-Quellcode:
//zB:
// Source = 'C:\Bilder\Delphi\Programmme';
//Dest = 'G:/';

// nur Path ohne Dateinamen
procedure CopyPath(const SourcePath, DestPath: string);
var
  Dest: string;
  Dir: TDirectory;
begin
  Dest:= ExcludeTrailingPathDelimiter(DestPath);
  Dest:= StringReplace(Source,ExtractFileDrive(Source),Dest,[]);
  Dir.Copy(Source,Path);
end;

Willie1 9. Jan 2021 18:25

AW: Dateien mit Pfad kopieren
 
Zitat:

Warum eigentlich Copy(s, LastDelimiter('\', s)+1, MAXINT) anstatt einem einfachem ExtractFileName?
Ich habe als Source einen Verzeichnisbaum: Bilder\Aachen1 Bilder\HochzeitOllie Bilder\HochzeitOllie\Paar Bilder\ZuHause Bilder\Blumen1 usw. .
Der Bilderrahmen sortiert die Bilder ohne Rücksicht auf die Ordner nur nach dem Dateinamen. Alse binde ich den Ordner in den Dateinamen mit ein und ändere den Dateinamen in das Aufnahmedatum Form: Ordnername#JJJJ.MM.TT-SS.mm.ss.jpg. Dann werden die Bilder in der richtigen Reihenfolge angezeigt. Ich muss nur darauf achten, falls es mehrere Fotografen gibt.
Jetzt will ich diese Ordnerstruktur auf die SD-Karte kopieren. Das sind ca. 1000 Bilder und das dauert, deshalb wäre eine Fortschrittsanzeige nützlich. Mit ShellExecute(...XCopy...) geht es, aber es ist nicht zu sehen, wann der Kopiervorgang zu Ende ist. Deshalb will ich SHFileOperation benutzen.
Reinhold, deinen Ansatz muss ich ausprobieren.
Willie.

Moombas 11. Jan 2021 07:43

AW: Dateien mit Pfad kopieren
 
Bin etwas verwirrt gerade was dieses Thema angeht, also korrigiert mich wenn ich jetzt falsch liege.
Es soll doch Ordner X mit allen Unterordnern an einen neuen Ort kopiert werden (Durch beibehalten aller Dateinamen und (Unter-)Ordnernamen bleibt dann die Struktur auch erhalten, richtig?

In Lazarus mache ich das aktuell so (nicht vom Widestring irritieren lassen):
Delphi-Quellcode:
copydir(Source, Destination);
Delphi-Quellcode:
//Verzeichnis kopieren
function CopyDir(SourceDirectory: WideString; DestinationDirectory: WideString): boolean;
var
  SHFileOpStruct: TSHFileOpStruct;
  SourceBuffer, DestinationBuffer: array[0..255] of char;
  res: integer;
begin
  try
    if not SysUtils.DirectoryExists(SourceDirectory) then
    begin
      Result := False;
      exit;
    end;
    Fillchar(SHFileOpStruct, sizeof(SHFileOpStruct), 0);
    FillChar(SourceBuffer, sizeof(SourceBuffer), 0);
    FillChar(DestinationBuffer, sizeof(DestinationBuffer), 0);
    StrPCopy(SourceBuffer, String(SourceDirectory));
    StrPCopy(DestinationBuffer, String(DestinationDirectory));
    with SHFileOpStruct do
    begin
      Wnd := 0;
      wFunc := FO_COPY;
      pFrom := @SourceBuffer;
      pTo := @DestinationBuffer;
      fFlags := FOF_ALLOWUNDO;
      hNameMappings := nil;
      lpszProgressTitle := nil;

      fFlags := fFlags or FOF_NOCONFIRMATION;
      fFlags := fFlags or FOF_SILENT;
      fFlags := fFlags or FOF_SIMPLEPROGRESS;
      fFlags := fFlags or FOF_NOCONFIRMMKDIR;
    end;
    res := SHFileOperation(SHFileOpStruct);
    Result := (res = 0);

    if not Result then
    begin
      ShowMessage(SysErrorMessage(GetLastError));
    end;
  except
    Result := False;
  end;
end;
Das funktioniert einwandfrei bisher.

himitsu 12. Jan 2021 05:05

AW: Dateien mit Pfad kopieren
 
Zitat:

Zitat von Moombas (Beitrag 1480710)
Das funktioniert einwandfrei bisher.

Ähhhhhhhhhhhhhhh ... nein.

Mit BufferOverflow, wenn die Pfade länger als 256 255 sind.
Selbst mit MAX_PATH darf es schon 260 sein (3 für "C:\" + 256 für den Pfad + eine #0) und Windows hat in vielen APIs seit 'ner Weile auch endlich das MAX_PATH als Grenze aufgehoben und es darf auch ohne UNC nun länger sein (mit UNC auch schon seit ewig länger)

und wenn das als ANSI kompiliert wurde, dann raucht der Code mit Unicodedateinamen auch wunderbar ab.


Wenn schon WideString als Eingang, warum dann nicht direkt die UnicodeAPI verwenden?
SHFileOperationW und vermutlich TSHFileOpStructW
und das nutzlose Umkopieren der Strings auch weglassen.

Zitat:

Delphi-Quellcode:
  except
    Result := False;
  end;

Für sowas sollte man mindestens gesteinigt, ausgepeitscht, gevierteilt, geköpft und vorallem die Hände abgehackt bekommen.
Zitat:

Delphi-Quellcode:
ShowMessage

Und dafür tritt dir hinterher auch noch Derjenige in die Eier den Arsch, nachdem er versucht hatte diese Funktion in ein eigenes Try-Except zu packen.

Moombas 12. Jan 2021 07:53

AW: Dateien mit Pfad kopieren
 
Ich habe die Funktion bisher auch nur übernommen, kommt nicht von mir selber und habe ich keine Hand mehr angelegt und die Funktion nicht weiter betrachtet.
Und bisher hat es (ob du willst oder nicht) immer funktioniert.

Das bei mir deine Beschriebenen Fälle nicht aufgetreten sind/auftreten werden kann natürlich sein.

Willie1 13. Jan 2021 16:42

AW: Dateien mit Pfad kopieren
 
Zitat:

Bin etwas verwirrt gerade was dieses Thema angeht, also korrigiert mich wenn ich jetzt falsch liege.
Es soll doch Ordner X mit allen Unterordnern an einen neuen Ort kopiert werden (Durch beibehalten aller Dateinamen und (Unter-)Ordnernamen bleibt dann die Struktur auch erhalten, richtig?
Hallo, genau so ist es. Ich denke, meine Anfrage ist ein realistisches Problem, das auch in anderen Zusammenhang vorkommen kann.
Ich bleibe zunächst bei meiner Lösung mit Xcopy. Sie mag höheren Ansprüchen nicht genügen aber sie funktioniert.
Willie.


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:51 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