Kako mogu u delphiju da kopiram jedan direktorijum koji je pun poddirektorijuma na neko drugo mesto, radi backup-a podataka?
Kopiranje direktorijuma sa poddirektorijumima
Zaključano
Zakačeno
Ovo bi ti uradilo posao:
Sad, da li postoji nesto elegantnije...
ss.
Code:
procedure TMyForm.GetFiles(dir:string);
var
F: TSearchRec;
begin
if FindFirst(dir + '*.*', faAnyFile, F) = 0 then
begin
repeat
application.ProcessMessages; //da program ne ostane 'zaledjen'
if (F.Attr = faDirectory) and (f.Name[1] <> '.')
then GetFiles(dir + F.Name + '\');
ListBox1.Items.Add(dir + F.Name); // ovde mozes ubaciti CopyFile
until FindNext(F) <> 0;
FindClose(F);
end;
end;
procedure TMyForm.GetFiles(dir:string);
var
F: TSearchRec;
begin
if FindFirst(dir + '*.*', faAnyFile, F) = 0 then
begin
repeat
application.ProcessMessages; //da program ne ostane 'zaledjen'
if (F.Attr = faDirectory) and (f.Name[1] <> '.')
then GetFiles(dir + F.Name + '\');
ListBox1.Items.Add(dir + F.Name); // ovde mozes ubaciti CopyFile
until FindNext(F) <> 0;
FindClose(F);
end;
end;
Sad, da li postoji nesto elegantnije...
ss.
Potpis
When something is hard to do, then it's not worth doing.
mislim da ima...preko API-ja, dobijes i onaj windowsov Copy dijalog :)
upotreba ide ovako:
pozdravi
Code:
uses ShellAPI;
...
function WinCopy(Owner: Integer; FromFile, ToFile: String; RenameOnCollision: boolean = False; Confirm: boolean = False): Boolean;
var
Struct : TSHFileOpStructA;
MultDest: boolean;
begin
FillChar(Struct, SizeOf(Struct), 0); MultDest:=pos(';',ToFile)>0;
While pos(';',FromFile)>0 do
FromFile[pos(';',FromFile)]:=#0;
While pos(';',ToFile)>0 do
ToFile[pos(';',ToFile)]:=#0;
FromFile:=FromFile+#0#0;
ToFile:=ToFile+#0#0;
with Struct do
begin
wnd :=Owner;
wFunc :=FO_Copy;
pFrom :=PChar(FromFile);
pTo :=PChar(ToFile);
fFlags:=FOF_ALLOWUNDO or FOF_FILESONLY;
If MultDest then
fFLags:=fFlags or FOF_MULTIDESTFILES;
If RenameOnCollision then
fFLags:=fFlags or FOF_RENAMEONCOLLISION;
If not Confirm then
begin
fFLags:=fFlags or FOF_NOCONFIRMATION or FOF_NOCONFIRMMKDIR;
end;
hNameMappings:=nil;
lpszProgressTitle:=nil;
end;
Result:=(SHFileOperationA(Struct)=0) and (not Struct.fAnyOperationsAborted);
end;
uses ShellAPI;
...
function WinCopy(Owner: Integer; FromFile, ToFile: String; RenameOnCollision: boolean = False; Confirm: boolean = False): Boolean;
var
Struct : TSHFileOpStructA;
MultDest: boolean;
begin
FillChar(Struct, SizeOf(Struct), 0); MultDest:=pos(';',ToFile)>0;
While pos(';',FromFile)>0 do
FromFile[pos(';',FromFile)]:=#0;
While pos(';',ToFile)>0 do
ToFile[pos(';',ToFile)]:=#0;
FromFile:=FromFile+#0#0;
ToFile:=ToFile+#0#0;
with Struct do
begin
wnd :=Owner;
wFunc :=FO_Copy;
pFrom :=PChar(FromFile);
pTo :=PChar(ToFile);
fFlags:=FOF_ALLOWUNDO or FOF_FILESONLY;
If MultDest then
fFLags:=fFlags or FOF_MULTIDESTFILES;
If RenameOnCollision then
fFLags:=fFlags or FOF_RENAMEONCOLLISION;
If not Confirm then
begin
fFLags:=fFlags or FOF_NOCONFIRMATION or FOF_NOCONFIRMMKDIR;
end;
hNameMappings:=nil;
lpszProgressTitle:=nil;
end;
Result:=(SHFileOperationA(Struct)=0) and (not Struct.fAnyOperationsAborted);
end;
upotreba ide ovako:
Code:
WinCopy(Application.Handle, 'c:\folder1', 'c:\folder2'); //ovo confirm je za potvrdu overwrite-a
WinCopy(Application.Handle, 'c:\folder1', 'c:\folder2'); //ovo confirm je za potvrdu overwrite-a
pozdravi
Potpis
U smislu elegancije, malo preradjeno ShellAPI resenje (danas sam bas zaludan, a?
) Inace, meni licno se vise dopada ffirst/fnext resenje, jer je portabilno - radi i pod dos-om provereno.
ss.
ss.
Code:
function DirCopy(FromPath, ToPath: string; Overwrite: Boolean): Boolean;
var
fos: TSHFileOpStruct;
begin
FillChar(fos, SizeOf(fos), #0);
fos.Wnd := 0;
fos.wFunc := FO_COPY;
fos.pFrom := PChar(FromPath + #0);
fos.pTo := PChar(ToPath + #0);
if Overwrite then
fos.fFlags := FOF_SILENT // ako zelimo prikaz progresa, FOF_SIMPLEPROGRESS
else
fos.fFlags := FOF_RENAMEONCOLLISION or FOF_SIMPLEPROGRESS;
fos.fAnyOperationsAborted := False;
fos.hNameMappings := nil;
Result := (ShFileOperation(fos) = 0);
end;
function DirCopy(FromPath, ToPath: string; Overwrite: Boolean): Boolean;
var
fos: TSHFileOpStruct;
begin
FillChar(fos, SizeOf(fos), #0);
fos.Wnd := 0;
fos.wFunc := FO_COPY;
fos.pFrom := PChar(FromPath + #0);
fos.pTo := PChar(ToPath + #0);
if Overwrite then
fos.fFlags := FOF_SILENT // ako zelimo prikaz progresa, FOF_SIMPLEPROGRESS
else
fos.fFlags := FOF_RENAMEONCOLLISION or FOF_SIMPLEPROGRESS;
fos.fAnyOperationsAborted := False;
fos.hNameMappings := nil;
Result := (ShFileOperation(fos) = 0);
end;
Potpis
When something is hard to do, then it's not worth doing.
Ako ti stvarno treba ova funkcija za backup bilo bi jos bolje resenje da ne kopiras nego da zapakujes direktorijum, zar ne? :)
Potpis
a ako hoces za cele drajvove mozes da pravis image fajlove ovako:
Code:
procedure ImageDisk;
var
InF, OutF: THandle;
Buffer: array [1..(1024 * 64)] of Byte; // 64kb buffer
BufRead, BufWrote: DWORD;
begin
InF := CreateFile('\\.\A:',GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,0,0);
OutF := CreateFile('DISK.IMG',GENERIC_WRITE,FILE_SHARE_READ,nil,CREATE_ALWAYS,0,0);
BufRead := 1;
while (ReadFile(InF,Buffer,SizeOf(Buffer),BufRead,nil) = True) and
(BufRead <> 0) do
begin
WriteFile(OutF,Buffer,BufRead,BufWrote,nil);
end;
CloseHandle(OutF);
CloseHandle(InF);
end;
procedure RestoreImage;
var
InF, OutF: THandle;
Buffer: array [1..(1024 * 64)] of Byte; // 64kb buffer
BufRead, BufWrote: DWORD;
begin
InF := CreateFile('DISK.IMG',GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,0,0);
OutF := CreateFile('\\.\A:',GENERIC_WRITE,FILE_SHARE_READ,nil,OPEN_EXISTING,0,0);
if GetFileSize(OutF,nil) < GetFileSize(InF,nil) then
begin
CloseHandle(InF);
CloseHandle(OutF);
Exit;
end;
BufRead := 1;
while (ReadFile(InF,Buffer,SizeOf(Buffer),BufRead,nil) = True) and
(BufRead <> 0) do
begin
WriteFile(OutF,Buffer,BufRead,BufWrote,nil);
end;
CloseHandle(OutF);
CloseHandle(InF);
end;
procedure ImageDisk;
var
InF, OutF: THandle;
Buffer: array [1..(1024 * 64)] of Byte; // 64kb buffer
BufRead, BufWrote: DWORD;
begin
InF := CreateFile('\\.\A:',GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,0,0);
OutF := CreateFile('DISK.IMG',GENERIC_WRITE,FILE_SHARE_READ,nil,CREATE_ALWAYS,0,0);
BufRead := 1;
while (ReadFile(InF,Buffer,SizeOf(Buffer),BufRead,nil) = True) and
(BufRead <> 0) do
begin
WriteFile(OutF,Buffer,BufRead,BufWrote,nil);
end;
CloseHandle(OutF);
CloseHandle(InF);
end;
procedure RestoreImage;
var
InF, OutF: THandle;
Buffer: array [1..(1024 * 64)] of Byte; // 64kb buffer
BufRead, BufWrote: DWORD;
begin
InF := CreateFile('DISK.IMG',GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,0,0);
OutF := CreateFile('\\.\A:',GENERIC_WRITE,FILE_SHARE_READ,nil,OPEN_EXISTING,0,0);
if GetFileSize(OutF,nil) < GetFileSize(InF,nil) then
begin
CloseHandle(InF);
CloseHandle(OutF);
Exit;
end;
BufRead := 1;
while (ReadFile(InF,Buffer,SizeOf(Buffer),BufRead,nil) = True) and
(BufRead <> 0) do
begin
WriteFile(OutF,Buffer,BufRead,BufWrote,nil);
end;
CloseHandle(OutF);
CloseHandle(InF);
end;
Potpis
Ono prvo resenje sa sistemskom funkcijom je najbolje. Funkcije FindFirst i ostale ne podrzavaju unicode nazive foldera i fajlova (sto danas nije nikakvo cudo), tako da kada budu naleteli na takve fajlove bice tesno. Mislim da se meni cak desilo od ranije da sam imao problem sa fajlom koji ima znak pitanja u nazivu. Total Commander je tek od verzije 6 dobio podrsku za takve nazive.
Pitanje:
'\\.\A:' je direktan pristup A: drajvu ?
to mu je kao pandan /dev/fd0 ?
Ima negde na netu kako su imena C: drajva ili celog harddiska ?
'\\.\A:' je direktan pristup A: drajvu ?
to mu je kao pandan /dev/fd0 ?
Ima negde na netu kako su imena C: drajva ili celog harddiska ?
Potpis
People who think they know everything tend to irritate those of us who do.