2017-02-22 103 views
0

我有一個掃描硬盤內容的Windows程序。我想在顯示有意義的進度欄的同時顯示。是否有快速獲取磁盤上文件總數的方法?這個數字不一定是確切的 - 一個近似值應該在10%左右。有沒有一種快速獲取磁盤上文件數的方法?

+0

您是否擁有管理員權限? [閱讀MFT的內容](http://stackoverflow.com/a/7459109/886887)提供了一種更快捷的方式來掃描磁盤的內容,如果你這樣做了,你可以通過保留一個進度條跟蹤[您已經處理了多少MFT百分比](http://stackoverflow.com/a/11337898/886887)。 –

+0

不幸的是 - 這個程序需要能夠在儘可能廣泛的環境下運行。 – Mark

回答

0

這對於NTFS卷是可能的。作爲Harry Johnston的一種方式write。也可能有其他方式,通過迭代文件記錄也足夠快:

struct NTFS_RECORD_HEADER 
{ 
    enum { 
     FILE = 'ELIF', 
     INDX = 'XDNI', 
     BAAD = 'DAAB', 
     HOLE = 'ELOH', 
     CHKD = 'DKHC' 
    } Type; 
    USHORT UsaOffset; 
    USHORT UsaCount; 
    USN Usn; 
}; 

struct NTFS_FILE_RECORD_HEADER : public NTFS_RECORD_HEADER 
{ 
    USHORT SequenceNumber; 
    USHORT LinkCount; 
    USHORT AttributesOffset; 
    USHORT Flags; 
    ULONG BytesInUse; 
    ULONG BytesAllocated; 
    ULONGLONG BaseFileRecord; 
    USHORT NextAttributeNumber; 

    enum{ 
     flgInUse = 1, flgDirectory = 2 
    }; 
}; 

ULONG GetFileCount(HANDLE hVolume, PULONG FileCount) 
{ 
    NTFS_VOLUME_DATA_BUFFER nvdb; 

    ULONG cb, BytesReturned; 
    if (!DeviceIoControl(hVolume, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, &nvdb, sizeof(nvdb), &BytesReturned, NULL)) 
    { 
     return GetLastError(); 
    } 

    NTFS_FILE_RECORD_INPUT_BUFFER nfrib; 

    cb = FIELD_OFFSET(NTFS_FILE_RECORD_OUTPUT_BUFFER, FileRecordBuffer[nvdb.BytesPerFileRecordSegment]); 

    PNTFS_FILE_RECORD_OUTPUT_BUFFER pnfrob = (PNTFS_FILE_RECORD_OUTPUT_BUFFER)alloca(cb); 

    union { 
     PVOID FileRecordBuffer; 
     NTFS_RECORD_HEADER* pnrh; 
     NTFS_FILE_RECORD_HEADER* pnfrh; 
    }; 

    FileRecordBuffer = pnfrob->FileRecordBuffer; 

    // get maximum valid FileReferenceNumber 
    ULONG a = 0, b = MAXLONG, N; 
    do 
    { 
     nfrib.FileReferenceNumber.QuadPart = N = (a + b) >> 1; 

     DeviceIoControl(hVolume, FSCTL_GET_NTFS_FILE_RECORD, 
      &nfrib, sizeof nfrib, pnfrob, cb, &BytesReturned, 0) ? a = N + 1 : b = N; 

    } while(a < b); 

    if (!b) 
    { 
     return ERROR_GEN_FAILURE; 
    } 

    N = 0; 
    nfrib.FileReferenceNumber.QuadPart = b - 1; 

    // itterate [0, nfrib.FileReferenceNumber.QuadPart) 
    do 
    { 
     if (DeviceIoControl(hVolume, FSCTL_GET_NTFS_FILE_RECORD, 
      &nfrib, sizeof nfrib, pnfrob, cb, &BytesReturned, 0)) 
     { 
      // are really file 
      if (
       pnrh->Type == NTFS_RECORD_HEADER::FILE && 
       pnfrh->Flags & NTFS_FILE_RECORD_HEADER::flgInUse && 
       !pnfrh->BaseFileRecord 
       ) 
      { 
       N++; 
      } 
     } 
     else 
     { 
      pnfrob->FileReferenceNumber.QuadPart = nfrib.FileReferenceNumber.QuadPart; 
     } 

    } while (0 <= (nfrib.FileReferenceNumber.QuadPart = pnfrob->FileReferenceNumber.QuadPart - 1)); 

    *FileCount = N; 

    return NOERROR; 
} 
相關問題