介绍伪协议前先介绍一下协议是什么。这里说到的协议不是指网络上的TCP/IP协议,而是操作系统提供支持的一种协议,类似标准协议HTTP, FTP。自定义协议叫做伪协议。
如何注册一个伪协议?
在windows系统下,这种伪协议就是通过修改注册表来实现的。具体的注册表项目路径有两个:
计算机\HKEY_CLASSES_ROOT\sandbox.worldeditor\shell\open
计算机\HKEY_CURRENT_USER\Software\Classes\sandbox.worldeditor\shell\open\command
上述路径中的sandbox.worldeditor字样,就是自定义的伪协议名称。
或者这么描述,注册表路径带有shell\open\command的,都是伪协议。
我们在注册表内[HKEY_CLASSES_ROOT]下添加一项对我们软件支持的协议标志即可!
[HKEY_CLASSES_ROOT\zzz] zzz:代表你的协议的名称
@="URL:zzz Protocol" 这项必须的有 值可以为空
"URL Protocol"=""
[HKEY_CLASSES_ROOT\zzz\shell]
[HKEY_CLASSES_ROOT\zzz\shell\open]
[HKEY_CLASSES_ROOT\zzz\shell\open\command]
@="\"C:\\Windows\\System32\\osk.exe\" \"%1\"",最后command的值是系统把协议数据传给的接受程序。
注:C:\\Windows\\System32\\osk.exe 这个路径就是你的应用程序所在的绝对路径。
注册完后我们就可以应用这个协议:zzz://xxxxxx
我们输入这段协议后会把 zzz://xxxxxx 这个的内容加入命令行来启动我们自定的接受程序。
/// @brief 注册一个伪协议
/// @param[in] szProName 协议名字,其实就是伪协议的标识
/// @param[in] szDescription 伪协议的描述
/// @param[in] szExePath 遇到该伪协议时,系统会自动调用这个EXE程序进行解析
/// @remark 使用方式为"szProName://+参数"
/// @return true成功,false失败
bool AddFakeProtocol(std::wstring szProName, std::wstring szDescription, std::wstring szExePath)
{
bool bRet = false;
HKEY hKey = NULL;
HKEY hSubKey = NULL;//hKey的子键
HKEY hSubKey2 = NULL;//hSubKey得子键
HKEY hSubKey3 = NULL;//hSubKey2的子键
if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CLASSES_ROOT, szProName.c_str(), 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL))
{
RegCloseKey(hKey);
return bRet;
}
if (ERROR_SUCCESS != RegSetValueEx(hKey, NULL, 0, REG_SZ, //这是协议描述
(LPBYTE)(LPCTSTR)szDescription.c_str(), szDescription.length()*2+1))
{
RegCloseKey(hKey);
return bRet;
}
if (ERROR_SUCCESS != RegSetValueEx(hKey, L"URL Protocol", 0, REG_SZ,
(LPBYTE)(LPCTSTR)szExePath.c_str(), szExePath.length()*2+1))
{
RegCloseKey(hKey);
return bRet;
}
//图标在下面设置
if (ERROR_SUCCESS != RegCreateKeyEx(hKey, L"DefaultIcon", 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hSubKey, NULL))
{
RegCloseKey(hKey);
RegCloseKey(hSubKey);
return bRet;
}
//图标在上面设置
RegCloseKey(hSubKey);
if (ERROR_SUCCESS != RegCreateKeyEx(hKey, L"shell", 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hSubKey, NULL))
{
RegCloseKey(hKey);
RegCloseKey(hSubKey);
return bRet;
}
if (ERROR_SUCCESS != RegCreateKeyEx(hSubKey, L"open", 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hSubKey2, NULL))
{
RegCloseKey(hKey);
RegCloseKey(hSubKey);
RegCloseKey(hSubKey2);
return bRet;
}
if (ERROR_SUCCESS != RegCreateKeyEx(hSubKey2, L"command", 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hSubKey3, NULL))
{
RegCloseKey(hKey);
RegCloseKey(hSubKey);
RegCloseKey(hSubKey2);
RegCloseKey(hSubKey3);
return bRet;
}
//
std::wstring strCommand = _T("\"") + szExePath + _T("\" \"%1\"");
if (ERROR_SUCCESS == RegSetValueEx(hSubKey3, NULL, 0, REG_SZ,
(LPBYTE)(LPCTSTR)strCommand.c_str(), strCommand.length()*2+1))
{
bRet = true;
}
RegCloseKey(hSubKey3);
RegCloseKey(hSubKey2);
RegCloseKey(hSubKey);
RegCloseKey(hKey);
return bRet;
}
注册协议:AddFakeProtocol(_T("zzz"), _T("this is test by kandy"), _T("C:\\Windows\\System32\\osk.exe"));
测试刚才注册的协议:
<html>
<head>
<title>测试伪协议</title>
</head>
<body>
测试页面<br />
<input id="button1" type="button" value="伪协议" onclick="return window.open('zzz://test')">
</body>
</html>
或者在浏览器(最好是IE,其他浏览器会默认为搜索)地址栏中输入:zzz://test,进行测试!