如何取消创建文件

时间:2013-01-28 22:19:14

标签: winapi file-io error-handling

让我们说我正在将数据写入文件句柄:

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();
}

如果我的数据写入失败,我想要在关闭句柄时删除文件。即:我希望文件“un-CreatFile'd”


我已经尝试了显而易见的,如果出现问题则删除文件:

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;
}

这种方法存在两个问题:

  1. 有一个竞争条件,有人可以在关闭它之后打开我的文件,但在我删除它之前
  2. 我可能有权创建文件,但不能删除
  3. 我想要的是一种 追溯 指定的方式:

      

    FILE_FLAG_DELETE_ON_CLOSE:文件将在所有句柄关闭后立即删除,包括指定的句柄和任何其他打开或重复的句柄。

    到我打开的文件。

    我创建了文件!当然我可以解开它!所有这些都是因为我忘了事前指定一面旗帜?

3 个答案:

答案 0 :(得分:5)

在Windows Vista及更高版本中,可以使用SetFileInformationByHandleFILE_DISPOSITION_INFO完成此操作。

答案 1 :(得分:5)

在所有版本的Windows中,您都可以

  1. 最初打开文件时指定FILE_SHARE_DELETE
  2. 第二次打开它,指定FILE_FLAG_DELETE_ON_CLOSE
  3. 关闭第二个手柄。
  4. 关闭所有句柄后,文件将被删除。
  5. FILE_FLAG_DELETE_ON_CLOSE的文档中的CreateFile说明中解释了这一点:

      

    该文件将在所有句柄关闭后立即删除,其中包括指定的句柄和任何其他打开或重复的句柄。   如果文件存在打开的句柄,则除非使用FILE_SHARE_DELETE共享模式打开所有句柄,否则调用将失败。


    如果自动删除不够好,您可以查看Transactional NTFS,将文件创建和所有写入放入事务中,然后在必要时将其回滚。

答案 2 :(得分:1)

如果您使用的是Windows 2003服务器或Vista或更高版本,ReOpenFile()就是您正在寻找的。它允许您为重新打开的句柄指定新的“flags”参数。很遗憾,它显然不适用于XP。