2

假设我正在将数据写入文件句柄:

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. 我可能有创建文件的权限,但没有删除它的权限。

我想要的是一种追溯指定的方法:

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

到我打开的文件。

我创建了文件!我当然可以取消创建它!都是因为我忘了事先指定一个标志?

4

3 回答 3

5

在 Windows Vista 和更新版本中,这可以使用SetFileInformationByHandle和来完成FILE_DISPOSITION_INFO

于 2013-01-28T22:58:09.530 回答
5

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

  1. FILE_SHARE_DELETE最初打开文件时指定。
  2. 再次打开它,指定FILE_FLAG_DELETE_ON_CLOSE
  3. 关闭第二个手柄。
  4. 当所有句柄都关闭时,该文件将被删除。

FILE_FLAG_DELETE_ON_CLOSE在以下文档的描述中进行了解释CreateFile

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


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

于 2013-01-28T23:03:11.533 回答
1

如果您使用的是 Windows 2003 服务器或 Vista 或更高版本,那么 ReOpenFile()就是您要找的。它允许您为重新打开的句柄指定一个新的“标志”参数。很遗憾,它显然在 XP 上不可用。

于 2013-01-28T22:58:41.983 回答