使用FindFirstFile()进行文件遍历,为什么有的目录下的文件或者子目录无法遍历出来

使用FindFirstFile()进行文件遍历,为什么有的目录下的文件或者子目录无法遍历出来
 int SearchFile(string path, int* num, map<string, string>* _path)
{


    string buffer = "";
    buffer = path + "\\*.*";
    _WIN32_FIND_DATAA pNextInfo;//保存文件信息
    HANDLE hFile = 0;
    hFile = FindFirstFileA(buffer.c_str(), &pNextInfo);
    int a = GetLastError();
    if (a && (a != 2)) {
        string errorpath = path+ " : " + to_string(a);
        WriteErrorToLog(errorpath);
    }
    if (hFile != INVALID_HANDLE_VALUE)//
    {
        do
        {
            if (pNextInfo.cFileName[0] == '.' || pNextInfo.cFileName[0] == '..')//过滤.和..
                continue;
            //dwFileAttributes值是可以一位或多位的,不好直接使用"=="来判断
            if (pNextInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)//判断是否为文件夹
            {
                buffer = path + "\\" + pNextInfo.cFileName;//将文件夹追加到目录,成为下一级要搜索目录
                SearchFile(buffer, num, _path);//递归
            }
            ULARGE_INTEGER ulFileSize;
            //求得文件的大小
            ulFileSize.LowPart = GetCompressedFileSizeA((pNextInfo.cFileName), &(pNextInfo.nFileSizeHigh));
            __int64 creattime = *(__int64*)&(pNextInfo.ftCreationTime);//将FILETIME转换成
            __int64 writetime = *(__int64*)&(pNextInfo.ftLastWriteTime);
            //将文件绝对路径,创建时间,修改时间,文件大小拼接
            string str = path + "\\" + pNextInfo.cFileName + to_string(creattime) + to_string(writetime) + to_string(ulFileSize.LowPart);
            //遍历结束一个文件路径进行++
            //将文件的属性全部存到map中

            //求出exe,dll文件
            string str_ed = pNextInfo.cFileName;
            int size = str_ed.size();
            if (size > 3) {
                string str_1 = str_ed.substr(size - 3);
                //|| strcmp(str_1.c_str(), "exe") == 0
                //|| strcmp(str_1.c_str(), "exe") == 0 || strcmp(str_1.c_str(), "bat") == 0
                if (strcmp(str_1.c_str(), "dll") == 0) {
                    string _md5 = md5(str);
                    buffer = path + "\\" + pNextInfo.cFileName;
                    (*num)++;
                    (*_path).insert(pair<string, string>(buffer, _md5));//存储到map中

                }
            }

        } while (FindNextFileA(hFile, &pNextInfo));//遍历文件
    }
    FindClose(hFile);
    return 0;
}

img

最终遍历出来的文件个数要和everything搜索出来的文件个数要相符合

害,在查了好多资料还有在网上查问题后,发现了三个问题,一是重定向问题,二是权限问题,三是函数使用,判断出错。
1.重定向问题:是因为在在win64下,system32会重定向到SysWOW64,因此在遍历的时候后出现错误,解决的方法是在你进行遍历的时候加上下面这段代码。

PVOID OldValue = NULL;
    //关闭系统重定向
    if (Wow64DisableWow64FsRedirection(&OldValue)) {
        //查找指定路径
        hFile = FindFirstFileA(buffer.c_str(), &pNextInfo);
        if (FALSE == Wow64RevertWow64FsRedirection(OldValue))
            return NULL;
    }

2.权限问题:提升权限,反正我是将exe程序注册成了服务
3.函数使用问题
在我上面的代码我的strcmp()在进行判断时他区分了大小写,因此在遍历文件时才会出现遍历不完全,dll,exe等文件有的后缀时大写的,可以使用stricmp()函数进行比较。

system("dir /b /a-d c:\\*.* >d:\\allfiles.txt");
//读文件d:\\allfiles.txt的内容即C:\\下所有文件的名字
system("dir /b /a-d /s c:\\*.* >d:\\allfilesinsub.txt");
//读文件d:\\allfilesinsub.txt的内容即C:\\下所有文件的名字包含子目录
system("dir /b /ad  c:\\*.* >d:\\alldirs.txt");
//读文件d:\\alldirs.txt的内容即C:\\下所有子目录的名字
请记住,能用shell命令获取文件文件夹信息或者操作文件文件夹最好用shell命令获取或者操作,而不要用各种API获取或者操作,因为当遇到非法文件夹名或非法文件名或非法文件长度非法文件日期压缩文件链接文件稀疏文件……等各种意料之外的情况时,API会处理的不全面或陷入死循环,而shell命令不会
如果嫌system黑窗口一闪,将system("...")替换为WinExec("cmd /c ...",SW_HIDE);