Windows系統很早就加入了檔案關聯的功能,它大大增加了日常使用作業系統的便利性。所謂的檔案關聯就是指系統把指定副檔名的檔案自動關聯到相應的應用程式,比如.doc檔案預設情況下就自動和Microsoft Word關聯。當使用者雙擊.doc檔案的時候,系統會自動用Microsoft Word開啟它。這篇文章將介紹怎樣在Windows系統下面手動設定或者用程式自動化佈建檔案關聯。
如何手動設定檔案關聯
Windows系統(包括Windows XP、Windows Vista和Windows 7)都可以手動設定檔案關聯,下面以Windows 7為例解釋怎樣設定。
- 開啟控制台->程式->預設程式->關聯檔案類型或者協議與應用程式:
在上面的螢幕截屏上,我們可以看到.doc檔案類型為"Microsoft Word 97 - 2003 Document",其預設相關 App程式是Microsoft Word。使用者可以雙擊上面列表中的任何一條關聯記錄來設定自己的關聯。比如把TXT檔案關聯從預設的寫字板應用程式改成Microsoft Word。首先雙擊TXT檔案關聯記錄,彈出下面對話方塊。然後在其中選擇Microsoft Word應用程式預設開啟TXT檔案,確定之後即可。
如何編程添加檔案關聯
除了上面介紹的手動設定檔案關聯,我們還經常需要程式自動化佈建檔案關聯。比如,程式有預設的檔案格式,我們常常希望自動把該檔案格式和程式自動關聯起來。現在很多安裝包製作軟體(比如Install Shield) 都提供了類似的功能,它可以協助我們在安裝過程中設定檔案關聯。具體的設定方式大家參考相軟體使用手冊吧。這裡我想介紹如何自己寫程式來實現檔案關聯(該技術的經典用例就是希望在程式運行時首先檢查檔案關聯設定並在需要時添加指定檔案關聯設定)。
- 背景知識
-
Windows用註冊表來儲存當前系統的所有檔案關聯設定。它們一般存在下面的幾個登錄機碼中:
- HKEY_LOCAL_MACHINE\Software\Classes:該登錄機碼包括適用所有使用者的預設檔案關聯設定,如所示:
- HKEY_CURRENT_USER\Software\Classes:該登錄機碼包含只適用目前使用者的檔案關聯設定(它會覆蓋HKEY_LOCAL_MACHINE項中的設定)。如所示:
除上面兩個登錄機碼和檔案關聯相關外,還有另外一個非常重要的登錄機碼:HKEY_CLASSES_ROOT
該登錄機碼目裡面的設定是保證Windows瀏覽器能夠選擇正確的應用程式開啟相應檔案的關鍵所在。在Windows 2000之後,該登錄機碼目中的檔案關聯設定分別存在上面所說的兩個登錄機碼中去了。而HKEY_CLASS_ROOT 登錄機碼則成為融合(注意,對於相關的檔案類型,HKEY_CURRENT_USER下面的設定會覆蓋HKEY_LOCAL_MACHINE下面的設定)上面兩個登錄機碼內容的一個鏡像。為了更新檔案關聯設定,你必須更新"HKEY_CURRENT_USER\Software\Classess"或者"HKEY_LOCAL_MACHINE\Software\Classess"下的登錄機碼,而不是直接更新HKEY_CLASS_ROOT下的登錄機碼。
- 程式執行個體
典型的設定檔案關聯的程式邏輯如下:
- 檢查當前檔案類型是否已經關聯到某個應用程式(檢查HKEY_CLASS_ROOT登錄機碼,因為它包含了來自HKEY_LOCAL_MACHINE和HKEY_CURRENT_USER設定)。如果沒有該檔案類型的設定,則進入下一步。如果已經設定了相關的檔案關聯,則由你的商務邏輯確定需不需要覆蓋該檔案關聯。若需要,則也進入下一步。
- 添加相應的檔案關聯到登錄機碼中去(如果希望該設定只對目前使用者有效,則添加到HKEY_CURRENT_USER中,如果希望該設定對機器上的所有使用者有效,則添加HKEY_LOCAL_MACHINE中。
- 重新整理更新後的註冊表讓它生效。
具體代碼如下:
bool setFileAssociation(const wstring& ext,
const wstring& applicationName,
const wstring& progId,
const wstring& defaultIcon,
const wstring& description)
{
bool bRet = false;
HKEY hExtKey;
//檢查是否已經為該檔案類型設定檔案關聯
if(RegOpenKey(HKEY_CLASSES_ROOT, ext.c_str(), &hExtKey) == ERROR_SUCCESS)
{
HKEY hKey;
wstring HKCUPrefix = _T("Software\\Classes\\");
//設定檔案關聯(注意:需要設定一組值,包括檔案類型副檔名、描述、ProgId、預設表徵圖和Windows Shell啟動命令格式)
wstring fullExt = HKCUPrefix + ext;
if(ERROR_SUCCESS != RegCreateKey(HKEY_CURRENT_USER, fullExt.c_str(), &hKey)
|| ERROR_SUCCESS != RegSetValue(hKey, _T(""), REG_SZ, progId.c_str(), progId.length() * sizeof(wchar_t) + 1)
|| ERROR_SUCCESS != RegCloseKey(hKey))
{
throw exception(ext.c_str());
}
wstring fullProgId = HKCUPrefix + progId;
if(ERROR_SUCCESS != RegCreateKey(HKEY_CURRENT_USER, fullProgId.c_str(), &hKey)
|| ERROR_SUCCESS != RegSetValue(hKey, _T(""), REG_SZ, description.c_str(), description.length() * sizeof(wchar_t) + 1)
|| ERROR_SUCCESS != RegCloseKey(hKey))
{
throw exception(ext.c_str());
}
wstring strIconKey = fullProgId + _T(" \\DefaultIcon ");
if(ERROR_SUCCESS != RegCreateKey(HKEY_CURRENT_USER, strIconKey.c_str(), &hKey)
|| ERROR_SUCCESS != RegSetValue(hKey, _T(""), REG_SZ, defaultIcon.c_str(), defaultIcon.length() * sizeof(wchar_t) + 1)
|| ERROR_SUCCESS != RegCloseKey(hKey))
{
throw exception(ext.c_str());
}
wstring strShellKey = fullProgId + _T(" \\Shell ");
if(ERROR_SUCCESS != RegCreateKey(HKEY_CURRENT_USER, strShellKey.c_str(), &hKey)
|| ERROR_SUCCESS != RegSetValue(hKey, _T(""), REG_SZ, _T("Open"), 4 * sizeof(wchar_t) + 1)
|| ERROR_SUCCESS != RegCloseKey(hKey))
{
throw exception(ext.c_str());
}
wstring strCommandKey = fullProgId + _T(" \\Shell\\Open\\Command ");
wstring strCommand = applicationName + _T(" \"%1\"");
if(ERROR_SUCCESS != RegCreateKey(HKEY_CURRENT_USER, strCommandKey.c_str(), &hKey)
|| ERROR_SUCCESS != RegSetValue(hKey, _T(""), REG_SZ, strCommand.c_str(), strCommand.length() * sizeof(wchar_t) + 1)
|| ERROR_SUCCESS != RegCloseKey(hKey))
{
throw exception(ext.c_str());
}
//通知系統讓上面設定生效
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
bRet = true;
}
return bRet;
}
Del.icio.us : File Association, 檔案關聯