我发现WINDOWS通过执行FindNextFile来显示所有文件的,但是却有一个例外,那就是每个逻辑分区下的第一个文件或者文件夹不是这样的,比如“C:\”下的第一个文件的显示没有通过FindNextFile,有谁知道为什么吗?

解决方案 »

  1.   

    你可在控制台窗口下,输入dir,即可看到。。所以,你在枚举目录下文件的时候,需要用CFileFind::IsDots()判断,是否找到的是该目录,是则跳过参考http://blog.csdn.net/lixiaosan/archive/2006/04/07/654277.aspx
      

  2.   

    你可设置第二个参数lpFindFileData规定其要查询的文件类型
      

  3.   

    FindFristFile返回的是“..”,然后下面的所有文件都是通过FindNextFile来显示的,我这里是说API函数,不是MFC里包装好的类的成员函数。
    我是希望彻底了解WINDOWS显示文件的细节。
      

  4.   

    比如说我E盘下有以下几个文件(夹):11,b.txt,c.exe
    则执行FindNextFile的记录是:b.txt,c.exe如果某个文件夹下有同样的文件:11,b.txt,c.exe
    则执行FindNextFile的记录是:11,b.txt,c.exe就是有这么一个区别。
      

  5.   

    举个例子:WIN32_FIND_DATA fd;
    HANDLE hFind = ::FindFirstFile(_T("*.*"),&fd);
    //::FindFirstFile(m_strFilePath + "\\*.*", &fd);
    if(hFind != INVALID_HANDLE_VALUE)
    {
    do
    {
    //读取文件与读取目录的区别在于if里面的!呵呵
    if(!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
    TRACE(_T("%s\n"),fd.cFileName); }while(::FindNextFile(hFind,&fd));
    ::FindClose(hFind);
    }//"."当前目录
    //".."上一级目录Try it!
      

  6.   

    The FindNextFile function searches for files by name only; it cannot be used for attribute-based searches.
      

  7.   

    换句话说就是对“C:\”和“C:\TEST”分别执行FindNextFile是有区别的,所以怀疑windows对磁盘根目录下的第一个文件的显示采取了特殊处理。“每个文件夹都包含两个默认的隐含的目录,一个是 "." ,表示当前目录,一个是"..",表示上级目录”我是知道的。
      

  8.   

    The order in which this function returns the file names is dependent on the
    file system type. With NTFS and CDFS file systems, the names are returned in
    alphabetical order. With FAT file systems, the names are returned in the
    order the files were written to the disk, which may or may not be in
    alphabetical order.
      

  9.   

    你应该看看我上面的代码,注意这里“//读取文件与读取目录的区别在于if里面的!呵呵”Try it!
      

  10.   

    据我所知道的,windows显示某个目录下的所有文件的步骤是:
    1、WIN32_FIND_DATA fd;
    HANDLE hFind = ::FindFirstFile(_T("*.*"),&fd);
    其中fd->cFileName就是“..”,hFind 用于FindNextFile(hFind,&fd)的入参。2、执行FindNextFile(hFind,&fd)
    其中,fd->cFileName就是当前找到的文件(夹)名。第一个文件也在此中,唯独就是磁盘根目录下的不在这里面出现。我是通过写文件的形式记录下来的。这个问题的意义就在于只要解决了这个问题,就完全可以通过HOOK FindNextFile实现隐藏所有文件,不然,每个磁盘根目录下的第一个文件隐藏不了。
      

  11.   

    对根目录FindFirstFile()没有'.'和'..'这两个特殊的目录。所以FindFirstFile()会找到实际显示的第一个目录或者文件。
      

  12.   

    to: lfchen(一条晚起的虫) ( ) 信誉:100 
    但是我跟踪FindFirstFile并记录在文件,它找到的总是C:\WINNT\Web目录下的一个folder.htt文件。不管是根目录还是普通目录。
      

  13.   

    也许有人怀疑我的依据,我现在是HOOK了FindFirstFileA、FindFirstFileW和FindNextFileA、FindNextFileW,在我替换的函数体里先调用原函数,然后只是简单记录得到的数据,再返回。我并不HOOK我写的这个程序,所以我自己调用原函数是没有影响的。
      

  14.   

    大家仔细看一下我后面的回复,我跟本就没做任何处理,只是简单记录了操作系统的行为,我的目的不是列举某个目录下的所有文件,而是在探讨windows是怎么列举的。
      

  15.   

    这里不是有很多MVP和版主的吗,怎么没一个人知道?
      

  16.   

    和楼主同感啊为什么知道地人不能回答一下呢?帮助别人就是帮助自己PS:bs那些目光短浅地所谓高手
      

  17.   

    ::FindFirstFile(_T("*"),&fd);不要用
    ::FindFirstFile(_T("*.*"),&fd);
      

  18.   


    #define FINDFILE_CONTINUE 0
    #define FINDFILE_ABORT 1
    #define FINDFILE_BREAK 2
    #define FINDFILE_SKIP 3typedef DWORD (WINAPI *LPFINDFILE_NOTIFY_ROUTINE)(
    LPWIN32_FIND_DATA lpFindData, LPCTSTR lpPath
    );class CFindFile
    {
    public:
    CFindFile( void );
    BOOL Find( LPCTSTR lpRootPath, LPFINDFILE_NOTIFY_ROUTINE lpFindRoutine,
    BOOL bRecursionFind = TRUE, LPCTSTR lpWildcard = NULL );
    private:
    void ResetWildcard( void );
    BOOL FindProc( LPCTSTR lpRootPath );
    DWORD FindNotify( const LPWIN32_FIND_DATA lpFindData, LPCTSTR lpPath );
    private:
    TCHAR m_szWildcard[MAX_PATH];
    DWORD m_dwWildcardLen;
    BOOL m_bRecursionFind;
    LPFINDFILE_NOTIFY_ROUTINE m_lpFindRoutine;
    };
    #include "findfile.h"CFindFile::CFindFile( void )
    {
    m_bRecursionFind = TRUE;
    m_lpFindRoutine = NULL;
    ResetWildcard();
    }void CFindFile::ResetWildcard( void )
    {
    m_szWildcard[0] = _T('*');
    m_szWildcard[1] = _T('\0');
    m_dwWildcardLen = 1;
    }BOOL CFindFile::Find( LPCTSTR lpRootPath,
     LPFINDFILE_NOTIFY_ROUTINE lpFindRoutine,
     BOOL bRecursionFind, LPCTSTR lpWildcard )
    {
    if ( NULL == lpRootPath || NULL == lpFindRoutine )
    {
    SetLastError( ERROR_INVALID_PARAMETER );
    return FALSE;
    }
    // 重置通配符
    ResetWildcard();
    // 如果指定了通配符
    if ( lpWildcard != 0 )
    {
    // 测算通配符长度
    m_dwWildcardLen = (DWORD)lstrlen( lpWildcard );
    // 如果长度超标则返回错误
    if ( m_dwWildcardLen >= MAX_PATH )
    {
    m_dwWildcardLen = 1;
    SetLastError( ERROR_INVALID_PARAMETER );
    return FALSE;
    }
    // 复制通配符到成员
    lstrcpyn( m_szWildcard, lpWildcard, MAX_PATH );
    }
    m_bRecursionFind = bRecursionFind;
    m_lpFindRoutine = lpFindRoutine;
    return FindProc( lpRootPath );
    }DWORD CFindFile::FindNotify( LPWIN32_FIND_DATA lpFindData, LPCTSTR lpPath )
    {
    // 检查是否找到的是路径引导
    LPCTSTR lpName = lpFindData->cFileName;
    return m_lpFindRoutine( lpFindData, lpPath );
    }BOOL CFindFile::FindProc( LPCTSTR lpRootPath )
    {
    TCHAR szFullName[MAX_PATH];
    WIN32_FIND_DATA stFindData;
    // 获得根目录添加通配符后的字符串长度
    DWORD dwFullNameLen = lstrlen( lpRootPath ) + m_dwWildcardLen + 1; if ( dwFullNameLen >= MAX_PATH )
    {
    SetLastError( ERROR_FILE_NOT_FOUND );
    return FALSE;
    }
    // 为目录增加通配符
    lstrcpyn( szFullName, lpRootPath, MAX_PATH );
    lstrcat( szFullName, _T("\\") );
    lstrcat( szFullName, m_szWildcard ); // 开始查找第一个文件,出错则退出
    HANDLE hFindFile = FindFirstFile( szFullName, &stFindData );
    if ( hFindFile == INVALID_HANDLE_VALUE )
    {
    return ERROR_ACCESS_DENIED == GetLastError();
    } BOOL bReturn = TRUE;
    // 准备FullName;
    lstrcpyn( szFullName, lpRootPath, MAX_PATH );
    lstrcat( szFullName, _T("\\") );
    dwFullNameLen = lstrlen( szFullName );
    // 开始循环查找文件
    while ( TRUE )
    {
    // 调用通知
    DWORD dwResult = FindNotify( &stFindData, lpRootPath );
    if ( FINDFILE_ABORT == dwResult )
    {
    bReturn = FALSE;
    SetLastError( ERROR_OPERATION_ABORTED );
    break;
    }
    if ( FINDFILE_BREAK == dwResult )
    {
    break;
    }
    // 如果找到的是路径,并且允许递归,用户也没有跳过,则查找子文件夹
    if ( stFindData.cFileName[0] != _T('.') &&
    (stFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
    m_bRecursionFind && FINDFILE_SKIP != dwResult )
    {
    lstrcpy( &szFullName[0] + dwFullNameLen, stFindData.cFileName ); // 递归调用查找
    if ( FALSE == FindProc( szFullName ) )
    {
    // 如果出错继续返回错误
    bReturn = FALSE;
    break;
    }
    } // 如果找不到更多的文件
    if ( FALSE == FindNextFile( hFindFile, &stFindData ) )
    {
    // 判断是否出错
    if ( GetLastError() != ERROR_NO_MORE_FILES )
    {
    bReturn = FALSE; 
    }
    // 跳出循环
    break;
    }
    } // 关闭查找文件句柄
    FindClose( hFindFile ); // 返回错误码
    return bReturn;
    }
      

  19.   

    谢谢fireseed(奶油狗【奥伊斯特拉赫的声音简直不可思异!】) 共享代码但可能是我的标题没写清楚,导致某些兄弟误会,我要了解的是操作系统在显示磁盘根目录下的所有文件,和显示某个文件夹下的所有文件稍有不同,就是对第一个文件或文件夹的处理上不太一样.
    请大家再看看我的所有回复:---------------------------------------------------------------------------------
     zhun_yi(zhunyi) ( ) 信誉:100  2006-5-29 10:36:46  得分: 0  
       
    FindFristFile返回的是“..”,然后下面的所有文件都是通过FindNextFile来显示的,我这里是说API函数,不是MFC里包装好的类的成员函数。
    我是希望彻底了解WINDOWS显示文件的细节。---------------------------------------------------------------------------------
     zhun_yi(zhunyi) ( ) 信誉:100  2006-5-29 10:41:31  得分: 0  
      
    比如说我E盘下有以下几个文件(夹):11,b.txt,c.exe
    则执行FindNextFile的记录是:b.txt,c.exe如果某个文件夹下有同样的文件:11,b.txt,c.exe
    则执行FindNextFile的记录是:11,b.txt,c.exe就是有这么一个区别。-----------------------------------------------------------------
     zhun_yi(zhunyi) ( ) 信誉:100  2006-5-29 10:45:21  得分: 0  
       
    换句话说就是对“C:\”和“C:\TEST”分别执行FindNextFile是有区别的,所以怀疑windows对磁盘根目录下的第一个文件的显示采取了特殊处理。“每个文件夹都包含两个默认的隐含的目录,一个是 "." ,表示当前目录,一个是"..",表示上级目录”我是知道的。----------------------------------------------------------------------------
     zhun_yi(zhunyi) ( ) 信誉:100  2006-5-29 10:54:32  得分: 0  
       
    据我所知道的,windows显示某个目录下的所有文件的步骤是:
    1、WIN32_FIND_DATA fd;
    HANDLE hFind = ::FindFirstFile(_T("*.*"),&fd);
    其中fd->cFileName就是“..”,hFind 用于FindNextFile(hFind,&fd)的入参。2、执行FindNextFile(hFind,&fd)
    其中,fd->cFileName就是当前找到的文件(夹)名。第一个文件也在此中,唯独就是磁盘根目录下的不在这里面出现。我是通过写文件的形式记录下来的。这个问题的意义就在于只要解决了这个问题,就完全可以通过HOOK FindNextFile实现隐藏所有文件,不然,每个磁盘根目录下的第一个文件隐藏不了。-------------------------------------------------------------------------------
      
     zhun_yi(zhunyi) ( ) 信誉:100  2006-5-29 11:11:22  得分: 0  
       
    to: lfchen(一条晚起的虫) ( ) 信誉:100 
    但是我跟踪FindFirstFile并记录在文件,它找到的总是C:\WINNT\Web目录下的一个folder.htt文件。不管是根目录还是普通目录。-------------------------------------------------------------------------
     zhun_yi(zhunyi) ( ) 信誉:100  2006-5-29 11:37:28  得分: 0  
       
    也许有人怀疑我的依据,我现在是HOOK了FindFirstFileA、FindFirstFileW和FindNextFileA、FindNextFileW,在我替换的函数体里先调用原函数,然后只是简单记录得到的数据,再返回。我并不HOOK我写的这个程序,所以我自己调用原函数是没有影响的。------------------------------------------------------------------------
     zhun_yi(zhunyi) ( ) 信誉:100  2006-5-31 8:28:22  得分: 0  
       
    大家仔细看一下我后面的回复,我跟本就没做任何处理,只是简单记录了操作系统的行为,我的目的不是列举某个目录下的所有文件,而是在探讨windows是怎么列举的。
      

  20.   

    不知道你还有什么问题。第一个文件没有什么不同。如果你的通配符使用了“*.*”,那么像“aa”这样的文件是无法被找到的。所以通配符一定要使用“*”找C盘下的所有文件:
    WIN32_FIND_DATA stFindData;
    FindFirstFile( "c:\*", &stFindData );如果还有什么文件找不到,我负责
      

  21.   

    有点问题:FindFirstFile( "c:\\*", &stFindData );剩下的代码你自己补
      

  22.   

    还有,FindFirstFile本身就会查到一个文件,不要漏掉