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/)
-   -   CopyFile Datei wird nicht überschrieben (https://www.delphipraxis.net/186916-copyfile-datei-wird-nicht-ueberschrieben.html)

Dennis07 11. Okt 2015 18:26

CopyFile Datei wird nicht überschrieben
 
Hallo,
ich habe mal wieder ein Problem. Und zwar möchte ich eine Datei Kopieren und gegebenenfalls überscheiben.
Hierzu nutze ich die Funktion "CopyFile(...)".
Ich weise den Parameter "FailIfExists" durch das ergebnis eines MessageDlg's zu.
Das ganze sieht wie Folgt aus:

Delphi-Quellcode:
var
  Index: Integer;
  NewFolder: String;
  FailIfExists: Boolean;
begin
  NewFolder := GetEnvironmentVariable('USERPROFILE') + '\Documents\';
  for Index := 0 to ListBox1.Items.Count - 1 do
  begin
    if ListBox1.Selected[Index] = True then
    begin
      if FileExists(NewFolder + ChangeFileExt(ListBox1.Items.Strings[Index],'.txt')) = True then
      begin
        FailIfExists := (MessageDlg('Die Datei "' + ListBox1.Items.Strings[Index] + '" existiert bereits.' + sLineBreak + 'Soll diese überschieben werden?',mtWarning,mbYesNo,0) <> mrYes);
      end;
      CopyFile(PChar(CurrentFolder + '\' + ChangeFileExt(ListBox1.Items.Strings[Index],'.txt')),PChar(NewFolder + ChangeFileExt(ListBox1.Items.Strings[Index],'.txt')),FailIfExists);
    end;
  end;
Es wird eine Datei kopiert, falls die Zieldatei nicht vorhanden ist. Außerdem wird die Variable "FailIfExists" korrekt zugewiesen (True, falls die Datei nicht überschrieben werden soll und False, falls die Datei überschrieben werden soll). Allerdings wird die Datei, auch wenn "FailIfExists" auf False steht, nicht überschrieben. "RaiseLastOSError" zeigt nichts verdächtiges an und es wird auch in den virtualisierten Verzeichnissen nichts angelegt.

Könnte mir jemand sagen, woran dies liegt?

Danke!

zeras 11. Okt 2015 18:46

AW: CopyFile Datei wird nicht überschrieben
 
Ich kann zwar im Moment nicht testen, aber solche Konstrukte wie

Delphi-Quellcode:
if ListBox1.Selected[Index] = True then
kommen nicht immer gut.
Nimm einfach

Delphi-Quellcode:
if ListBox1.Selected[Index]then
bei allen boolschen Vergleichen.
Das kommt bei dir öfters vor.

Auch sollte man, wenn man eine Variable mehrmals verwendet, diese erst einmal zwischenspeichern. Das erhöht die Übersicht.
Beispielsweise kommt
Delphi-Quellcode:
ListBox1.Items.Strings[Index]
öfters vor.
Nimm eine lokale Variable, bsp.
Delphi-Quellcode:
Filename := ListBox1.Items.Strings[Index]
und ersetze die weiteren Abfragen dann immer mit Filename.

Dennis07 11. Okt 2015 18:58

AW: CopyFile Datei wird nicht überschrieben
 
Ja, grundsätzlich ist das aber egal.
Außerdem habe ich bereits überprüft, "FailIfExists" ist/wird korrekt gesetzt. Daran liegt es nicht. Die "CopyFile"-Methode ansich scheint Probleme zu machen.

zeras 11. Okt 2015 19:00

AW: CopyFile Datei wird nicht überschrieben
 
Zitat:

Zitat von Dennis07 (Beitrag 1318335)
Ja, grundsätzlich ist das aber egal.

Da wirst du im Forum etliche Einträge finden, dass es NICHT egal ist!

Dennis07 11. Okt 2015 19:18

AW: CopyFile Datei wird nicht überschrieben
 
Ich meinte damit nicht, dass es "komplett egal" sei, sondern dass es für dieses Szenario keinen Unterschied macht. Und das stimmt auch. Das ganze hat afaik nur eine auswirkung auf manche API-Sachen wegen der BOOL-Boolean-Inkompatibilität. Bei nativer VCL ist das aber soweit ich weiß sowieso irrelevant. Und wenn man die Vergleiche mit True weglässt, kommt man ja auch aufs selbe Ergebnis. Nähmlich, dass CopyFile nicht überschreibt.

zeras 11. Okt 2015 19:35

AW: CopyFile Datei wird nicht überschrieben
 
Ändere doch mal die letzte Zeile Copyfile wie unten beschrieben und schaue dir die Strings an. Dann wirst du merken, dass deine Dateinamensangaben nicht passen. Du nimmst gleich den neuen Namen, anstatt den Quellnamen.

Delphi-Quellcode:

var

  s1, s2: String;


....
     s1 := CurrentFolder + '\' + ChangeFileExt(fName,'.txt');
      s2 := NewFolder + ChangeFileExt(fName,'.txt');
      if not CopyFile(PChar(s1), PChar(s2), FailIfExists)then
  ShowMessage('Fehler beim Erstellen der Kopie!'#13#10 + SysErrorMessage(GetLastError));

Dennis07 11. Okt 2015 19:44

AW: CopyFile Datei wird nicht überschrieben
 
Nein. Hatte aber bereits auch schon gesagt, dass kein Fehler auftritt und die Funktion "True" zurückgibt. Trotzdem wird die Datei nicht überschrieben.
Und die Namen passen soweit. Beim erstmaligen Kopieren (wo die Zieldatei ja noch nicht existiert) passt es ja auch und die Datei wird problemlos kopiert.

zeras 11. Okt 2015 20:03

AW: CopyFile Datei wird nicht überschrieben
 
Und was bringt ShowMessage hinter dem Copyfile?

Dennis07 11. Okt 2015 20:13

AW: CopyFile Datei wird nicht überschrieben
 
Wie ich bereits sagte: Es wird nicht aufgerufen, wenn die Datei noch nicht existiert oder wenn diese überscrhieben werden soll.
Und wenn diese nicht überschrieben werden soll, dann wird ShowMessage aufgerufen und zeigt an, dass die Zieldatei bereits existiert und deswegen nicht Kopiert werden kann.
Also soweit alles im grünen Bereich ohne Auffälligkeiten.
Nur, wird die Datei halt nicht überschrieben, wenn sie das eigentlich sollte.

zeras 11. Okt 2015 20:26

AW: CopyFile Datei wird nicht überschrieben
 
Wenn Copyfile nicht erfolgreich ist, muss ShowMessage aufgerufen werden mit

Delphi-Quellcode:
SysErrorMessage(GetLastError));
Da siehst du, warum das fehlschlug.
Bitte deinen Code entsprechend ändern, wie von mir oben beschrieben und die Meldung posten.

Außerden wird FailIfExists nicht initialisiert. Das sollte auch gemacht werden.

Dennis07 11. Okt 2015 20:56

AW: CopyFile Datei wird nicht überschrieben
 
Zitat:

Zitat von zeras (Beitrag 1318349)
Wenn Copyfile nicht erfolgreich ist, muss ShowMessage aufgerufen werden

Eben nicht. Das ist ja mein Problem: Es wird nichts überschrieben, obwohl kein Fehler ausgelöst wurde und auch obwohl Copyfile True zurückgibt (also folglich ShowMessage nicht ausgeführt wird).

Zitat:

Zitat von zeras (Beitrag 1318349)
Außerden wird FailIfExists nicht initialisiert. Das sollte auch gemacht werden.

Nö, wieso? Ist doch egal was drinsteht, solange sichergestellt wurde, dass die Datei nicht existiert...

Luckie 11. Okt 2015 22:11

AW: CopyFile Datei wird nicht überschrieben
 
Räum deinen Code doch erst mal auf. Speicher den zusammengebastelten Pfad mal in einer Variablen zwischen. Dann guckst du mal, ob da auch das drin steht, was du erwartest.

Dalai 12. Okt 2015 01:14

AW: CopyFile Datei wird nicht überschrieben
 
Zitat:

Zitat von Dennis07 (Beitrag 1318339)
Das ganze hat afaik nur eine auswirkung auf manche API-Sachen wegen der BOOL-Boolean-Inkompatibilität.

Äh, ja genau darum geht's ja hier. CopyFile will einen BOOL und eben keinen Boolean. Ich wage einfach mal zu behaupten, dass das die Ursache für das Nicht-Überschreiben ist.

Übrigens empfehle ich, die Funktion Format() zu benutzen, um Pfade zusammenzusetzen, denn solche String-Zusammensetzungs-Orgien sind überaus unübersichtlich. Weiterhin empfehle ich, davon Abstand zu nehmen, Standardpfade aus Umgebungsvariablen zu ermitteln, denn dafür gibt es passende Funktionen (SHGetSpecialFolderPath und wie sie alle heißen); das schließt auch das bei dir hartcodierte Verzeichis "Documents" mit ein.

MfG Dalai

Dennis07 12. Okt 2015 02:18

AW: CopyFile Datei wird nicht überschrieben
 
Oh, danke, wusst ich gar nicht, das mit dem SHFolderDingsta... werd ich mir mal ansehen, danke.

p80286 12. Okt 2015 11:04

AW: CopyFile Datei wird nicht überschrieben
 
Delphi-Quellcode:
var
  Index: Integer;
  NewFolder: String;
  FailIfExists: Boolean;
begin
  NewFolder := GetEnvironmentVariable('USERPROFILE') + '\Documents\';
  for Index := 0 to ListBox1.Items.Count - 1 do
  begin
    if ListBox1.Selected[Index] = True then
    begin
      if FileExists(NewFolder + ChangeFileExt(ListBox1.Items.Strings[Index],'.txt')) = True then
      begin
        FailIfExists := (MessageDlg('Die Datei "' + ListBox1.Items.Strings[Index] + '" existiert bereits.' + sLineBreak + 'Soll diese überschieben werden?',mtWarning,mbYesNo,0) <> mrYes);
      end;
      CopyFile(PChar(CurrentFolder + '\' + ChangeFileExt(ListBox1.Items.Strings[Index],'.txt')),PChar(NewFolder + ChangeFileExt(ListBox1.Items.Strings[Index],'.txt')),FailIfExists);
    end;
  end;
was passiert den in dem vollkommen unwahrscheinlichen Fall, daß es
Delphi-Quellcode:
NewFolder + ChangeFileExt(ListBox1.Items.Strings[Index],'.txt'
nicht gibt?

Richtig,
Delphi-Quellcode:
 CopyFile
arbeitet mit einem zufälligen Wert der in
Delphi-Quellcode:
FailIfExists
steht.

(woher kommt eigentlich diese unsägliche Unsitte "if irgendwas = True" ? gibt es irgendeinen Java oder BASCIC -Dialekt der das so benötigt?)

Gruß
K-H

Dennis07 12. Okt 2015 16:03

AW: CopyFile Datei wird nicht überschrieben
 
Zitat:

Zitat von p80286 (Beitrag 1318385)
was passiert den in dem vollkommen unwahrscheinlichen Fall, daß es
Delphi-Quellcode:
NewFolder + ChangeFileExt(ListBox1.Items.Strings[Index],'.txt'
nicht gibt?

Kannst du nicht wissen, kann aber nicht passieren. Das hat was damit zu tun, wie ich an die Einträge der Listbox komme. Ich hab hier ja nicht mein gesammtes Programm gepostet.. :D

Zitat:

Zitat von p80286 (Beitrag 1318385)
woher kommt eigentlich diese unsägliche Unsitte "if irgendwas = True" ? gibt es irgendeinen Java oder BASCIC -Dialekt der das so benötigt?

Nicht wirklich, nein. Ist noch ne dumme angewohnheit, die ich aus Assembly übernommen hatte. Mal sehen, vielleicht gewöhn ich mir das wieder ab... :D

hoika 13. Okt 2015 03:14

AW: CopyFile Datei wird nicht überschrieben
 
Hallo,
wie ist der Rückgabewert von CopyFile und GetLastError?

Hier noch mal die Beschreibung:

https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx


Heiko

Dennis07 13. Okt 2015 16:38

AW: CopyFile Datei wird nicht überschrieben
 
Hatte ich bereits oben mehrfach gepostet. Egal, ich lösche die Datei jetzt einfach, falls dieses erwünscht ist und dann wird sie komplett neu erstellt beim Kopieren, oder halt nicht. Das klappt problemlos.
Danke trotzdem für eure Hilfe!

MfG

hoika 14. Okt 2015 04:26

AW: CopyFile Datei wird nicht überschrieben
 
Hallo,
es ist trotzdem schade, dass du keine der Hilfen annimmst,
wie z.B. mal lokale Variablen zu benutzen.
FailIfExists ist nicht initialisiert, wenn die Datei nicht existiert.

Mach das ganze doch auch für Dich und uns übersichtlicher und stell den Code noch mal hier rein.

Mit SearchEverything kannst du sehr schnell nach einer Datei suchen,
wer weiß, wo die ist . . .

Heiko

Dennis07 14. Okt 2015 07:34

AW: CopyFile Datei wird nicht überschrieben
 
Denkst du, das habe ich nicht?
Ich war schon bevor ich hier gepostet habe so weit, dass ich wusste, dass es an der CopyFile-Methode selbst liegen muss. Scheinbar irgendwas auf meinem System ist da Fehlerhaft. Die Variablen stimmen und es werden die Methoden und Variablen korrekt konfiguriert. Auch die Lösungswege, die ihr geostet habt (die im grunde identisch sind mit dem, was ich sonst noch so versucht habe) funktionierten nicht.

Sir Rufo 14. Okt 2015 09:02

AW: CopyFile Datei wird nicht überschrieben
 
Also das funktioniert ganz wunderbar
Delphi-Quellcode:
uses
  System.IOUtils,
  System.SysUtils,
  System.Types;

procedure CopyFiles(
  const SourceFiles     : array of string;
  const DestinationFolder: string;
  FileExistsCallback    : TFunc<string, Boolean>;
  FileFailCallback      : TProc<string, string> );
var
  Index        : Integer;
  Source, Target: string;
  FailIfExists : Boolean;
  LastError    : Cardinal;
begin
  for index := low( SourceFiles ) to high( SourceFiles ) do
    begin
      Source      := SourceFiles[ index ];
      Target      := TPath.Combine( DestinationFolder, TPath.GetFileName( Source ) );
      FailIfExists := True;

      while True do
        begin
          if not CopyFile( PChar( Source ), PChar( Target ), FailIfExists )
          then
            begin
              LastError := GetLastError;
              if ( LastError <> ERROR_FILE_EXISTS ) or not FailIfExists
              then
                begin
                  FileFailCallback( Source, SysErrorMessage( LastError ) );
                  Break;
                end;

              if not FileExistsCallback( Source )
              then
                begin
                  FileFailCallback( Source, 'UserChoice' );
                  Break;
                end;

              FailIfExists := False;
            end
          else
            Break;
        end;
    end;
end;

procedure TForm1.Button1Click( Sender: TObject );
var
  SourceFiles     : TStringDynArray;
  DestinationFolder: string;
begin
  SourceFiles      := TDirectory.GetFiles( TPath.GetDocumentsPath );
  DestinationFolder := TPath.GetTempPath;

  ListBox1.Items.Clear;

  CopyFiles( SourceFiles, DestinationFolder,
    function( Filename: string ): Boolean
    begin
      ListBox1.Items.Add( 'EXISTS: ' + Filename );
      Result := MessageDlg(
        {} string.Format( 'Die Datei %s existiert bereits' + sLineBreak + 'Soll diese überschrieben werden?', [ Filename ] ),
        {} mtWarning,
        {} mbYesNo,
        {} 0 ) = mrYes;
    end,
    procedure( Filename, Reason: string )
    begin
      ListBox1.Items.Add( 'FAILS: ' + Filename + ' REASON: ' + Reason );
    end );
end;

ergo2000 14. Okt 2015 09:04

AW: CopyFile Datei wird nicht überschrieben
 
Ersetze doch einfach mal CopyFile(... mit IOUtils.TFile.Copy(...
vielleicht so:

Delphi-Quellcode:
...
uses IOUtils, ...

function IO_CopyFile(dQuelle,dZiel:string):boolean;
begin
 Result:=false;
 if IOUtils.TFile.Exists(ExtractFilePath(dQuelle) + ExtractFileName(dQuelle)) then
     try
       //falls das Ziel-VZ nicht existiert, dann erstellen:
        if not TDirectory.Exists(ExtractFilePath(dZiel)) then
                                   IOUtils.TDirectory.CreateDirectory(ExtractFilePath(dZiel));
                 
      IOUtils.TFile.Copy(dQuelle,dZiel,true);

.....
      Result:=true;
....
     except
     end;
end;
Bei mir funktioniert diese Variante unter allen Windows-Versionen einwandfrei. Mit copyfile(... hatte ich zuvor auch gelegentlich so einige "Probleme".

Ralf

Dennis07 14. Okt 2015 11:59

AW: CopyFile Datei wird nicht überschrieben
 
Alles klar, danke. Beide wege funktionieren komischerweise. :)
Scheint wohl tatsächlich Probleme zu machen, die CopyFile-Methode...

Problem gelöst, danke!

Sir Rufo 14. Okt 2015 12:28

AW: CopyFile Datei wird nicht überschrieben
 
Zitat:

Zitat von Dennis07 (Beitrag 1318661)
Alles klar, danke. Beide wege funktionieren komischerweise. :)
Scheint wohl tatsächlich Probleme zu machen, die CopyFile-Methode...

Problem gelöst, danke!

:gruebel: ich verwende aber
Delphi-Quellcode:
CopyFile
... ohne Probleme. Dann scheint das Problem wohl doch in deinem Code zu sein, gelle?

Dennis07 14. Okt 2015 20:30

AW: CopyFile Datei wird nicht überschrieben
 
Zitat:

Zitat von Sir Rufo (Beitrag 1318670)
:gruebel: ich verwende aber
Delphi-Quellcode:
CopyFile
... ohne Probleme. Dann scheint das Problem wohl doch in deinem Code zu sein, gelle?

Naja, aber dann wohl nicht nur in meinem. Denn alle anderen Lösungen hier funzten genauso wenig :zwinker:

Sir Rufo 14. Okt 2015 20:34

AW: CopyFile Datei wird nicht überschrieben
 
Zitat:

Zitat von Dennis07 (Beitrag 1318724)
Zitat:

Zitat von Sir Rufo (Beitrag 1318670)
:gruebel: ich verwende aber
Delphi-Quellcode:
CopyFile
... ohne Probleme. Dann scheint das Problem wohl doch in deinem Code zu sein, gelle?

Naja, aber dann wohl nicht nur in meinem. Denn alle anderen Lösungen hier funzten genauso wenig :zwinker:

Es gibt halt mehr falsch als richtig, darum ist die Trefferquote für richtig auch so gering.

Die Hinweise hier waren aber so gesehen richtig. Wie du die umgesetzt hast kann ich nicht beurteilen.

Macht man alles richtig, funktioniert es im Normalfall auch ;)

Dennis07 14. Okt 2015 22:27

AW: CopyFile Datei wird nicht überschrieben
 
Zitat:

Zitat von Sir Rufo (Beitrag 1318726)
Die Hinweise hier waren aber so gesehen richtig.

Hab ich auch nie in Frage gestellt. :)

Zitat:

Zitat von Sir Rufo (Beitrag 1318726)
Wie du die umgesetzt hast kann ich nicht beurteilen.

Copy & paste... :D

Zitat:

Zitat von Sir Rufo (Beitrag 1318726)
Macht man alles richtig, funktioniert es im Normalfall auch

Der "Normalfall"... jaja, das geile daran ist ja dass der selbst so gut wie nie eintrifft...

Lyan 21. Okt 2015 19:00

AW: CopyFile Datei wird nicht überschrieben
 
Ohne jetzt alle 26 Antworten gelesen zu haben, meine erste Vermutung wäre dass das FailIfExists der Fehler ist.

Wenn ich mich nicht irre, dann ploppt die MsgBox auf "Möchten sie die datei übschreiben [...] ?" [Yes, No].

Wenn man dort dann Yes auswählt, dann wird true zurückgeliefert, was die Variable FailIfExist auch auf true setzt.

Demnach wird bei CopyFile(,,True) übergeben und somit failed logischreweise das Replace.

Sir Rufo 21. Okt 2015 20:54

AW: CopyFile Datei wird nicht überschrieben
 
Nein, wenn dort Yes ausgewählt wird, dann wird
Delphi-Quellcode:
mrYes
zurückgeliefert und dann wird
Delphi-Quellcode:
FailIfExists := MessageDlg(...) <> mrYes;
eben
Delphi-Quellcode:
false
.

delnu 21. Okt 2015 21:36

AW: CopyFile Datei wird nicht überschrieben
 
Weil ich zwar nicht neugierig bin, aber immer alles wissen möchte: :lol:

Läßt sich mal der KOMPLETTE Code von Dennis07 erhalten ?

Zwar habe ich nur maximal XP und Delphi 7, aber es wäre immerhin möglich, daß
er etwas benutzt, das mit so alten Sachen noch funktioniert ... :roll:

Lyan 21. Okt 2015 22:29

AW: CopyFile Datei wird nicht überschrieben
 
Zitat:

Zitat von Sir Rufo (Beitrag 1319389)
Nein, wenn dort Yes ausgewählt wird, dann wird
Delphi-Quellcode:
mrYes
zurückgeliefert und dann wird
Delphi-Quellcode:
FailIfExists := MessageDlg(...) <> mrYes;
eben
Delphi-Quellcode:
false
.

oh, das <> mrYes hatte ich übersehn, ach diese minilaptops sind doch echt nicht gut geeignet für das Lesen von Code ;D

Dennis07 22. Okt 2015 00:32

AW: CopyFile Datei wird nicht überschrieben
 
Zitat:

Zitat von delnu (Beitrag 1319390)
Zwar habe ich nur maximal XP und Delphi 7, aber es wäre immerhin möglich, daß
er etwas benutzt, das mit so alten Sachen noch funktioniert

Leider nicht. Ich verwende im Projekt neuere Sprachelemente und sogar eigene noch nicht veröffentlichte Komponenten und Bibliotheken. Grundsätzlich kann es aber tatsächlich an der Windowsversion oder an der Delphi-RTL selber liegen.
Ich kann dir aber versichern, dass der Code, den ich gepostet habe, bis auf die Variablennamen soweit übereinstimmt und für diese Sache keinerlei weitere Codeabschnitte betrifft oder von ihnen betroffen wird.


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