Or failing that is there a simple, and clean recursive script which I can
use to copy the folder & files?
- Dan
var
OpStruct: TSHFileOpStruct;
begin
AppendStr(FromDir, #0);
AppendStr(Destination, #0);
With OpStruct Do
Begin
Wnd:=0;
wFunc:=FO_COPY;
pFrom:= @FromDir[1];
pTo:= @Destination[1];
fFlags:=FOF_ALLOWUNDO or FOF_SILENT or FOF_NOCONFIRMATION;
End;
if not DirectoryExists(Destination) then ForceDirectories(Destination);
SHFileOperation(OpStruct);
end;
"Dan" <froze...@gmail.com> wrote in message
news:47f40868$1...@newsgroups.borland.com...
- Dan
"Rob Kennedy" <m...@privacy.net> wrote in message
news:47f41c86$1...@newsgroups.borland.com...
> Dan wrote:
>> I'm trying to do something fairly simple. I just need to copy a folder
>> along with all it's contents to another location.
>
> You'd think that would be simple, wouldn't you? But do you want to copy
> the file permissions, too? What if the permissions aren't compatible with
> the ones in the destination folder? What should you do if a file is
> encrypted? If one of the folders is a hard link, should you duplicate the
> link, or make a new copy of the linked-to folder? What should the new
> files' dates be?
>
>> Unfortunately the only way I can find to do it is some huge recursive
>> procedure. Isn't there a simple Delphi command to copy/move folder with
>> contents?
>
> ShFileOperation can copy files and folders the same as if you had dragged
> and dropped them in Windows Explorer. Explorer's answers to the questions
> above might not be what you want.
>
>> Or failing that is there a simple, and clean recursive script which I can
>> use to copy the folder & files?
>
> Sounds like you already have that.
>
> --
> Rob
You need to elaborate. What doesn't work about it? Can you compile it?
Can you run it? When you run it, what happens? What did you expect to
happen instead?
> Is
> there some problem wrong with my code? The destination folder structure
> doesn't exist yet when I run this code, don't know if that's a factor or
> not.
Test your function when the destination folder _does_ exist, and then
you'll know whether it's a factor.
> var
> OpStruct: TSHFileOpStruct;
> begin
> AppendStr(FromDir, #0);
> AppendStr(Destination, #0);
Is AppendStr a Delphi function? It's more idiomatic to write a regular
string-append statement:
FromDir := FromDir + #0;
> With OpStruct Do
> Begin
> Wnd:=0;
> wFunc:=FO_COPY;
> pFrom:= @FromDir[1];
> pTo:= @Destination[1];
I'd write those like this:
pFrom := PChar(FromDir);
Do those strings specify fully qualified paths? The documentation
recommends it.
> fFlags:=FOF_ALLOWUNDO or FOF_SILENT or FOF_NOCONFIRMATION;
TShFileOpStruct has eight members, but you only touch five of them. What
about the other three?
> End;
> if not DirectoryExists(Destination) then ForceDirectories(Destination);
I'm pretty sure ForceDirectories already incorporates the
DirectoryExists call; you don't need to call it yourself.
> SHFileOperation(OpStruct);
You're ignoring the function's return value. The return value tells you
why the function failed.
> end;
--
Rob
You'd think that would be simple, wouldn't you? But do you want to copy
the file permissions, too? What if the permissions aren't compatible
with the ones in the destination folder? What should you do if a file is
encrypted? If one of the folders is a hard link, should you duplicate
the link, or make a new copy of the linked-to folder? What should the
new files' dates be?
> Unfortunately the
> only way I can find to do it is some huge recursive procedure. Isn't
> there a simple Delphi command to copy/move folder with contents?
ShFileOperation can copy files and folders the same as if you had
dragged and dropped them in Windows Explorer. Explorer's answers to the
questions above might not be what you want.
> Or failing that is there a simple, and clean recursive script which I
> can use to copy the folder & files?
Sounds like you already have that.
--
Rob
Pretend it said the _folder_ could not be found; does it make sense now?
--
Rob
It compiles fine, when I run the code it runs fine and tries to copy. The
SHFileOperation function returns an integer of 2. I'm not really sure which
error code that corrisponds to though.
>
> Test your function when the destination folder _does_ exist, and then
> you'll know whether it's a factor.
Whether the destination folder is there or not nothing ever copies.
I revised the code to:
FillChar (shf, SizeOf (shf), #0);
fromStr:= source + #0#0;
toStr:= dest + #0#0;
shf.Wnd:= 0;
shf.wFunc:= FOF_COPY;
shf.pFrom:= PCHAR (fromStr);
shf.pTo:= PCHAR (toStr);
shf.fFlags:= flags;
SHFileOperation (shf);
> Do those strings specify fully qualified paths? The documentation
> recommends it.
Yes, it's an exact path eg. C:\Documents and ...
>> fFlags:=FOF_ALLOWUNDO or FOF_SILENT or FOF_NOCONFIRMATION;
>
> TShFileOpStruct has eight members, but you only touch five of them. What
> about the other three?
I'm not sure what these other "members are".
> --
> Rob
>> Do those strings specify fully qualified paths? The documentation
>> recommends it.
>
> Yes, it's an exact path eg. C:\Documents and ...
If it's got spaces in the path shouldn't it be:
"C:\Documents and ..."
I don't see why. The quotes are for escaping command-line processing.
The API already knows it's getting one file name per list item.
--
Rob
Hi Dan,
It's been a while since I wrote / used this procedure - SHFileOperation is
very fussy about null terminators and its TShFileOpStruct ... get anything
wrong and it either fails silently or works but not as expected or wanted.
Andrew
function ShFilesOperation(Source, Destination : string; SHFlags :
FILEOP_FLAGS; SHFunc : integer) : boolean;
{ FOF_ALLOWUNDO - Preserves undo information, if possible.
FOF_CONFIRMMOUSE - Not implemented.
FOF_FILESONLY - Performs the operation only on files if a wildcard
filename (*.*) is specified.
FOF_MULTIDESTFILES - Indicates that the pTo member specifies multiple
destination files (one for each source file)
rather than one directory where all source files
are to be deposited.
FOF_NOCONFIRMATION - Responds with "yes to all" for any dialog box that
is displayed.
FOF_NOCONFIRMMKDIR - Does not confirm the creation of a new directory if
the operation requires one to be created.
FOF_NOERRORUI - Do not put up error UI.
FOF_RENAMEONCOLLISION - Gives the file being operated on a new name (such
as "Copy #1 of...") in a move, copy,
or rename operation if a file of the target name
already exists.
FOF_SILENT - Does not display a progress dialog box.
FOF_SIMPLEPROGRESS - Displays a progress dialog box, but does not show
the filenames.
FOF_WANTMAPPINGHANDLE - Fills in the hNameMappings member. The handle must
be freed by using the SHFreeNameMappings function. }
var
ShFileOpStruct : TShFileOpStruct;
begin
if (SHFunc = FO_DELETE) then
Source := ExcludeTrailingBackslash(Source);
FillChar(ShFileOpStruct, SizeOf(ShFileOpStruct), #0);
with ShFileOpStruct do begin
Wnd := Application.Handle;
wFunc := SHFunc;
fFlags := SHFlags;
pFrom := PChar(Source + #0);
pTo := PChar(Destination + #0);
end; {with}
Result := (SHFileOperation(ShFileOpStruct) = 0); //
Success if returns zero.
Result := Result and not ShFileOpStruct.fAnyOperationsAborted; //
Not a success if it got aborted.
end; {ShFilesOperation}
> It compiles fine, when I run the code it runs fine and tries to copy.
> The SHFileOperation function returns an integer of 2. I'm not
> really sure which error code that corrisponds to though.
2 = ERROR_FILE_NOT_FOUND
Gambit