Merkwürdiges Verhalten auch bei DirCopy ?

  • Hallo zusammen !

    Vor einiger Zeit hatte Oscar folgenden Thread zu DirMove gepostet :

    merkwürdiges Verhalten bei DirMove

    Das Thema wurde bereits abschließend diskutiert, ist hier also nicht der Punkt.

    Mir ist jetzt aber auch bei der verwandten Funktion DirCopy ein Verhalten aufgefallen, dass mich etwas irritiert.

    Für eine identische Testumgebung habe ich die Datei Test-DirCopy.zip angehängt.

    -> Test_DirCopy.au3 in ein beliebiges Testverzeichnis kopieren

    -> den Ordner \Quelle in dieses SkriptDir kopieren

    Schritt 1 :

    -> Der Zielordner \Ziel existiert noch nicht

    -> Das Skript Test_DirCopy.au3 ausführen

    <- Resultat : Die Dateistruktur von \Quelle wurde erwartungsgemäß nach \Ziel kopiert => OK

    Schritt 2 :

    Im Zielordner einige Dateien von Hand löschen (nicht den Ordner selbst).

    Schritt 3 :

    -> Der Zielordner \Ziel ist jetzt vorhanden

    -> Das Skript Test_DirCopy.au3 erneut ausführen

    <- Resultat : DirCopy meldet einen Fehler (Return Value = 0) => es wurde nichts kopiert !

    Ich hätte erwartet, dass die existierenden Dateien nicht überschrieben, die in Schritt 2 gelöschten Dateien aber hinzugefügt werden.

    Da ich schnupfenbedingt gerade den Darth-Vader-Gedächnishelm trage, hier die Frage :

    Könnt ihr das Verhalten bestätigen, und soll das so sein ?

    Gruß Musashi

    • Offizieller Beitrag

    Ja, kann ich bestätigen!

    Erst ein $FC_OVERWRITE kopiert die fehlenden Dateien.

    Auch wenn man alle Dateien und das Unterverzeichnis aus dem Zielverzeichnis löscht, wird keine einzige Datei kopiert.

    Offensichtlich findet bei $FC_NOOVERWRITE nur ein Test auf die Existenz des Zielverzeichnisses statt. Existiert es bereits bricht DirCopy ab.

    Für mich ein klarer Bug!

    Aber vermutlich ist das wieder ein Feature. :rolleyes:

    Noch ein Grund mehr, lieber _WinAPI_ShellFileOperation() zu benutzen.

  • Hallo Musashi

    ich kann das bestätigen. Wenn ich nicht $FC_OVERWRITE setze erhalte ich einen Fehler. Mit $FC_OVERWRITE klappt es. Allerdings werden hier aber wirklich vorhandene Dateien überschrieben.

    Die Funktionen sind Murks. Besser eine eigene Funktion nutzen.

    Achso. Habs jetzt erst gepeilt. DirCopy meint eben DirCopy.. X/

    Wenn beim zweiten Versuch das Verzeichnis bereits existiert und nicht $FC_OVERWRITE gesetzt ist, bricht die Funktion eben wie versprochen mit Fehler ab. Das ganze funktioniert einfach ohne Ansehen der Inhalte. Es geht nur um die Verzeichnisse.. Also alles gut.

    Grüße autoiter

    Einmal editiert, zuletzt von autoiter (12. November 2017 um 19:58)

  • Ja, kann ich bestätigen!

    Erst ein $FC_OVERWRITE kopiert die fehlenden Dateien.

    Auch wenn man alle Dateien und das Unterverzeichnis aus dem Zielverzeichnis löscht, wird keine einzige Datei kopiert.

    Offensichtlich findet bei $FC_NOOVERWRITE nur ein Test auf die Existenz des Zielverzeichnisses statt. Existiert es bereits bricht DirCopy ab. Für mich ein klarer Bug! Aber vermutlich ist das wieder ein Feature.

    Ist identisch zu meinen Tests, daher betrachte auch ich dieses Verhalten als klaren Bug !

    Code
    Auszug aus der Hilfe zu flag :
    [optional] dieser Parameter gibt an, ob eventuell schon existierende Dateien überschrieben 
    werden sollen oder nicht.
     0 = (Standard) kein Überschreiben von existierenden Dateien
     1 = Überschreiben existierender Dateien

    Kein Überschreiben von existierenden Dateien impliziert, dass es existierende Dateien zumindest geben darf. Es wird aber lediglich auf die reine Existenz des Basisverzeichnisses (leer reicht bereits) geprüft.

    Damit ist das Defaultflag 0 ($FC_NOOVERWRITE) im Grunde völlig sinnlos.

    Wenn das Zielverzeichnis nicht existiert, ist es egal ob $FC_NOOVERWRITE oder $FC_OVERWRITE. Wenn es existiert, dann kommt es zu einem Fehler.:rolleyes:

    Das Ganze ist zwar nicht so schlimm wie die Endloskaskade von \Quelle\Quelle\Quelle... bei DirMove, trotzdem nicht das Ergebnis, welches viele Nutzer wahrscheinlich erwarten !

    Noch ein Grund mehr, lieber _WinAPI_ShellFileOperation() zu benutzen.

    Das werde ich jetzt auch mal ins Auge fassen ;).

    Trotzdem ärgerlich, da Funktionen wie DirMove und DirCopy ja nun wirklich keine Exoten sind.

    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

    • Offizieller Beitrag

    Trotzdem ärgerlich, da Funktionen wie DirMove und DirCopy ja nun wirklich keine Exoten sind.

    Da stimme ich Dir zu.

    Aber eigentlich hat man mit "_WinAPI_ShellFileOperation" sogar gleich noch eine Benutzer-Rückfrage, ohne dass man sich selbst darum kümmern muss.

    Wenn man sich also eine kleine Funktion ("_DirCopy") schreibt, kann man das echte DirCopy leicht ersetzen:

  • Wenn man sich also eine kleine Funktion ("_DirCopy") schreibt, kann man das echte DirCopy leicht ersetzen:

    Ich habe mir die Funktion _WinAPI_ShellFileOperation kurz angesehen. Im ersten Moment wird man durch die Vielzahl an Parametern zwar etwas erschlagen, aber da muss man halt durch ^^.

    In der dialogfreien Variante deiner Funktion, also _DirCopy($sSourceDir, $sDestinationDir, $FOF_NOCONFIRMATION) , verhält sie sich momentan noch wie DirCopy($sSourceDir, $sDestinationDir, $FC_OVERWRITE) , d.h. :

    -> fehlende Dateien/Ordner werden eingefügt

    -> bestehende Dateien/Ordner werden überschrieben

    Was noch fehlt, wäre der Schutz bestehender Dateien/Ordner vor dem Überschreiben.

    Sobald das funktioniert, hat sich auch die Funktion DirMove erledigt, indem man schreibt :

    If _DirCopy($sSourceDir, $sDestinationDir, [Flag]) Then DirRemove($sSourceDir, $DIR_REMOVE)

    Danke und Gruß

    Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • Hallo Oscar !

    (Nachtrag zu Beitrag #7)

    Ich habe mal etwas mit der Funktion herumexperimentiert^^.

    Trotz des Flags $FOF_NOCONFIRMATION wird, bei Nichtexistenz des Zielordners, ein Dialogfenster angezeigt :

    -> 'Ordner ... nicht vorhanden -> Erstellen ?

    Das Flag $FOF_SILENT ist für die dialogfreie Variante daher wohl besser geeignet !

    Ein Flag, welches den Schutz vor dem Überschreiben aktiviert, habe ich nicht entdeckt.

    Was aber geht ist $FOF_RENAMEONCOLLISION , dann werden Kopien vorhandener Dateien angelegt (Testdatei1 - Kopie.txt).

    Der Aufruf würde nun so aussehen :

    If _DirCopy($sSourceDir, $sDestinationDir, BitOR($FOF_SILENT, $FOF_RENAMEONCOLLISION)) Then ...

    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

    • Offizieller Beitrag

    Ich weiß nicht, ob ich Dich richtig verstehe.

    Wenn Du _WinAPI_ShellFileOperation($sSourceDir, $sDestinationDir, $FO_COPY, 0) mit Null als Flag aufrufst, dann wird doch der Anwender gefragt, ob eine evtl. bestehende Datei überschrieben werden soll:

    DirCopy_Screenshot.png

    Somit ist _WinAPI_ShellFileOperation mit Flag=0 sogar besser als DirCopy mit Flag=0, oder siehst Du das anders?

    Und wenn Dich die Nachfrage zum erstellen des Zielverzeichnisses beim "Überschreiben"-Flag stört, dann einfach: BitOR($FOF_NOCONFIRMATION, $FOF_NOCONFIRMMKDIR).

  • Somit ist _WinAPI_ShellFileOperation mit Flag=0 sogar besser als DirCopy mit Flag=0, oder siehst Du das anders?

    Nein, das sehe ich ganz genau wie Du ! Mit Flag 0 öffnet sich der Dialogmodus, den man aus Windows kennt. Es stehen einem damit alle Freiheiten offen, wie mit bestehenden Dateien/Ordnern verfahren werden soll.

    Was ich meine ist ein dialogfreier Modus, den man in Programmen verwenden kann ohne das irgendein Fenster aufgeht !

    Du hast in deinem Skript (Beitrag #6) ja bereits die folgende Option genannt:

    ... ; oder $FOF_NOCONFIRMATION fuer: "ueberschreiben ohne Nachfrage"

    Ich wollte nur sagen, dass trotz $FOF_NOCONFIRMATION , bei Nichtexistenz des Zielordners, ein Dialogfenster angezeigt wird. Daher mein Hinweis auf $FOF_SILENT, wobei $FOF_NOCONFIRMMKDIR diesen Punkt wohl auch löst.

    Die unterschiedlichen Möglichkeiten bzgl. bestehender Dateien/Ordner zeigt deine Grafik aus Beitrag #9.

    Ich habe bei den Flags zu _WinAPI_ShellFileOperation aber nichts entdecken können, dass z.B. das Ersetzen einer Datei im Zielordner verhindert, wenn diese 'neuer' ist. Offenbar stehen nicht alle Möglichkeiten für einen dialogfreien Modus zur Verfügung. $FOF_RENAMEONCOLLISION z.B. gibt es -> Kopien vorhandener Dateien werden angelegt.

    Ich hoffe, ich habe mich jetzt klarer ausgedrückt ^^!

    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

    • Offizieller Beitrag

    Ich habe bei den Flags zu _WinAPI_ShellFileOperation aber nichts entdecken können, dass z.B. das Ersetzen einer Datei im Zielordner verhindert, wenn diese 'neuer' ist.

    Im dialogfreien Modus nicht, nein!

    Mit dem Windows-Dialog hätte zumindest der Anwender die Möglichkeit, ob der dann immer über das entsprechende Wissen verfügt, sei mal dahingestellt.

    Will man wirklich die volle Kontrolle über die Kopieraktion, muss man wohl jede Datei einzeln testen/kopieren/ersetzen.

  • Hallo Oscar !

    Die Funktion _WinAPI_ShellFileOperation, als Ersatz für DirCopy, gefällt mir immer besser ;).

    Hier eine überarbeitete Zusammenfassung (auch für andere interessierte Leser) :

    Verwendet man bei _DirCopy (siehe Skript von Oscar - Beitrag #6) das Flag 0, dann erhält man den Windows-Dialog.

    Dialog, falls sich bereits gleichnamige Dateien im Zielordner befinden :

    1. Kopieren und ersetzen

    Bestehende Dateien/Ordner werden überschrieben

    2. nicht Kopieren

    Bestehende Dateien/Ordner im Zielordner belassen (also nicht überschreiben)

    3. Kopieren, aber beide Dateien behalten

    Die zu kopierende Datei wird umbenannt

    Wen die User-Interaktion nicht stört, dem stehen damit alle Möglichkeiten offen.

    Verwendung ohne User-Interaktion :

    Die Meldung : 'Der Ordner xxx ist nicht vorhanden. Möchten Sie ihn erstellen ?' läßt sich mit $FOF_NOCONFIRMMKDIR unterdrücken. Das von mir oben genannte Flag $FOF_SILENT macht das zwar auch, ist lt. MSDN aber dafür gedacht, die Anzeige einer 'Progress Dialog Box' zu unterbinden.

    Zu 1. Kopieren und ersetzen:

    Dazu im Befehl _DirCopy folgende Flags verwenden :

    BitOR($FOF_NOCONFIRMMKDIR, $FOF_NOCONFIRMATION)

    (Anmerkung : neue Dateien/Ordner aus dem Quellverzeichnis werden in den Zielordner eingefügt)

    Zu 3. Kopieren, aber beide Dateien behalten

    Dazu im Befehl _DirCopy folgende Flags verwenden :

    BitOR($FOF_NOCONFIRMMKDIR, $FOF_NOCONFIRMATION, $FOF_RENAMEONCOLLISION)

    (Anmerkung : neue Dateien/Ordner aus dem Quellverzeichnis werden in den Zielordner eingefügt)

    Für die Variante 2 nicht Kopieren gibt es offenbar kein passendes Flag (zumindest habe ich keines entdecken können).

    Wer bestehende Dateien/Ordner beibehalten möchte, sollte daher Variante 3 verwenden. Die im Zielordner bereits existierenden Dateien/Ordner bleiben, inklusive ihres Namens, erhalten. Die aus dem Quellordner stammenden Dateien/Ordner werden als Kopie mit Namenszusatz eingefügt.

    Nicht ganz die perfekte Lösung, aber deutlich besser als die Fehlermeldung bei der Standardfunktion DirCopy ;).

    Edit :

    Ich setze den Thread mal auf erledigt. Es besteht ja weiterhin die Möglichkeit, Beiträge anzufügen.

    Danke für das bisherige Feedback :)

    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

    Einmal editiert, zuletzt von Musashi (14. November 2017 um 13:58) aus folgendem Grund: erledigt