如何计算GetModuleFileName的完整缓冲区大小?

Fra*_*cis 12 windows winapi getmodulefilename

GetModuleFileName()需要一个缓冲器和缓冲器作为输入的大小; 但是它的返回值只能告诉我们复制了多少个字符,以及大小是否足够(ERROR_INSUFFICIENT_BUFFER).

如何确定保存整个文件名的实际所需缓冲区大小GetModuleFileName()

大多数人使用,MAX_PATH但我记得路径可以超过(默认定义为260)...

(使用零作为缓冲区大小的技巧对这个API不起作用 - 我之前已经尝试过)

RBe*_*eig 10

通常的方法是调用它将大小设置为零,并保证失败并提供分配足够缓冲区所需的大小.分配缓冲区(不要忘记空终止的空间)并再次调用它.

在很多情况下MAX_PATH就足够了,因为许多文件系统限制了路径名的总长度.但是,可以构建超出合法且有用的文件名MAX_PATH,因此查询所需缓冲区可能是一个很好的建议.

不要忘记最终从提供缓冲区的分配器返回缓冲区.

编辑:弗朗西斯在评论中指出,通常的配方不起作用GetModuleFileName().不幸的是,弗朗西斯在这一点上是绝对正确的,我唯一的理由是在提供"通常"的解决方案之前,我没有去查看它.

我不知道该API的作者在想什么,除了有可能在它被引入时,MAX_PATH确实是最大可能的路径,使正确的配方变得容易.只需在长度不小于MAX_PATH字符的缓冲区中进行所有文件名操作.

哦,是的,不要忘记自1995年以来的路径名允许使用Unicode字符.由于Unicode需要更多空间,因此可以在任何路径名之前\\?\明确请求MAX_PATH删除对该名称的字节长度限制.这使问题复杂化.

MSDN在文章名称,路径和命名空间的文章中有关于路径长度的说法:

最大路径长度

在Windows API中(以下段落中讨论了一些例外),路径的最大长度为MAX_PATH260个字符.本地路径按以下顺序构成:驱动器号,冒号,反斜杠,由反斜杠分隔的组件以及终止空字符.例如,驱动器D上的最大路径是" D:\<some 256 character path string><NUL>",其中" <NUL>"表示当前系统代码页的不可见终止空字符.(< >这里使用的字符是为了清晰起见,不能成为有效路径字符串的一部分.)

注意Windows API中的文件I/O函数将" /" 转换为" \"作为将名称转换为NT样式名称的一部分,除非使用" \\?\"前缀,如以下部分所述.

Windows API具有许多函数,这些函数也具有Unicode版本,以允许扩展长度路径,最大总路径长度为32,767个字符.这种类型的路径由用反斜杠分隔的组件组成,每个组件lpMaximumComponentLength都是GetVolumeInformation函数参数中返回的值 .要指定扩展长度路径,请使用" \\?\"前缀.例如," \\?\D:\<very long path>".(< >这里使用的字符是为了清晰起见,不能成为有效路径字符串的一部分.)

注意最大路径为32,767个字符是近似值,因为\\?\系统在运行时可以将" "前缀扩展为更长的字符串,并且此扩展适用于总长度.

" \\?\"前缀也可以与根据通用命名约定(UNC)构造的路径一起使用.要使用UNC指定此类路径,请使用" \\?\UNC\"前缀.例如," \\?\UNC\server\share",其中"server"是机器的名称,"share"是共享文件夹的名称.这些前缀不会用作路径本身的一部分.它们表明路径应该以最小的修改传递给系统,这意味着您不能使用正斜杠来表示路径分隔符,也不能使用句点来表示当前目录.此外,您不能将" \\?\"前缀与相对路径一起使用,因此相对路径仅限于MAX_PATH 前面所述的不使用" \\?\"前缀的路径的字符.

使用API​​创建目录时,指定的路径不能太长,以至于无法附加8.3文件名(即目录名不能超过MAX_PATH减去12).

shell和文件系统有不同的要求.可以使用Windows用户界面可能无法处理的Windows API创建路径.

因此,一个简单的答案是分配一个大小的缓冲区MAX_PATH,检索名称并检查错误.如果它适合,你就完成了.否则,如果它以" \\?\" 开头,则获得一个大小为64KB左右的缓冲区(上面的"最大路径为32,767个字符是近似的"这句话有点麻烦,所以我要留下一些细节供进一步研究)再试一次.

溢出MAX_PATH但不以" \\?\" 开头似乎是"不可能发生"的情况.同样,那么你需要处理的细节是什么.

对于以" \\Server\Share\" 开头的网络名称的路径长度限制,可能还会有一些混淆,更不用说以" \\.\" 开头的内核对象名称空间中的名称.上面的文章没有说明,我不确定这个API是否会返回这样的路径.


sha*_*oth 9

实现一些合理的策略来增长缓冲区,比如从MAX_PATH开始,然后使每个连续的大小比前一个大1.5倍(或者2次迭代次数更少).迭代直到函数成功.