如果你電腦中裝有QQ,在IE地址欄輸入:“tencent://Message/?menu=yes&exe=&uin=13231462”然後[回車],立即可以與我的QQ建立臨時會話,如下圖:
Skype也有類似的功能。到底是如何實現的呢?看MSDN中有這麼一段話:
The IURLSearchHook interface is used by the browser to translate the address of an unknown URL protocol. When attempting to browse to a URL address that does not contain a protocol, the browser will first attempt to determine the correct protocol from the address. If this is not successful, the browser will create URL Search Hook objects and call each object's Translate method until the address is translated or all of the hooks have been queried.
IURLSearchHook接口被浏覽器用來轉換一個未知的URL協議地址。當浏覽器企圖去打開一個未知協議的URL地址時,浏覽器首先嘗試從這個地址得到當前的協議,如果不成功,浏覽器將創建在系統中注冊的URL Search Hook對象並調用每一個對象的Translate方法,直到地址被轉換或所有的URL Search Hook都嘗試過。
也就是說,我們可以注冊一種目前不存在的協議(類似HTTP),當浏覽器遇到新的協議時會自動調用Translate方法來翻譯我們的協議,甚至激活我們自己的程序。
以下源代碼將實現注冊一個新的自定義的Web協議:
// // 注冊自定義的Web協議 // return : ------------------------------------------------------------------------ // 0 - 失敗 // 1 - 成功 // 2 - 已經存在 // int RegWebProtocol ( LPCTSTR lpszProtocolName, LPCTSTR lpszAssociatedApp, int nIconIndex/*=0*/ ) { if ( !lpszProtocolName || lstrlen(lpszProtocolName) < 1 || !lpszAssociatedApp || lstrlen(lpszAssociatedApp) < 1 ) return 0; CString csSubKey; DWORD dwBufSize = 0; // 該協議已經存在 HKEY hKey = NULL; if ( RegOpenKeyEx ( HKEY_CLASSES_ROOT, lpszProtocolName, 0, KEY_ALL_ACCESS, &hKey ) == ERROR_SUCCESS ) { return 2; } else hKey = NULL; // 創建協議子鍵 if ( !CreateRegisterSubKey ( HKEY_CLASSES_ROOT, lpszProtocolName ) ) return 0; // 設置協議描述字符串 CString csProtocolDesc; csProtocolDesc.Format ( _T("%sProtocol"), lpszProtocolName ); dwBufSize = csProtocolDesc.GetLength(); if ( !WriteRegister ( HKEY_CLASSES_ROOT, lpszProtocolName, _T(""), REG_EXPAND_SZ, (PUCHAR)csProtocolDesc.GetBuffer(0),&dwBufSize) ) return 0; CString csAppFile; csAppFile.Format ( _T("%s"), lpszAssociatedApp ); dwBufSize = csAppFile.GetLength(); if ( !WriteRegister ( HKEY_CLASSES_ROOT, lpszProtocolName, _T("URL Protocol"), REG_EXPAND_SZ, (PUCHAR)csAppFile.GetBuffer(0),&dwBufSize) ) return 0; // DefaultIcon 子鍵 csSubKey.Format ( _T("%s\\DefaultIcon"), lpszProtocolName ); if ( !CreateRegisterSubKey ( HKEY_CLASSES_ROOT, csSubKey ) ) return 0; CString csIconParameter; csIconParameter.Format ( _T("%s,%d"), lpszAssociatedApp, nIconIndex ); dwBufSize = csIconParameter.GetLength(); if ( !WriteRegister ( HKEY_CLASSES_ROOT, csSubKey, _T(""), REG_EXPAND_SZ, (PUCHAR)csIconParameter.GetBuffer(0),&dwBufSize) ) return 0; // shell\open\command 子鍵 csSubKey.Format ( _T("%s\\shell\\open\\command"), lpszProtocolName ); if ( !CreateRegisterSubKey ( HKEY_CLASSES_ROOT, csSubKey ) ) return 0; CString csCommand; csCommand.Format ( _T("\"%s\" \"%%1\""), lpszAssociatedApp ); dwBufSize = csCommand.GetLength(); if ( !WriteRegister ( HKEY_CLASSES_ROOT, csSubKey, _T(""), REG_EXPAND_SZ, (PUCHAR)csCommand.GetBuffer(0),&dwBufSize) ) return 0; return 1; }
以下源代碼將刪除自定義的Web協議:
//
// 卸載自定義的Web協議
//
BOOL UnRegWebProtocol ( LPCTSTR lpszProtocolName )
{
if ( !lpszProtocolName || lstrlen(lpszProtocolName) < 1 )
return FALSE;
return RegDeleteAllSubKey ( HKEY_CLASSES_ROOT, lpszProtocolName );
}
我提供一個詳細的源代碼可以演示整個過程,程序界面如下:
先設置好需要注冊的協議名稱和關聯的執行程序文件名,然後點[Register Protocol]按鈕完成注冊,點擊[Test Protocol]按鈕測試注冊後的效果。
如本例中注冊一個“HXXP”協議,關聯程序就是本程序,當點擊[Test Protocol]按鈕時就會執行該程序的另一個副本,同時[Test URL Parameter]輸入的參數也被顯示出來了。您也可以將“HXXP://Para1/Para2/Para2”復制到IE地址欄中執行,實現相同的效果,如下圖:
最後,謝謝曹昌利同志講述QQ臨時會話的相關知識。
本文配套源碼