Win7下,擷取檔案夾C:\Users 大小時遇到的問題

來源:互聯網
上載者:User

最近在負責資料備份產品的時候遇到一個問題:在Win7系統下,使用者選擇“C:\Users” 作為備份源,發現產品UI上顯示的檔案夾大小和負責備份的Service進程裡的檔案夾大小不一致。

起先,我懷疑是擷取檔案夾大小的方法不對,但是查看代碼之後發現代碼是一樣的。都是枚舉檔案夾和檔案大小,然後累加。後來才發現,UI進程擷取該檔案夾大小的時候,很多目錄不能訪問;而Service進程能訪問該目錄下的所有檔案夾,所以得到的大小比UI上顯示的大很多。這樣確認是由於兩個進程的許可權不一致導致的。

該產品的架構是:UI進程是在目前使用者狀態下啟動並執行,故只有目前使用者的許可權;而後台Service進程是運行在System狀態下的,所以有最高許可權,夢訪問所有目錄。

問題本身:

首先,我們看看Win7下 目錄 C:\Users的內容(把 Hide和System都是設定為可見)

然後在C:\Users\All Users 目錄下,有個“Application Data” 目錄,這個目錄在資源管理員裡是不能訪問。

因為資源管理員實際上也是運行在目前使用者許可權下,所以UI進程取得的目錄大小和通過資源管理員查看屬性的方法看到的目錄大小是一致的。

如何解決問題:

然後我進一步對比這種目錄的屬性,發現“Application Data” 目錄除了具有FILE_ATTRIBUTE_DIRECTORY之外,還有FILE_ATTRIBUTE_SYSTEM、FILE_ATTRIBUTE_REPARSE_POINT以及FILE_ATTRIBUTE_NOT_CONTENT_INDEXED等屬性。但是我們又不能通過屬性來判斷為目前使用者無權訪問,因為有些類似目錄目前使用者是可以訪問的,比如使用者自己的“Application Data”目錄。

所以最完美的方案是:把Service進程的許可權從System降為目前使用者許可權。但是本人查了很多資料,還是不得要領,加上實施風險比較高,所以放棄了。

由於本案例中只要保持兩邊目錄大小顯示一直,所以最後想辦法把這個目錄大小通過UI進程傳給Service進程,而不是讓Service進程自己再擷取一次。

擷取目錄大小的方法:

下面是我們常用的擷取檔案夾大小的函數,僅供參考。

bool GetFolderSize(LPCWSTR szPath,  UInt64 *totalSize,   UInt64 *totalFiles,  UInt64 *totalFolders)
{
    if (NULL == szPath)
    {
        return false;
    }
    static const int MAX_PATH_LEN = 512;

    WCHAR szFileFilter[MAX_PATH_LEN] = {0};
    TCHAR szFilePath[MAX_PATH_LEN] = {0};
    HANDLE hFind = INVALID_HANDLE_VALUE;
    WIN32_FIND_DATA fileinfo;

    wcsncpy_s(szFilePath,szPath,MAX_PATH_LEN);
    wcscat_s(szFilePath,L"\\");
    wcsncpy_s(szFileFilter,szFilePath, MAX_PATH_LEN);
    wcscat_s(szFileFilter,L"*.*");

    hFind = FindFirstFile(szFileFilter,&fileinfo);
    if (INVALID_HANDLE_VALUE == hFind)
    {
        return false;
    }
    do
    {
        if(fileinfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        {
            if (!wcscmp(fileinfo.cFileName,L".") || !wcscmp(fileinfo.cFileName,L".."))
            {
                //Do nothing for "." and ".." folders
            }
            else
            {
                WCHAR sztmp[MAX_PATH_LEN];
                wcsncpy_s(sztmp,szFilePath,MAX_PATH_LEN);
                wcscat_s(sztmp,fileinfo.cFileName);

                GetFolderSize(sztmp, totalSize, totalFiles, totalFolders);
                if(totalFolders != NULL)
                {
                    ++(*totalFolders);
                }
            }
        }
        else
        {
            if(totalFiles != NULL)
            {
                ++(*totalFiles);
            }
        }

        if(totalSize != NULL)
        {
            (*totalSize) += ((UInt64)MAXDWORD+1) * fileinfo.nFileSizeHigh + fileinfo.nFileSizeLow;
        }
    }while(FindNextFile(hFind,&fileinfo));

    FindClose(hFind);
    hFind = INVALID_HANDLE_VALUE;
    return true;
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.