windows - FindFirstFile springe over en mappe

Indlæg af Hanne Mølgaard Plasc

Problem



Ok, det gør mig skør. Jeg skriver et simpelt program, der går ned i katalogtræet og ser på størrelserne af alle filer på min drev. Temmelige tamme ting.


Men jeg har bemærket, at jeg ikke fik det svar, jeg forventede. Det viser sig, at min kode er hoppe over nogle mapper. For at starte, her er en (forenklet) version af min kode:


#include <stdio.h>
#include <Windows.h>

int main()
{
  WIN32\_FIND\_DATA fd;
  HANDLE h = FindFirstFile(L"c:\Windows\System32\wbem\*.*", &fd);

  if (h !=  INVALID\_HANDLE\_VALUE)
  {
    BOOL b;
    do {
      if (fd.dwFileAttributes & FILE\_ATTRIBUTE\_DIRECTORY)
          printf("d: \%S
", fd.cFileName);
      //else
      //    printf("f: \%S
", fd.cFileName);

      b = FindNextFile(h, &fd);
    } while (b != FALSE);
    FindClose(h);
  }
}


Udgangen jeg får er stort set, hvad du ville forvente:


d: .
d: ..
d: AutoRecover
d: en-US
d: Logs
d: Repository
d: tmf
d: xml


Men fra en kommandoprompt i c: \ Windows \ System32 \ wbem, dir /ad giver mig:


06/15/2016  07:20 PM    <DIR>          .
06/15/2016  07:20 PM    <DIR>          ..
04/14/2016  05:40 PM    <DIR>          AutoRecover
03/24/2011  03:52 PM    <DIR>          en-US
07/13/2009  06:34 PM    <DIR>          Logs
07/13/2009  09:08 PM    <DIR>          MOF
02/20/2017  10:32 PM    <DIR>          Performance
02/23/2017  03:59 AM    <DIR>          Repository
07/13/2009  06:36 PM    <DIR>          tmf
07/13/2009  07:20 PM    <DIR>          xml
               0 File(s)              0 bytes
              10 Dir(s)  171,203,104,768 bytes free


En tæt undersøgelse viser, at katalogerne Performance og MOF ikke er angivet i min output. Huh?


Det er klart, at noget er anderledes med disse mapper. Men hvad?



  • Se på udgangen dir, vi kan se, at de ikke er kryds.

  • Ved atrib er der ingen særlige flag indstillet (som system eller skjult).

  • fsutil viser ikke nogen hårde links.

  • Se på bibliotekstilladelserne, Administratorer (som jeg er) har fuld kontrol.



Jeg er stumped. Jeg har selv gået så langt som at køre chkdsk /f for at se, om min katalogtabeller er skruet op. Andre end nogle Cleaning up 472 unused index entries from index $SII of file 0x9. Cleaning up 472 unused index entries from index $SDH of file 0x9. fandt den ikke noget.


Jeg har forsøgt at bruge FindFileEx med forskellige muligheder, men jeg kan stadig ikke få disse mapper til at blive vist.


Jeg kan ikke tænke på, hvad jeg skal prøve. Hvad ville få disse mapper til at blive vist til dir, men ikke til FindFile? Og (vigtigere) hvordan kan jeg få dem til at blive vist i FindFile?


FWIW:



  • Windows 7 Professional x64

  • Drev C er NTFS

  • Bygning med MSVC 2010


Bedste reference


Din kode forsøger at få adgang til 64-bit System32 mappen.


Jeg gætter på din kode er udarbejdet som 32-bit, så du ville faktisk få adgang til 32-bit SysWOW64 mappen i stedet på grund af File System Redirector. På min Win7 x64-maskine er de manglende mapper (MOF og Performance) findes kun i 64-bit System32wbem mappen, men ikke i 32-bit SysWOW64wbem mappen. [27]


Hvis 32-bit kode ønsker at få adgang til 64-bit System32 mappen, skal den bruge WOW64s special Sysnative alias for at undgå omdirigering, fx:


HANDLE h = FindFirstFile(L"c:\Windows\Sysnative\wbem\*.*", &fd);


Brug IsWow64Process() for at vide, om din kode kører inde i WOW64-emulatoren eller ej. [28]


Med det sagt bør du heller ikke kode c:\Windows banen. Ikke alle brugere installerer Windows til den pågældende sti. Brug GetWindowsDirectory(), SHGetFolderPath(CSIDL\_WINDOWS) eller SHGetKnownFolderPath(FOLDERID\_Windows) i stedet for at få den faktiske vej. [29] [30] [31]


Prøv noget mere som dette:


bool IsRunningInWow64()
{
    #ifndef \_WIN64
    BOOL bIsWow64 = FALSE;
    if (IsWow64Process(GetCurrentProcess(), &bIsWow64) && bIsWow64)
        return true;
    #endif

    return false;
}

...

WCHAR szMask[MAX\_PATH];

if (IsRunningInWow64())
{
    // Must be a 32-bit process running on a 64-bit system.
    // Use the 'Sysnative' alias...

    GetWindowsDirectory(szMask, MAX\_PATH);
    // or: SHGetFolderPath(..., CSIDL\_WINDOWS, ...);
    // or: SHGetKnownFolderPath(FOLDERID\_Windows, ...);
    PathAppend(szMask, L"Sysnative");
}
else
{
    // Must be either:
    // - A 32-bit process running on a 32-bit system.
    // - A 64-bit process running on a 64-bit system.
    // Use the standard 'System32' path...

    GetSystemDirectory(szMask, MAX\_PATH);
    // or: SHGetFolderPath(..., CSIDL\_SYSTEM, ...);
    // or: SHGetKnownFolderPath(FOLDERID\_System, ...);
}

PathAppend(szMask, L"wbem");
PathAppend(szMask, L"*.*");

HANDLE h = FindFirstFile(szMask, &fd);