VC.NET擴充Windows磁碟清理工具的功能

來源:互聯網
上載者:User
引言

  Windows磁碟清理工具(Disk CleanUp)是一個實用快捷並擁有簡單易用介面的系統清理軟體,更值得系統開發管理員注意的是,此系統清理軟體是建立在以COM技術為基礎發展的,支援第三方外掛程式,並且可以根據需要自製定義功能二次開發的平台。在這裡,我們對於Windows磁碟清理工具的開發介面做深入地研究,在此基礎上舉例示範添加一個尋找“*.tmp”臨時檔案的功能。

  技術討論

  微軟的COM技術廣泛地運用在Windows的模組化設計中,致使支援二次開發。關於COM技術基礎與應用,可參考。在此,我們只為Windows磁碟清理工具,簡稱清理工具的擴充介面加以分解。清理工具首次出現在Windows 98作業系統中,並在後來推出的Windows版本中予以改進,添加了新的功能。比如說,在NTFS的檔案系統下,自動壓縮不經常訪問的檔案。這些新功能通過COM模組實現,在清理工具中作為外掛程式調用。早期的版本是通過IEmptyVolumeCache介面調用,在Windows 2000以後的版本中,還加入了IEmptyVolumeCache2介面,加入了較小的更新。

  IEmptyVolumeCache介面由五個函數組成,根據呼叫的順序,分別是:

virtual /* [local] */ HRESULT STDMETHODCALLTYPE Initialize(
/* [in] */ HKEY hkRegKey,
/* [in] */ LPCWSTR pcwszVolume,
/* [out] */ LPWSTR *ppwszDisplayName,
/* [out] */ LPWSTR *ppwszDescription,
/* [out] */ DWORD *pdwFlags) = 0;

virtual HRESULT STDMETHODCALLTYPE GetSpaceUsed(
/* [out] */ DWORDLONG *pdwlSpaceUsed,
/* [in] */ IEmptyVolumeCacheCallBack *picb) = 0;

virtual HRESULT STDMETHODCALLTYPE ShowProperties(
/* [in] */ HWND hwnd) = 0;

virtual HRESULT STDMETHODCALLTYPE Purge(
/* [in] */ DWORDLONG dwlSpaceToFree,
/* [in] */ IEmptyVolumeCacheCallBack *picb) = 0;

virtual HRESULT STDMETHODCALLTYPE Deactivate(
/* [out] */ DWORD *pdwFlags) = 0;

  清理工具在正常執行時,首先調用Initialize初始化外掛程式,隨後執行GetSpaceUsed來掃描可清除的檔案大小。掃描完畢後,清理工具的主介面就出現了如圖1所示,在此,我們加入了清理TMP檔案的功能可以瀏覽不同的清理檔案種類。列表中的每一個檔案種類均由一個COM外掛程式實現。除了閱覽可清理檔案大小以外,使用者在可以點擊一個可自訂的按鈕,調用外掛程式的ShowProperties功能,以顯示更詳細的資料。如使用者選擇OK,清理工具就調用Purge函數,清理掃描出來的檔案。最後,Deactivate函數被調用,終止外掛程式的應用。

  運用於Windows 2000以後的清理工具的外掛程式也應該支援IEmptyVolumeCache的介面。IEmptyVolumeCache只由一個函數組成:

virtual /* [local] */ HRESULT STDMETHODCALLTYPE InitializeEx(

/* [in] */ HKEY hkRegKey,
/* [in] */ LPCWSTR pcwszVolume,
/* [in] */ LPCWSTR pcwszKeyName,
/* [out] */ LPWSTR *ppwszDisplayName,
/* [out] */ LPWSTR *ppwszDescription,
/* [out] */ LPWSTR *ppwszBtnText,
/* [out] */ DWORD *pdwFlags) = 0;

  InitializeEx增加了更嚴格的本地化語言要求,加強了國際化的支援,並且允許自訂按鈕的顯示文字。pdwFlags變數用於在工具與外掛程式間傳遞資訊,支援下列旗標:

EVCF_OUTOFDISKSPACE
EVCF_SETTINGSMODE
EVCF_DONTSHOWIFZERO
EVCF_ENABLEBYDEFAULT
EVCF_ENABLEBYDEFAULT_AUTO
EVCF_HASSETTINGS
EVCF_REMOVEFROMLIST

  EVCF_OUTOFDISKSPACE與EVCF_SETTINGSMODE用於工具傳遞給外掛程式的設定。EVCF_OUTOFDISKSPACE表示當前硬碟的空餘空間非常有限,需要儘可能多地清理,即使是系統的效能會受到影響。EVCF_SETTINGSMODE表示可定期執行的無人控制模式。在此模式下,GetSpaceUsed,Purge,及ShowProperties都將不予調用,所有清理任務應予InitializeEx時執行。其它旗標用於外掛程式傳遞給工具的不同運行模式。EVCF_DONTSHOWIFZERO表示在沒有找到可刪除檔案時不顯示此類型,EVCF_ENABLEBYDEFAULT表示此類型檔案可以安全刪除,EVCF_ENABLEBYDEFAULT_AUTO表示此類型檔案可以非常安全的刪除,EVCF_HASSETTINGS表示此外掛程式支援ShowProperties功能,可以顯示詳細資料。EVCF_REMOVEFROMLIST表示是一次性清理任務,清理工具在執行後自動將外掛程式關閉,以後不再執行。



圖1 清理工具的主介面

  實現方法

  我們開發一個新的清理工具外掛程式,掃描並清理*.TMP檔案。COM的編程有多種方法,我們選擇了ATL庫。關於ATL庫的運用。

  我們在Visual Studio .Net 2003中產生新的ATL的DLL Server項目,並使用Add Class加入新的ATL Simple Object控制項類CCleanSimpleHandler。在定義中,我們讓CCleanSimpleHandler從IEmptyVolumeCache2繼承。並且,我們添加了下列變數:

// 儲存掃描出檔案的大小

DWORDLONG m_dwlFileSize;

// 儲存根目錄

WCHAR m_strRootDir[MAX_PATH];

// 儲存掃描出檔案清單

std::vector<WCHAR *> m_lstFilesToDel;

  然後,我們一一實現IEmptyVolumeCache及IEmptyVolumeCache2介面的函數。在下面的代碼清單中,沒有包括嚴格的檢查錯誤傳回值。這是為了簡短代碼的長度,提高可讀性。在實際應用中,檢查錯誤傳回值是不可少的。為了不同版本Windows相容,我們在InitializeEx中調用Initialize。

HRESULT CCleanSimpleHandler::InitializeEx (HKEY hKey, LPCWSTR pcwszVolume, LPCWSTR pcwszKeyName, LPWSTR *ppwszDisplayName, LPWSTR *ppwszDescription, LPWSTR *ppwszBtnText, DWORD *pdwFlags)
{
 HRESULT hr = Initialize (hKey, pcwszVolume, ppwszDisplayName, ppwszDescription, pdwFlags);
 *ppwszBtnText = (LPWSTR) CoTaskMemAlloc (64 * sizeof (WCHAR));
 StrCpyW(*ppwszBtnText, L"View files");
 return hr;
}

HRESULT CCleanSimpleHandler::Initialize (HKEY hKey, LPCWSTR pcwszVolume, LPWSTR *ppwszDisplayName, LPWSTR *ppwszDescription, DWORD *pdwFlags)
{
 StrCpyW(m_strRootDir, pcwszVolume);
 *ppwszDisplayName = (LPWSTR) CoTaskMemAlloc(256 * sizeof (WCHAR));
 StrCpyW(*ppwszDisplayName, L"*.TMP files");
 *ppwszDescription = (LPWSTR) CoTaskMemAlloc (256 * sizeof (WCHAR));
 StrCpyW(*ppwszDescription, L"Temporary files - *.TMP");
 *pdwFlags = EVCF_HASSETTINGS | EVCF_ENABLEBYDEFAULT;
 m_dwlFileSize = 0;
 return S_OK;
}

  在GetSpaceUsed中,我們調用ScanDir來掃描*.TMP檔案,儲存在m_lstFilesToDel中。GetSpaceUsed的第二個參數是IEmptyVolumeCacheCallBack介面的指標,用於調用其ScanProgress函數以報告掃描的進展情況。ScanProgress函數定義是:

HRESULT ScanProgress(DWORDLONG dwlSpaceUsed, DWORD dwFlags, LPCWSTR pwszReserved);

  其中dwFlags正常應設為零,在結束時改為EVCCBF_LASTNOTIFICATION。ScanProgress函數的傳回值很重要,因為使用者可以在任何時候中斷在進行中的清理任務。如ScanProgress返回E_ABORT,GetSpaceUsed應最快終端掃描,函數返回。因此,我們在遞迴的目錄掃描函數ScanDir中,加入了如中斷立即退出的功能。

HRESULT CCleanSimpleHandler::GetSpaceUsed (DWORDLONG *pdwSpaceUsed,  IEmptyVolumeCacheCallBack *picb)
{
 m_dwlFileSize = 0;
 ScanDir(m_strRootDir, picb);
 picb->ScanProgress(m_dwlFileSize, EVCCBF_LASTNOTIFICATION ,NULL);
 *pdwSpaceUsed = m_dwlFileSize;
 return S_OK;
}

bool CCleanSimpleHandler::ScanDir(WCHAR * szDir, IEmptyVolumeCacheCallBack *pcib)
{
 WCHAR strPath[MAX_PATH];
 WCHAR* pchPathFileName;
 bool cancelled = false;
 WIN32_FIND_DATAW fd;
 HANDLE hFind;

 if (cancelled = FAILED(pcib->ScanProgress(m_dwlFileSize, NULL, NULL))) return false;
 StrCpyW(strPath,szDir);
 PathAppendW(strPath, L"*");
 pchPathFileName = strPath+lstrlenW(strPath)-1;
 hFind = FindFirstFileW(strPath, &fd);
 if (hFind == INVALID_HANDLE_VALUE) // E.g. Due to security issues
  return true;
  do {
   StrCpyW(pchPathFileName, fd.cFileName);
   if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
    if (fd.cFileName[0] != '.') {
     if (cancelled = !ScanDir(strPath, pcib)) break;
    }
   } else {
    WCHAR* pchExt = PathFindExtensionW(strPath);
    if ( StrCmpIW(pchExt, L".tmp") == 0 ) {
     m_dwlFileSize += ((DWORDLONG)fd.nFileSizeHigh)*4294967295+fd.nFileSizeLow;
     WCHAR* filename = (WCHAR *)CoTaskMemAlloc((lstrlenW(strPath)+1)*sizeof(WCHAR));
     StrCpyW(filename, strPath);
     m_lstFilesToDel.push_back(filename);
    }
   }

  } while (FindNextFileW(hFind, &fd) != NULL);
  FindClose(hFind);
  return !cancelled;
}

  其他的函數很簡單。Purge函數將掃描出的檔案清單m_lstFilesToDel中的檔案一一刪除。ShowProperties中,我們顯示掃描出來的檔案。最後,Deactivate將分配的記憶體釋放。

HRESULT CCleanSimpleHandler::Purge (DWORDLONG dwSpaceToFree, IEmptyVolumeCacheCallBack *picb)
{
 for (unsigned int i=0; i < m_lstFilesToDel.size(); ++i)
  DeleteFileW(m_lstFilesToDel[i]);
  return S_OK;
}

HRESULT CCleanSimpleHandler::ShowProperties (HWND hWnd)
{
 for (unsigned int i=0; i < m_lstFilesToDel.size(); ++i)
  if (MessageBoxW(hWnd, m_lstFilesToDel[i], L"View files",
   MB_OKCANCEL|MB_ICONINFORMATION)==IDCANCEL) break;
   return S_OK;
}

HRESULT CCleanSimpleHandler::Deactivate (LPDWORD pdwFlags)
{
 for (unsigned int i=0; i < m_lstFilesToDel.size(); ++i)
  CoTaskMemFree(m_lstFilesToDel[i]);
  m_lstFilesToDel.clear();
  *pdwFlags = 0;
  return S_OK;

  結論和建議

  通過執行個體分解,我們對Windows磁碟清理工具的基於COM技術的開發介面做了深入地研究。Windows外殼中有較多的開發介面,本文介紹的開發思想也可以運用在其它擴充外掛程式中。
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.