C# Dateien in die Zwischenablage kopieren

Phoenixz

Lieutenant
Registriert
März 2004
Beiträge
595
Hallo,

ich würde gerne bestimmte Dateien in die Zwischenablage kopieren. Das geht im Prinzip ziemlich einfach, z.B. so hier:
Code:
System.Collections.Specialized.StringCollection files = new System.Collections.Specialized.StringCollection();
files.Add(@"...");
files.Add(@"...");
files.Add(@"...");
...
Clipboard.SetFileDropList(files);

Soweit sogut! Funktionieren tut das auch einwandfrei. Mir ist jedoch ein Problem aufgefallen, bei dem ich Fragen wollte, ob das bei euch auch so ist. Und zwar, wenn ich ganz normal über den Explorer Dateien kopiere und in einen anderen Ordner einfüge kann ich den Explorer auch während des Kopiervorgangs schließen oder in einen anderen Ordner navigieren (logischerweise kann man das nur bei großen Dateien testen). Mache ich das hingegen mit dem oben angegebenen Code freiert der Explorer während des ganzen Kopiervorgangs ein. D.h. möchte ich wo anders hin navigieren, muss ich mir eine neue Instanz des Explorers öffnen. Stört mich eigentlich fast 0, aber wäre schöner wenn es nicht so wäre. Ist das bei euch auch so bzw. hat jemand Rat?

Vielen Dank,
Daniel
 
Vermute mal das der Explorer einen neuen Thread/Process startet wenn er zu kopieren anfängt
wenn er von außen angestartet wird, Benutzt er den Hauptthread
wie du das umgehen kannst... sorry keine Ahnung :(
 
Streng genommen wird er aber nicht von außen an gesteuert? Eigentlich unterscheidet sich der "manuelle" Weg (also kopieren und dann einfügen) zum oben beschriebenen Weg nur beim Kopieren der Dateien.
In Beiden Szenarien (manuell und programmiert) drücke ich ja "am Ende" rechte Maustaste in den Ordner und gehe dann auf einfügen.
Also würde das quasi bedeuten, dass sich das Clipboatrd-Objekt beim Benutzen von Clipboard.SetFileDropList(files); von dem unterschiedet, das ich hätte, wenn ich manuell kopieren würde. Werde diesen Ansatz (sobald ich Zeit habe, was in ein paar Stunden sein wird) weiter verfolgen und die beiden Objekte mal vergleichen.
 
Ich habe mal eine kleine Testapplikation dazu gebaut. Deinen beschrieben Fehler habe ich dabei aber nicht bekommen. Er lässt mich aber beim Kopiervorgang nicht den Explorer schließen, das passiert dann erst nach dem Ende.
 
Zuletzt bearbeitet:
Mit welcher Version von VS hast du das geschrieben? Beim Versuch das Projekt zu öffnen bekomme ich die Meldung im Projektmappenexplorer "Diese Projekt ist nicht mit der aktuellen Version von Visual Studio kompatibel". Normalerweise kenne ich das so, dass er dich dann Fragt ob du Upgreaden möchtest, aber hier kam die Frage nicht. Ich habe Visual Studio 2010 Ultimate.

Er lässt mich aber beim Kopiervorgang nicht den Explorer schließen, das passiert dann erst nach dem Ende.
Das scheint mir aber genau das zu sein, was ich oben als „mein Problem“ beschrieben habe (bzw. was ich als "einfrieren" bezeichnet habe). Nicht nur, dass du es nicht schließen kannst, du kannst das Fenster auch nicht verschieben, minimieren oder wo anders hin navigieren, bis der Kopiervorgang abgeschlossen ist (also das Explorer Fenster, den Kopierdialog kannst du normal verschieben usw.). Dieses Verhalten ist jedoch nicht normal, d.h. wenn ich direkt aus dem Explorer Dateien kopiere und irgendwo einfüge blockiert der Kopierdialog nicht den Explorer. Und genau das hätte ich auch gerne. Und meine Vermutung liegt daran, dass das Clipboard-Objekt beim manuellen Weg anders ist, als beim Programmier-Weg.

Trotzdem vielen Dank für die Mühe beim Erstellen eines Testprojekts.
 
Ich hatte das Projekt mit VS2012 angelegt und der stellt .Net 4.5 standardmäßig ein. Das macht das Projekt dann inkompatibel mit VS2010. Ich habe das umgestellt und zumindest bei mir lädt VS2010 es fehlerfrei.


Wegen des Problems:
In der MSDN habe ich gesehen, dass es noch Clipboard.SetDataObject() mit einem Flag gibt, der das Objekt in der Zwischenablage persistent macht. Ich werde mal damit rumspielen, vielleicht ist das die Lösung.
 

Anhänge

Zuletzt bearbeitet:
Dein Problem besteht deswegen, weil der Windows Explorer noch einiges mehr an Daten ins Clipboard ablegt, als nur eine Dateiliste.

Wenn du wissen willst welche Daten das sind, kannst du mal ne Datei (im Explorer) kopieren und dann mit dem Debugger durch diesen Codefetzen steppen und dir anschaun, was da so alles in den Variablen steht (besonders interessant: format, buffer):
Code:
var obj = Clipboard.GetDataObject() as DataObject;

if (obj != null)
{
    string[] formats = obj.GetFormats(true);

    foreach (string format in formats)
    {
         object data = obj.GetData(format);
         byte[] buffer = null;

         if (data is MemoryStream)
         {
              var stream = (MemoryStream)data;
              buffer = stream.ToArray();
         }                
    }
}


Was für dich wichtig ist, is das AsyncFlag das der Explorer setzt.
Dadurch wird der Kopiervorgang - wie sollte es auch anders sein - asynchron ausgeführt.

Die Lösung sieht also folgendermaßen aus:
Code:
var files = new StringCollection();
//TODO: Add files

var asyncFlag = new MemoryStream(new byte[] { 1, 0, 0, 0 });

var data = new DataObject();
data.SetFileDropList(files);
data.SetData("AsyncFlag", asyncFlag);            

Clipboard.SetDataObject(data, true);
 
Zuletzt bearbeitet:
Zurück
Oben