views:

369

answers:

3

I have an application where I am trying to implement a "safe file overwrite" by:

  1. Creating a file (A)
  2. Filling A with data
  3. Copying A to its final destination (B) via SHFileOperation
  4. Deleting A using DeleteFile

However in step 4 DeleteFile always returns ERROR_SHARING_VIOLATION. The entire process takes milliseconds, so I can't imagine who else would be interfering with my file. A couple questions:

  1. Is there a better Win32 (C/C++) technique for performing the above?
  2. How can I get more information about the "other process" that's keeping me from deleting file A?
  3. How do I gently (wink wink nudge nudge) force Windows to delete my temporary file?

Any other suggestions are welcome

+2  A: 

My best guess would be that you need a step 2.5) Close the file handle created in 1)

What are you using to create/open the file?

If you use CreateFile then make sure you are closing your file handle before the call to delete, or else make sure you specify the sharing flag FILE_SHARE_DELETE.

HANDLE hFile = CreateFile("C:\\test.txt", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE |  FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, 0, NULL);

You might also want to simplify your copying of file code by using the Win32 API CopyFile.

Brian R. Bondy
Adding step 2.5 solved the problem; thanks!
fbrereto
+1  A: 

One way to delete the file would be to open it with FILE_FLAG_DELETE_ON_CLOSE which will request the OS to automatically delete the file after the last handle to it is closed. If you create the file with FILE_SHARE_READ then SHFileOperation should be able to read it to copy it, and you can then immediately close your handle to the file. When the shell closes its handle to the file, the file will be automatically deleted.

Greg Hewgill
I think he has this problem on every use of his function though, so this shouldn't be needed.
Brian R. Bondy
A: 
  • Try using Handles.exe from www.sysinternals.com to see if and how the file is in use.

  • You can use GetLastError and FormatMessage to get further information about the last failed funtion. Some sample code:

    char tx2[1024];
    
    
    DWORD l;
    
    
    if(l = GetLastError())
    

    {

    LPVOID lpMessageBuffer = 0;
    FormatMessage(
    FORMAT_MESSAGE_ALLOCATE_BUFFER |
    

    FORMAT_MESSAGE_FROM_SYSTEM, NULL, l, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //The user default language (LPTSTR) &lpMessageBuffer,
    0, NULL );

    SetLastError(0); MessageBox(NULL, tx2, "MyApplication", MB_ICONINFORMATION | MB_OK | (MB_SETFOREGROUND | MB_TOPMOST | MB_TASKMODAL));

}

RED SOFT ADAIR