(有好的方法欢迎讨论)解决C++ filesystem 迭代器试图访问高权限文件夹报错问题
使用filesystem迭代器遍历C盘时程序报错退出。filesystem error: cannot increment recursive directory iterator: Invalid argument
起初以为是什么中文路径或者特殊符号在作妖,排查后发现不是。
之后尝试遍历其它目录全部正常,于是怀疑是C盘权限问题。
询问GPT报错原因,GPT给出的答案是遍历到的文件无法访问或者不存在(说得太对了)
GPT给出的方法是使用std::filesystem::exists(Path),检查目录或文件是否存在
但我寻思着迭代器自己遍历出来的文件怎么可能不存在,它又不会凭空产生一个就很迷惑
之后又经过反复调试输出最后一个遍历到的文件夹是C:\Documents and Settings,这不是用户文件目录吗怎么会出问题?
还有recycle bin之类的几个文件夹都能正常遍历,权限方面怎么会出问题?
然后我又尝试使用std::filesystem::file_status和std::filesystem::perms检查文件及文件夹权限,没问题权限都正常(肯定会返回正常啊)
我设置了skip_permission_denied,所以说“无权访问的文件都被跳过”了(没问题啊)
GPT搞不定我又上网搜索,中文资料数量为0,只有stackoverflow上有着几个零散的提问
提出的问题和我所遇到的一模一样,完全没有一个能用的方案
零零散散看到有提到使用boost库替代stl库就能够解决,那么问题究竟在哪里???
这台电脑上没下载ark工具,后来专门去爱盘下载了一个,看看C:\Documents and Settings到底是什么妖怪?
系统&隐藏,真有意思,我先前一直认为这是用户文件夹,不应该存在权限问题
直接给出解决方案好了,写一大篇胡话
每个文件夹都尝试创建迭代器,成功说明能访问,失败说明不能访问
bool canAccess(const std::filesystem::path &p) {
try {
std::filesystem::directory_iterator{p};
return true;
} catch (const std::filesystem::filesystem_error &e) {
return false;
}
}
std::filesystem::file_status和std::filesystem::perms有BUG
简直坑爹,stackoverflow上都在说已经设置了skip_permission_denied所以不用考虑权限问题
分明是std::filesystem::file_status和std::filesystem::perms有BUG,检查文件及文件夹权限都返回正常所以迭代器不会自动跳过,然后出错
而后我又把所有程序无权访问的文件夹都输出了,艾玛这不都是XP时代遗留的文件夹,为啥现在还不删掉?
有更好的方法欢迎大家讨论,这玩意儿太坑了
系统保护的文件夹,你得过滤掉,或者先判断是否可访问 在CMD使用dir /a看看,可以发现一堆隐藏文件(夹),有的是历史遗留问题有的有其他用途。
在实际遍历文件的时候可以根据文件的属性来确定要不要这个文件,通常的属性有只读、隐藏、系统文件、符号链接这种的,一般考虑普通文件属性就行了。
如果不考虑跨平台直接用系统调用会更准确,跨平台的话就考虑通用的情况。 Eaglecad 发表于 2024-5-17 20:17
系统保护的文件夹,你得过滤掉,或者先判断是否可访问
对,关键就是这个权限判断出问题了。
我能够找到是C:\Documents and Settings这个文件夹的问题是因为迭代器确实把它输出来了。但是迭代器在对这个文件夹下的目录进行遍历时就出现权限问题了。
帖子里也提到了我采用std::filesystem::file_status和std::filesystem::perms检查文件及文件夹权限,没问题权限都是正常的,但我猜测实际上有没有权限它根本就不知道,权限==NULL而不是权限==true || false,这个图片就是个好例子,我无权知道我有没有权限,而std::filesystem::file_status和std::filesystem::perms这俩家伙就忽略了这种情况,导致错误出现。
帖子最后提到的解决方案就是为每个遍历到的文件夹都尝试创建一个迭代器,成功说明有权限,报错说明没权限
艾玛这不都是XP时代遗留的文件夹,为啥现在还不删掉?
因为微软喜欢给开发者擦屁股,估计是有程序写死了这个路径,微软不想破坏那些程序兼容性。
还有一些例子比如 System32,32 位程序尝试访问的话其实会被悄悄重定向到 SysWow32。 本帖最后由 DEATHTOUCH 于 2024-5-17 23:50 编辑
还有一些例子比如 System32,32 位程序尝试访问的话其实会被悄悄重定向到 SysWow32。
捉虫,应该是SysWOW64
顺便,对于C:\Documents and Settings这个东西,其实是链接到C:\Users的,但是却不能直接遍历C:\Documents and Settings,这是一个问题。
比如说用CMD或者PowerShell去使用dir,会发现没东西或报错,但是手动指定“C:\Documents and Settings\<用户名>”却是可以的,这应该是系统的一个特殊处理。
如果使用NuShell,使用命令cd `C:\Documents and Settings\`会直接跳到C:\Users,因为它会解析这个符号链接。
如果直接用Windows API的FindFirstFile去搜索,发现当搜索“C:\Documents and Settings”时会返回INVALID_HANDLE_VALUE,传统的Win32API开发通常都会对返回值校验,而std::filesystem::file_status可能把因为这个结果抛出异常。
对于FindFirstFile打开“C:\Documents and Settings”,通过GetLastError可知是5,也就是拒绝访问(ACCESS DENIED)。同理,访问“C:\Program Files\WindowsApps”也是如此。这与Windows的权限管理有关,不是管理员权限就是最高权限,比如TrustedInstaller还有更高的呢。
一些链接:
https://learn.microsoft.com/zh-c ... eapi-findfirstfilea
https://learn.microsoft.com/zh-c ... error-codes--0-499-
页:
[1]