Jump to content
Sign in to follow this  
Tommi Prami

File Copy implementation with Progress Callback

Recommended Posts

I know it is quite simple thing to do, but still would preferably use some already tested implementation.

 

Does any Delphi Lib have such a routine?

 

-Tee-

Share this post


Link to post

Edit: Doh - as always I misread the original post... You wanted a callback for progress, I offered a progress bar 😛

Off to top up the coffee mug...

I use the native Windows one.  It deals well with UNC paths, access rights, network glitches, etc.

In addition, I touch up the target file date to ensure it matches the original file date.

Code was yanked from a utility unit, so there may be missing or superfluous units or functions. 

 


uses
  System.SysUtils, WinAPI.Windows, WinAPI.mmSystem, Winapi.ShlObj, Winapi.ShellApi, Winapi.ShFolder;


function ShellFileOperation(const hHandle: THandle; const aSourceFiles: string; aTargetDirectory: string; 
  aFunc:UInt; aFlags: FileOp_Flags; ProgressText:String):Integer;
var
  shellinfo: TSHFileOpStruct;
  rc: Integer;
begin
  FillChar(ShellInfo, SizeOf(ShellInfo), 0);
  shellinfo.wnd   := hHandle;
  shellinfo.wFunc := aFunc;
  shellinfo.fFlags := aFlags;
  shellinfo.pFrom := PChar(aSourceFiles+#0);
  shellinfo.pTo   := PChar(aTargetDirectory+#0);
  if ProgressText <> ''
  then shellinfo.lpszProgressTitle := pChar(ProgressText)
  else Shellinfo.lpszProgressTitle := pChar('Copying');
  rc := SHFileOperation(shellinfo);
  if (rc = 0) and shellinfo.fAnyOperationsAborted
   then rc := -1;
  Result := rc;
end;

function FileCopyProgress(const SourceFile, TargetFile: String; const ProgressText: String; const AppWinHandle: THandle; const Silent:Boolean): Boolean;
var
  rc : Integer;
  Flags: UInt;
  aDate: TDateTime;
  awh: hWnd;
begin
  FileAge(SourceFile,aDate);
  Flags := FOF_NOCONFIRMATION OR FOF_FILESONLY OR FOF_ALLOWUNDO;
  if Silent
  then begin
    Flags := Flags OR FOF_SILENT OR FOF_NOERRORUI OR FOF_NOCONFIRMMKDIR;
    awh := 0;
  end
   else awh := hWnd(AppWinHandle);
  rc := ShellFileOperation(awh, SourceFile, TargetFile, FO_COPY, Flags, ProgressText);
  DebugOut('ShellFileCopy ' + SourceFile + ' -> ' + TargetFile + ' returns rc='+IntToStr(rc));
  Result := (rc = 0);
  if Result
  then begin
    Sleep(250);
    FileSetDate(TargetFile, DateTimeToFileDate(aDate));
  end;
end;

 

Share this post


Link to post

I need to have one in the Command Line APP. 

Most likely it'll be OK for me to use TFile.Copy, as this small utility will run in one single machine.  But had got interesting errors while testing it just now over Slow 4G connection and VPN. Did not take screenshots but one was something like "Operation failed successfully" or something similar weirdness. And network path disappeared underneath and so on. 

Now that Schools are out my Internet bandwidth in here in rural areas of Finland plummeted totally. All house wifes watching PiornHUB and kids YouTube, I think.

Edited by Tommi Prami

Share this post


Link to post

The silent flag for the shell copy makes it run nicely in services and console apps - but yeah... no progress callback.


LOL at the last comment 😄

Share this post


Link to post

 

image.thumb.png.41f202cf67ec13147ef83395a855b16d.png

What is the point of this Exception? And how to handle it 🙂

 

IT sems that Actually file is not copied 😄 This is so weird 😄 

 

-Tee-

Edited by Tommi Prami

Share this post


Link to post
5 minutes ago, Lars Fosdal said:

Callstack?

2021-06-15_09h00_42.png.cfac16b477d2d600dab7675f0ca76713.png

 

That raise :

  if not DoCopy(SourceFileName, DestFileName, Overwrite) then
    raise EInOutError.Create(SysErrorMessage(GetLastError));

Edited by Tommi Prami

Share this post


Link to post

DoCopy calls WinAPI.Windows function CopyFileexternal kernelbase name 'CopyFileW';

So, your guess is good as mine...

Share this post


Link to post

My dzlib has TFilesystem.CopyFileWithProgress in unit u_dzFileUtils. It's a wrapper around the WinAPI function CopyFileEx.

 

I also seem to remember such a functionality in the jcl.

  • Like 2

Share this post


Link to post

Using CopyFileEx with quick and dirty simplem,entation, fixed my problem, more than less.. I bet dzlib one is not as crude as mine, have to check that out...

 

-Tee-

Edited by Tommi Prami

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×