Entwickler-Ecke
Dateizugriff - Konsolenanwendung zum Kopieren von Ordnern
Kay E. - Mo 18.07.11 23:50
Titel: Konsolenanwendung zum Kopieren von Ordnern
Hallo zusammen!
Ich wollte mir ein kleines Konsolenprogramm schreiben, dass mir (hardcoded) meine Diplomarbeit sichert. Dazu soll von einem USB-Stick, der die aktuellen Daten enthält (das ist der 'Store N Go'-Stick, s.u.) zuerst eine Kopie auf die Festplatte gemacht werden und von dort auf einen anderen USB-Stick (der 'Corsair'), sofern gewünscht. Die Backups sollen fortlaufend numeriert werden.
Ich hab jetzt folgenden Code:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149:
| program KopiererDA;
{$APPTYPE CONSOLE}
uses SysUtils, ShellAPI, Windows, Classes;
var VolumeName: String; DriveOrig, DrivePlatte, DriveUSB: Char; DirName: string; DirNameOld: string; DirNameTemp: string; StdInput: String; i, j: Integer;
const cOrdnerName = 'Diplomarbeit'; cDAOrdnerOriginal = '\Diplomarbeit\Diplomarbeit\'; cDAKopiePlatte = '\Universität & Studium\DA Backup\'; cPlattenName: string = 'Sonstiges'; cUSBName: string = 'Corsair'; cOrigName: string = 'STORE N GO'; cDAKopieUSB = '\Backup DA\';
function CopyDir(const fromDir, toDir: string): Boolean; var fos: TSHFileOpStruct; begin ZeroMemory(@fos, SizeOf(fos)); with fos do begin wFunc := FO_COPY; fFlags := FOF_FILESONLY; pFrom := PChar(fromDir + #0); pTo := PChar(toDir) end; Result := (0 = ShFileOperation(fos)); end;
function GetVolumeName(DriveLetter: Char): String; var dummy: DWORD; buffer: array[0..MAX_PATH] of Char; oldmode: LongInt; begin oldmode := SetErrorMode(SEM_FAILCRITICALERRORS); try GetVolumeInformation(PChar(DriveLetter + ':\'), buffer, SizeOf(buffer), nil, dummy, dummy, nil, 0); Result := StrPas(buffer); finally SetErrorMode(oldmode); end; end;
begin try for i := ord('c') to ord('z') do begin if CompareText(GetVolumeName(char(i)), cOrigName) = 0 then DriveOrig := char(i); if CompareText(GetVolumeName(char(i)), cUSBName) = 0 then DriveUSB := char(i); if CompareText(GetVolumeName(char(i)), cPlattenName) = 0 then DrivePlatte := char(i); end;
if DriveOrig = '' then begin WriteLn('Laufwerk von Original kann nicht gefunden werden - Abbruch'); ReadLn; exit; end; if DrivePlatte = '' then begin WriteLn('Laufwerk von Platte kann nicht gefunden werden - Abbruch'); ReadLn; exit; end; if DriveOrig = '' then begin WriteLn('Laufwerk von USB-Sicherung kann nicht gefunden werden - Überspringen? [j,n]'); ReadLn(StdInput); if StdInput <> 'j' then exit; end;
for i := 1 to 255 do begin DirNameTemp := cOrdnerName + 'Bkp' + inttostr(i); if not DirectoryExists(DrivePlatte + ':\' + cDAKopiePlatte + DirNameTemp + '\') then begin DirName := DrivePlatte + ':' + cDAKopiePlatte + DirNameTemp + '\'; break; end; end;
if DirectoryExists(DriveOrig + ':' + cDAOrdnerOriginal) then if not CopyDir(DriveOrig + cDAOrdnerOriginal, DirName) then begin WriteLn('Fehler beim kopieren von Original zu Platte aufgetreten - Abbruch'); ReadLn; exit; end else begin WriteLn('Kann Originalordner nicht finden - Abbruch'); ReadLn; exit; end;
DirNameOld := DirName; DirName := DriveUSB + ':' + cDAKopieUSB + DirNameTemp + '\';
if DirectoryExists(DirNameTemp) then if not CopyDir(DirNameTemp, DirName) then begin WriteLn('Fehler beim kopieren von Platte zu USB-Stick aufgetreten - Abbruch'); ReadLn; exit; end else begin WriteLn('Kann Plattenordner nicht finden - Abbruch'); ReadLn; exit; end;
WriteLn('Ordner erfolgreich kopiert. Schönen Tag noch!'); ReadLn; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. |
Ich hab das Problem, dass er völlig falsche Laufwerksbuchstaben findet und damit eben auch nicht den Originalordner. Aber anstatt bei der entsprechenden if-Abfrage in den else-Zweig zu springen, überspringt er die und geht zur nächsten Anweisung.
Ich steh grad aufm Schlauch. Wo ist das Problem? Warum findet er die Laufwerke nicht richtig? Warum überspringt er den Else-Zweig?
Ich hoff, ihr könnt mir helfen!
Grüße Kay
Kay E. - Di 19.07.11 21:25
Push
jaenicke - Di 19.07.11 22:54
Naja, weshalb ich dazu nichts geschrieben hatte ist, dass du nicht dazu geschrieben hast was beim Debuggen denn genau passiert. Denn wenn da ein falscher Laufwerksbuchstabe herauskommt, musst du ja beim Debuggen sehen warum.
Wenn du in der Schleife an der Stelle bist, dass der richtige Buchstabe vorliegt, dann sollte CompareText ja auch 0 liefern. Das musst du eben im Debugger auswerten und analysieren was da schief geht...
Delete - Mi 20.07.11 07:57
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| if DriveOrig = '' then begin WriteLn('Laufwerk von Original kann nicht gefunden werden - Abbruch'); ReadLn; exit; end; if DrivePlatte = '' then begin WriteLn('Laufwerk von Platte kann nicht gefunden werden - Abbruch'); ReadLn; exit; end; if DriveOrig = '' then |
Moderiert von
Martok: Delphi-Tags hinzugefügt
Moderiert von
Martok: Highlight-Tags hinzugefügt
Kay E. - Mi 20.07.11 18:19
@ Jaenicke: Ähm, ja... Und daurch, dass du nichts geschrieben hast, hab ich natürlich auch gewusst, was für Informationen noch gebraucht werden, nicht wahr? Und den Debugger hab ich durchaus auch schon mal genutzt. Da ich aber ja nichts sinnvolles gefunden habe, hab ich die Frage hier gestellt. Alles andere wäre irgendwie ein wenig... witzlos.
@ Hathor: Du hast Recht, das war ein kleiner Copy-Paste Fehler. Ist behoben.
-------------------------
Das Problem mit den Laufwerksbuchstaben hab ich jetzt rausgefunden. Das liegt daran, dass der Buffer in
GetVolumeName seinen alten Wert behält. Mit einem reinitialisieren auf #0 nach dem result oder vor
GetVolumeInformation behebt das Problem.
Dafür gibt es ein neues Problem: Das Kopieren an sich funktioniert nicht. Mit einfachen Testordnern (ein Ordner, ein leeres txt-file darin) funktionierts, aber bei meinen Ordnern klappts nicht (mehrere Dateien und Unterordner). Ich habe mir nochmal eingehend die Structs und den API-Aufruf angeschaut und die oben gepostete
CopyDir-Funktion nochmal ein wenig abgeändert.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| function CopyDir(const fromDir, toDir: string): Boolean; var fos: TSHFileOpStruct; begin ZeroMemory(@fos, SizeOf(fos)); with fos do begin wFunc := FO_COPY; fFlags := FOF_NOCONFIRMMKDIR; pFrom := PChar(fromDir + #0); pTo := PChar(toDir + #0) end; Result := (0 = ShFileOperation(fos)); end; |
Ich hab bei den Flags FOF_FILESONLY rausgenommen, so dass ich sicher sein kann, dass auch die Unterordner kopiert werden.
FOF_NOCONFIRMMKDIR hab ich dazugenommen, mit dem Gedanken, dass das Kopieren deswegen vlt. nicht klappt (und es sinnvoll ist)
Und dann steht in der Hilfe, dass pTo auch doppelt Nullterminiert sein soll, deswegen dann noch ein #0 hinten dran.
Nichts desto trotz funktionierts nicht. Ich bekomm aber keine Fehler, sondern
ShFileOperation liefert einfach nicht 0 zurück.
Der pFrom-Pfad existiert (wird geprüft) und der pTo-Pfad soll ohne Nachfrage angelegt werden, wobei das Laufwerk auch existiert (wird auch geprüft). Was kann ich also tun, um rauszufinden, wo mein Fehler liegt? Was mach ich bei dem Aufruf falsch?
Grüße Kay
jaenicke - Mi 20.07.11 18:48
Welcher Wert kommt denn zurück?
Und sagt GetLastError vielleicht etwas?
Kay E. - Mi 20.07.11 19:15
Hat sich erledigt.
Im oberen Code prüf ich in Zeile 110, ob das Folder existiert. In Zeile 111 hab ich aber ':' vergessen. Im Debugger hab ich das dann gefühlte 10000 mal übersehen. Naja, manchmal sieht man den Wald vor lauter Bäumen nicht.
Danke euch allen!
P.S: @jaenicke: Der Wert war immer ein anderer, nie gleich. Just for information.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!