在Windows系统中使用纯C语言创建一个独特的临时目录

12
我想在Windows中使用一些C代码(不是C++或C#)创建一个独特的临时目录。 我想这样做是为了将一些临时文件放入该目录中,然后在完成时轻松地删除它们(通过递归删除目录)。 我基本上正在寻找mkdtemp函数的等效项。有一个C#答案here,并且在this question的响应建议使用Boost。 但由于我正在使用C,所以这些解决方案对我无效。到目前为止,我能想出的最好的方法是使用GetTempFileName然后是CreateDirectory,但问题在于,如果我要求GetTempFileName创建唯一的文件名,它也会创建文件(这是我不想要的,因为我想代替创建一个目录)。
相关的是,有一个GetTempPath函数,它从环境变量中返回用户临时文件夹的位置 - 但由于我想创建自己的目录,以后可以安全地删除,所以我仍然需要在它返回的任何路径内创建一个目录。
看起来,如果我想创建一个唯一的目录,我必须创建一个临时文件,获取文件名,删除它,然后使用相同的名称创建一个目录 - 这听起来非常混乱。还有其他的想法吗?

3
你最后一段的想法行不通 - 它会受到竞态条件的影响。 - nobody
3个回答

9
您可以使用 GetTempPath 返回的路径与一个 Guid 连接起来,以确保目录的唯一性。您可以使用 UuidCreate CoCreateGuid Function 创建 Guid。
要递归删除目录,这里有一个纯 C 示例:如何递归地删除目录? 例子中使用了 FindFirstFile、FindNextFile、DeleteFile 和 RemoveDirectory
还有一个更加复杂的方法是使用 SHFileOperation,但它基于 Windows Shell 函数,而 Shell DLL 并不总是需要的,特别是当您正在编写服务器代码时。

我考虑使用 GUID 或 UUID,但我不知道如何将它们转换为字符串。进一步的查找带我到 StringFromGUID2,这可能会起作用,只要它不会生成不能放在文件名中的字符?看起来它只会生成十六进制字符串,应该没问题。 - Timothy Jones
@ Timothy - 标准的 GUID 格式适用于文件名,但是,既然您不需要这些 GUID 格式,则您不需要显式地使用 StringFromGUIS2。您可以使用十六进制格式编写的 16 个字节的串联手动生成文件名。 - Simon Mourier

4

使用 GetTempPath 函数获取临时文件路径,然后在该路径下使用随机名称创建目录,如果由于已存在该目录而导致 CreateDirectory 函数失败,则可以选择重试。但是,如果您的名称生成足够好,那么与现有名称发生冲突的可能性要比黑客猜测您的密码甚至私人密钥的可能性小得多,因此您也可以忽略它。


1
这基本上就是 mkdtemp 所做的事情(当然包括重试)。 - andrewdski

3
使用 _tempnamtmpnam_s 创建一个尚不存在的文件名,然后使用 CreateDirectory 创建目录。如果这样做,技术上存在竞争条件,因为在你生成文件名和创建目录之间的时间内,另一个进程可能会使用该名称创建文件或目录,但这种情况的概率相当小。为了防止这种情况,可以循环直到成功。
要递归删除目录树,可以使用 SHFileOperation。或者,您也可以使用 FindFirstFile/FindNextFileDeleteFileRemoveDirectory 自己进行目录遍历。
如果您想在退出时自动删除目录,请使用 atexit 注册一个函数。这仅适用于正常程序终止(即通过 exit 函数或通过从 main/WinMain 返回)。这不适用于异常程序终止(例如通过 abort、访问冲突、其他人调用 TerminateProcess 等)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接