How to un-CreateFile

2020-02-29 11:27发布

问题:

Let us say that i am writing data to a file handle:

hFile = CreateFile(filename, GENERICREAD | GENERICWRITE, 0, null, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
//[snip error check]
try
{
   if (!WriteFile(hFile, buffer, count, ref bytesWritten, null))
       throw new Win32Exception(GetLastError());
}
finally
{
   CloseHandle();
}

If my write of data failed, i want the file to be deleted when i close the handle. I.e.: i want the file to be "un-CreatFile'd".


i've tried the obvious, delete the file if there was a problem:

hFile = CreateFile(filename, GENERICREAD | GENERICWRITE, 0, null, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
//[snip error check]
try
{
   try
   {
      if (!WriteFile(hFile, buffer, count, ref bytesWritten, null))
          throw new Win32Exception(GetLastError());
   }
   finally
   {
      CloseHandle();
   }
}
catch
{
   DeleteFile(filename);
   throw;
}

There are two problems with that approach:

  1. There's a race condition, where someone could open my file after i close it, but before i delete it
  2. i might have permission to Create a file, but not the Delete it.

What i would like is a way to retroactively specify:

FILE_FLAG_DELETE_ON_CLOSE: The file is to be deleted immediately after all of its handles are closed, which includes the specified handle and any other open or duplicated handles.

to the file that i have open.

i created the file! Surely i can uncreate it! All because i forgot to specify a flag before-hand?

回答1:

In all versions of Windows, you can

  1. Specify FILE_SHARE_DELETE when opening the file originally.
  2. Open it a second time, specifying FILE_FLAG_DELETE_ON_CLOSE
  3. Close the second handle.
  4. The file will be deleted when all handles are closed.

This is explained in the FILE_FLAG_DELETE_ON_CLOSE description in the documentation for CreateFile:

The file is to be deleted immediately after all of its handles are closed, which includes the specified handle and any other open or duplicated handles. If there are existing open handles to a file, the call fails unless they were all opened with the FILE_SHARE_DELETE share mode.


If the automatic deletion isn't good enough, you could look into Transactional NTFS, putting file creation and all writes into a transaction, and then rolling it back if necessary.



回答2:

In Windows Vista and newer, this could be done using SetFileInformationByHandle and FILE_DISPOSITION_INFO.



回答3:

If you're using Windows 2003 server or Vista or higher, ReOpenFile() is what you're looking for. It allows you to specify a new 'flags' parameter for the reopened handle. Shame it's apparently not available on XP.