熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

VC.NET擴展Windows磁盤清理工具的功能

2022-06-13   來源: .NET編程 

  摘 要 介紹了Windows磁盤清理工具二次開發的擴展接口對其COM接口加以分解並運用ATL庫具體實現了清理*tmp臨時文件的功能

  關鍵詞 磁盤清理工具ATL庫COM接口

  引言

  Windows磁盤清理工具(Disk CleanUp)是一個實用快捷並擁有簡單易用界面的系統清理軟件更值得系統開發管理人員注意的是此系統清理軟件是建立在以COM技術為基礎發展的支持第三方插件並且可以根據需要自制定義功能二次開發的平台在這裡我們對於Windows磁盤清理工具的開發接口做深入地研究在此基礎上舉例示范添加一個查找*tmp臨時文件的功能

  技術討論

  微軟的COM技術廣泛地運用在Windows的模塊化設計中致使支持二次開發關於COM技術基礎與應用可參考在此我們只為Windows磁盤清理工具簡稱清理工具的擴展接口加以分解清理工具首次出現在Windows 操作系統中並在後來推出的Windows版本中予以改進添加了新的功能比如說在NTFS的文件系統下自動壓縮不經常訪問的文件這些新功能通過COM模塊實現在清理工具中作為插件調用早期的版本是通過IEmptyVolumeCache接口調用在Windows 以後的版本中還加入了IEmptyVolumeCache接口加入了較小的更新

  IEmptyVolumeCache接口由五個函數組成根據呼叫的順序分別是

  

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

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

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

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

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

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

  運用於Windows 以後的清理工具的插件也應該支持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) = ;

  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表示可定期執行的無人控制模式在此模式下GetSpaceUsedPurge及ShowProperties都將不予調用所有清理任務應予InitializeEx時執行其它旗標用於插件傳遞給工具的不同運行模式EVCF_DONTSHOWIFZERO表示在沒有找到可刪除文件時不顯示此類型EVCF_ENABLEBYDEFAULT表示此類型文件可以安全刪除EVCF_ENABLEBYDEFAULT_AUTO表示此類型文件可以非常安全的刪除EVCF_HASSETTINGS表示此插件支持ShowProperties功能可以顯示詳細信息EVCF_REMOVEFROMLIST表示是一次性清理任務清理工具在執行後自動將插件關閉以後不再執行

  

  圖 清理工具的主界面

  實現方法

  我們開發一個新的清理工具插件掃描並清理*TMP文件COM的編程有多種方法我們選擇了ATL庫關於ATL庫的運用

  我們在Visual Studio Net 中生成新的ATL的DLL Server項目並使用Add Class加入新的ATL Simple Object控件類CCleanSimpleHandler在定義中我們讓CCleanSimpleHandler從IEmptyVolumeCache繼承並且我們添加了下列變量

  

  // 儲存掃描出文件的大小

DWORDLONG m_dwlFileSize;

// 儲存根目錄

WCHAR m_strRootDir[MAX_PATH];

// 儲存掃描出文件列表

std::vector<WCHAR *> m_lstFilesToDel;

  然後我們一一實現IEmptyVolumeCache及IEmptyVolumeCache接口的函數在下面的代碼列表中沒有包括嚴格的檢查錯誤返回值這是為了簡短代碼的長度提高可讀性在實際應用中檢查錯誤返回值是不可少的為了不同版本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
ppwszDescriptionpdwFlags);
 *ppwszBtnText = (LPWSTR) CoTaskMemAlloc ( * sizeof (WCHAR));
 StrCpyW(*ppwszBtnText LView files);
 return hr;
}

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

  在GetSpaceUsed中我們調用ScanDir來掃描*TMP文件儲存在m_lstFilesToDel中GetSpaceUsed的第二個參數是IEmptyVolumeCacheCallBack接口的指針用於調用其ScanProgress函數以報告掃描的進展情況ScanProgress函數定義是

  HRESULT ScanProgress(DWORDLONG dwlSpaceUsed DWORD dwFlags LPCWSTR pwszReserved)

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

  

  HRESULT CCleanSimpleHandler::GetSpaceUsed (DWORDLONG *pdwSpaceUsed
IEmptyVolumeCacheCallBack *picb)
{
 m_dwlFileSize = ;
 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;
 WIN_FIND_DATAW fd;
 HANDLE hFind;

 if (cancelled = FAILED(pcib>ScanProgress(m_dwlFileSize NULL NULL)))
return false;
 StrCpyW(strPathszDir);
 PathAppendW(strPath L*);
 pchPathFileName = strPath+lstrlenW(strPath);
 hFind = FindFirstFileW(strPath &fd);
 if (hFind == INVALID_HANDLE_VALUE) // Eg Due to security issues
  return true;
  do {
   StrCpyW(pchPathFileName fdcFileName);
   if ((fddwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
    if (fdcFileName[] != ) {
     if (cancelled = !ScanDir(strPath pcib)) break;
    }
   } else {
    WCHAR* pchExt = PathFindExtensionW(strPath);
    if ( StrCmpIW(pchExt Ltmp) == ) {
     m_dwlFileSize += ((DWORDLONG)fdnFileSizeHigh)*+
fdnFileSizeLow;
     WCHAR* filename = (WCHAR *)CoTaskMemAlloc((lstrlenW(strPath)+)*
sizeof(WCHAR));
     StrCpyW(filename strPath);
     m_lstFilesToDelpush_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=; i < m_lstFilesToDelsize(); ++i)
  DeleteFileW(m_lstFilesToDel[i]);
  return S_OK;
}

HRESULT CCleanSimpleHandler::ShowProperties (HWND hWnd)
{
 for (unsigned int i=; i < m_lstFilesToDelsize(); ++i)
  if (MessageBoxW(hWnd m_lstFilesToDel[i] LView files
   MB_OKCANCEL|MB_ICONINFORMATION)==IDCANCEL) break;
   return S_OK;
}

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

  結論和建議

  通過實例分解我們對Windows磁盤清理工具的基於COM技術的開發接口做了深入地研究Windows外殼中有較多的開發接口本文介紹的開發思想也可以運用在其它擴展插件中


From:http://tw.wingwit.com/Article/program/net/201311/13334.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.