Jump to content
emileverh

Copy file to temp folder fails

Recommended Posts

Hi!

 

I need to copy a file to the Windows-temp folder. But on some of my clients it fails. I can not reproduce it, but when they open a mail with attachment in Outlook and my app is working on the same filename it fails. The routine below fails.

 

Please do not focus on Outlook, but in general. How can I 'force delete' a file? Or how can I safe save a file to the temp folder without problems? Any suggestions? Please help!  

-Emile

function TdtmBoot.CopyFileToTempFolder(const AFullFileName: TFileName): string;
begin
  var lFileName: string := ExtractFileName(AFullFileName);
  var lTempFolderFullFileName: string := GetTempFolder + lFileName;

  try
    if DeleteFile(lTempFolderFullFileName) = False then; // @17.22
    begin
      SendMadBugReport(Self, 'CopyFileToTempFolder(), delete failed');  // <<<<<<<< HERE IT FAILS!!!!!!!
    end;
  except
  end;

  Result := lTempFolderFullFileName;
  try
    TFile.Copy(AFullFileName, lTempFolderFullFileName, true); // true = overwrite
    Result := lTempFolderFullFileName;
  except
  end;
end;

 

Share this post


Link to post
17 minutes ago, Lajos Juhász said:

You should check GetLastError to see the reason why it fails. https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-deletefile

 

One of the possible reason is that the file doesn't exists and the other is that the file is in use by other application.

Thanks and agree! I had to check if the file exists. But the DeleteFile() call was recently added. In previous versions of my app it failed on the next statement TFIle.Copy().  So again; is there a way to force delete a file? 

Share this post


Link to post
1 hour ago, emileverh said:

So again; is there a way to force delete a file? 

No there is no way if the file is locked it is not going to be deleted. 

 

You should first try to add:

 

If FileExists(lTempFolderFullFileName) then

  if not DeleteFile(lTempFolderFullFileName ) then

    SendMadBugReport(Self, 'CopyFileToTempFolder(), delete failed');  // <<<<<<<< HERE IT FAILS!!!!!!!

 

Why do you have an empty try ... except block? That is very dangerous at least you should send a bug report with the exception. Ignoring an exception can lead to other bugs in a program. 

  • Like 1

Share this post


Link to post

First of all you should know why the file is not deleted. AFter that there are other ways to delete a file, for example when is locked. BUt this go over my competence.

 

 

Share this post


Link to post

You cannot delete a file that is in use, unless the app that is using the file explicitly permits the deletion (by specifying FILE_SHARE_DELETE when opening the file). Nobody does that under normal usage, so you will need to detect when this condition happens (check GetLastError() when the deletion fails) and then. either 1) retry the deletion later or 2) ask Windows to delete the file on the next reboot (via MoveFileEx(MOVEFILE_DELAY_UNTIL_REBOOT)).

Edited by Remy Lebeau

Share this post


Link to post
Just now, Remy Lebeau said:

You cannot delete a file that is in use, unless the app that is using the file explicitly permits the deletion (by specifying FILE_SHARE_DELETE when opening the file). Nobody does that under normal usage, so you will need to detect when this condition happens (check GetLastError() when the deletion fails) and then. either 1) retry the deletion later or 2) ask Windows to delete the file on the next reboot (via MoveFileEx(MOVEFILE_DELAY_UNTIL_REBOOT)).

You are right force deleting a file is not a good idea. The other (unknown for me) process needs the file. Any idea if there is an API to add a kind of duplication number like: file (1).txt, file (2).txt, file (3).txt ? 

I did Google something but I did not find 1-2-3 an API for that. Anybody knows?

Share this post


Link to post
33 minutes ago, emileverh said:

Any idea if there is an API to add a kind of duplication number like: file (1).txt, file (2).txt, file (3).txt ? 

Use the Win32 SHFileOperation() API to copy the file with the FOF_RENAMEONCOLLISION flag:

Quote

Give the file being operated on a new name in a move, copy, or rename operation if a file with the target name already exists at the destination.

 If you need to know what the copied filename was renamed to, include the FOF_WANTMAPPINGHANDLE flag as well:

Quote

If FOF_RENAMEONCOLLISION is specified and any files were renamed, assign a name mapping object that contains their old and new names to the hNameMappings member. This object must be freed using SHFreeNameMappings when it is no longer needed.

Alternatively, on Windows Vista+, you can use the IFileOperation API instead, using IFileOperation.SetOperationFlags() to set the FOF_RENAMEONCOLLISION flag, IFileOperation.CopyItem() and IFileOperation.PerformOperations() to perform the copy, and if needed use an IFileOperationProgressSink event sink to discover the copied filename in the PostCopyItem event.

Edited by Remy Lebeau
  • Like 1

Share this post


Link to post
39 minutes ago, Remy Lebeau said:

Use the Win32 SHFileOperation() API to copy the file with the FOF_RENAMEONCOLLISION flag:

 If you need to know what the copied filename was renamed to, include the FOF_WANTMAPPINGHANDLE flag as well:

Alternatively, on Windows Vista+, you can use the IFileOperation API instead, using IFileOperation.SetOperationFlags() to set the FOF_RENAMEONCOLLISION flag, IFileOperation.CopyItem() and IFileOperation.PerformOperations() to perform the copy, and if needed use an IFileOperationProgressSink event sink to discover the copied filename in the PostCopyItem event.

Thanks Remy for your help!!!

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

×