Laden...

SHFileOperation kopiert nicht von CD-Laufwerk

Letzter Beitrag vor 18 Jahren 30 Posts 4.944 Views
SHFileOperation kopiert nicht von CD-Laufwerk

Hallo Leute,

ich versuche mich gerade an dem Artikel bzw. an dessen Bespielcode:

http://www.pinvoke.net/default.aspx/shell32.SHFileOperation

Leider funktioniert bei mir das Kopieren von einer CD nicht. Warum? Ich könnte mir vorstellen das irgendein Flag falsch gesetzt ist...

Mein Code:

Shellworks fo = new Shellworks();
fo.pFrom = @"D:\";
fo.pTo = @"C:\TEMP";
fo.wFunc = Shellworks.FO_Func.FO_COPY;
fo.Execute();

Hallo -acid-,

wie ist der Rückgabewert? Gibt es einen Fehlercode (LastError?) oder Fehlermeldung? Was ist der Effekt?

herbivore

@"C:TEMP";?
deshalb?

irgendwie fehlt der Backslash.

Edit: ok, wurde wohl vom Forum geschluckt.

Hast du die Klasse so übernommen? Welche Parameter?

wie ist der Rückgabewert? Gibt es einen Fehlercode (LastError?) oder Fehlermeldung? Was ist der Effekt?

Die Klasse aus dem Beispiel habe ich nicht verändern. Ich rufe sie lediglich mit dem
Code auf:

public partial class Form1 : Form
    {
        private InteropSHFileOperation fo;
        public Form1()
        {
            InitializeComponent();

            fo = new InteropSHFileOperation();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            fo.pFrom = @"G:\\"; // CD
            fo.pTo = @"F:\\TEMP"; // Lokal
            fo.wFunc = InteropSHFileOperation.FO_Func.FO_COPY;
            fo.Execute();
        }
    }

Dann kommt diese Meldung (bei normalen Laufwerken geht es, nur halt bei meinem CD-Laufwerk nicht):

Hallo -acid-,

als Quelle hast du ein Verzeichnis und keine Datei angegeben.

herbivore

Ah. Wie wandle ich das denn um damit ich einen kompletten Ordner kopieren kann? Weil bei lokaler Quelle und Ziel geht es mit Ordnern.

Ich hab das ganze mal mit der ShellLib von Codeproject ausprobiert.
Funktionierte einwandfrei.

Gernot Melichar

Damit habe ich auch angefangen... Hm. Also muss ich dann mein zu kopierendes Verzeichnis rekursiv durchlaufen und den Filename an die ShellCopy Methode weitergeben? Oder gibt es eine Möglichkeit?

Hallo -acid-,

hast du denn mal probiert, ob es funktioniert eine einzelne Datei von CD zu kopieren? Wenn ja, wäre der rekursive Weg ja eine relative einfache Möglichkeit. Ich kennen das von APIs eigentlich nur so, dass sie nur einzelne Dateien kopieren können, und hätte daher gleich selbst rekursiv programmiert.

herbivore

Also er kopiert einzelne Dateien von CD, ja. Das heißt er kommt einfach nicht mit Verzeichnissen klar. Denke dann kann ich es auch manuell machen sprich selbst programmieren.

Danke für eure Hilfe 🙂

Nochmals:
Ich habe die ShellLib von Codeproject verwendet.


            ShellLib.ShellFileOperation op = new ShellLib.ShellFileOperation();

       

            string[] source = {@"e:\\beispiele\kapitel 01" };
            string[] dest =  {@"d:\\test" };

            op.OwnerWindow = this.Handle;
            op.Operation = ShellLib.ShellFileOperation.FileOperations.FO_COPY;
            op.SourceFiles = source;
            op.DestFiles = dest;
            
            bool ret=op.DoOperation();

Wurde einwandfrei kopiert von CD mit Unterverzeichnissen.Und bei Dir
funktioniert es nicht?

Gernot Melichar

Meli ich weiß. Du hast aber das Problem nicht verstanden: Er kopiert zwar Verzeichnisse komplett, aber nicht wenn ich direkt als Quelle das CD-LAufwerk zb. "D:" angebe.

Ahh, dann versuchs mit:


string[] source = {@"e:\\*.*" };


So klappts bei mir.

Gernot Melichar

Hui toll 🙂

Dank dir Meli. Ich habe es ja zum Großteil schon selbst gemacht, habe aber mit den ganzen Features wie Ersetzen ja/nein, alle, etc... noch Probleme gehabt und wuste nicht wie ich die ganzen Funktionen schreiben soll. Dann nehme ich das 👍

Hallo -acid-,

*.* ist Dos-Steinzeit und arbeitet bei Windows nicht wie erwartet.

Nimm einfach nur *

herbivore

Danke herbivore 👍

Habe mir gerade eine Demo Application geschrieben. Dort funzt es:

//Quelle wählen
private void button2_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog fb = new FolderBrowserDialog();

            if (fb.ShowDialog() == DialogResult.OK)
            {
                string[] SourcePath = { fb.SelectedPath + "*" };
                this.sc.SourceFiles = SourcePath;
            }
        }

//Ziel wählen
        private void button3_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog fb = new FolderBrowserDialog();

            if (fb.ShowDialog() == DialogResult.OK)
            {
                string[] DestPath = { fb.SelectedPath };
                this.sc.DestFiles = DestPath;
            }
        }

Dort habe ich dann auch noch noch Buttn der das Kopieren ausführt. Den gleichen Code habe ich in eine andre Anwendung übernommen und bekomme beim Abbrechen des Kopierendialogs folgenden Fehler:

************** Exception Text **************
System.NullReferenceException: Object reference not set to an instance of an object.
at fastInstall.plgnDataSource.button3_Click(Object sender, EventArgs e)
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

Könnt ihr mir helfen?

Hallo -acid-,

übersetz mal im Debug-Modus. Dann siehst du die genaue Zeile, in der die Exception auftritt. Da das in deiner eigene Methode ist, sollte die Ursache nicht schwer zu finden sein.

herbivore

übersetz mal im Debug-Modus.

Was heißt das? Ich benutze bereits den Debugmodus. Dort wird eine dll erstellt, die in meinem Hauptprojekt referenziert wird. Gibt es eine bessere Möglichkeit zu debuggen um genau die Zeile angezeigt zu bekommen?

Hallo -acid-,

ich bin davon ausgegangen, dass fastInstall.plgnDataSource.button3_Click eine Methode von dir ist. Und wenn die zugehörige Assembly im Debug-Modus übersetzt wäre, dann müsste dahinter eine Zeilennummer angezeigt werden.

Wenn die Methode gar nicht von dir ist, vergiss meinen Beitrag.

herbivore

Also ich habe nochmal geschaut. Komischerweise gehts im Debugmodus aus VS heraus ohne Fehler. Der Fehler tritt nur beim Einzelaufruf der exe auf. Wie kann ich denn den Fehler lokalisieren? Achja: Der Click des Buttons ist einfach nur ein stink normales Buttonevent, welche die Kopierroutine aufruft. Der Code ist also genau der gleiche wie unten...

Hallo -acid-,

Der Fehler tritt nur beim Einzelaufruf der exe auf. Wie kann ich denn den Fehler lokalisieren?

Da gibt es viele Möglichkeiten. Meine wäre, das Programm als Konsolen-Anwendung zu übersetzen und die Exception (und natürlich den StackTrace) einfach mit Console.WriteLine auszugeben.

herbivore

Ah. StackTrace... habe den mal ausgeben lassen:

try
            {
                //this.btnCopy.Enabled = false;
                this._ShellCopy.OwnerWindow = this.Handle;
                this._ShellCopy.Copy();
                //this.btnCopy.Enabled = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + " \r\n\r\n" + ex.StackTrace);
            }

Wenn ich nun die zwei Zeilen, die den Button erst deaktiviert und dann wieder aktiviert, ausblende geht es. Ich verstehe aber nicht was ich falsch mache bzw. warum es dann nicht funktioniert wenn die zwei Zeilen wieder eingebunden werden.

Hallo -acid-,

na vermutlich doch, weil this.btnCopy null ist.

herbivore

Habe die Zeilen weggelassen. So geh es jetzt. Bin aber noch wie vor am überlegen ob ich nicht doch - wie herbivore schon sagte - zu meiner alten eigenen Kopiermethode zurückgreife. Die ist zwar nicht so konfortabel, aber ich habe ein Dialogfenster, damit der User nicht mehr auf die Hauptform zugreifen kann und ich habe mehr Kontrolle über das was ich anzeige und mache. Außerdem bin ich unabhängig von WinApis.

Danke für eure Hilfe 🙂

Hallo -acid-,

auch hier verstehe ich nicht ganz den Zusammenhang. Hast du denn mal geguckt, ob this.btnCopy null ist? Wenn ja, dann musst du doch nur diese Variable auf den richtigen Button setzen und schon sollte es gehen.

herbivore

Ja sie ist null.

a) Wie wie setze ich diese Variable auf den richtigen Button? Mit this.btnCopy = this.btnCopy; ?!
b) Wie ich bereits sagte, spricht Einiges dafür eine eigene Methode zu verwenden. Daher denke ich ist es wirklich sinnvoller mich nochmal mit meiner eigenen Kopierroutine zu beschäftigen.

Hallo -acid-,

a) Wie wie setze ich diese Variable auf den richtigen Button?

Durch Zuweisung. 🙂
Der Button wird mit new erzeugt. Den Rückgabe dieses news musst du direkt oder indirekt an this.btnCopy zuweisen.

Mit this.btnCopy = this.btnCopy; ?!

Nein, das weist ja nur die Variable an sich selbst zu. Wenn die vorher null ist, ist sie es nacher auch.

herbivore

Ah also erzeuge ich einfach eine neue Buttoninstanz names btnCopy. Ok danke 🙂

Hallo -acid-,

nur wenn es diese Instanz noch nicht gibt, sonst hättest du ja zwei Instanzen. Wenn es die Instanz schon gibt, musst du nur dafür sorgen, dass sie an btnCopy zugewiesen wird.

herbivore