由扩展名获取其关联程序的安装路径
一、理论基础
在Windows操作系统中安装(无需安装的例外)任何外部的应用程序都需要在注册表(其本身是一个数据库)中进行信息(包括安装路径,默认Icon图标等信息)注册,应用程序的安装程序在注册表中建立了一个从文件扩展名到程序启动(或打开、打印等)路径的映射关系(此关系见下图文分析)。因此可以利用这个从扩展名到关联程序的映射关系获取关联程序的安装路径。
映射关系解析:映射信息在HKEY_CLASSES_ROOT根键下
1.扩展名 >> 对应的扩展名子键D >> 子键C的默认键的键值d >>
键值d就是关联程序信息所在的子键E >>
“子键E\shell\open\command”下的默认键的键值f就是关联成许的路径信息
2.以".txt"扩展名为示例,以图文方式解说:
由".txt"子键 >> (默认 REG_SZ)EditPlus 3.txt >> "EditPlus 3.txt"子键
"EditPlus 3.txt"子键 >> ..\shell\open\command子键 >>( 默认 REG_SZ)D:\apps\EditPlus\EDITPLUS.EXE
3.需要使用的Windows API 函数(具体信息查看MSDN Libary)
a.打开注册表函数
LONG WINAPI RegOpenKeyEx(
__in HKEY hKey, //根键句柄,此处使用HKEY_CLASSES_ROOT根键
__in_opt LPCTSTR lpSubKey, //要查询的子键路径
__reserved DWORD ulOptions, //必须置为NULL
__in REGSAM samDesired, //权限掩码,由于只查询,故使用KEY_QUERY_VALUE
__out PHKEY phkResult //保存返回子键的句柄
);
b.读取注册表项键值函数
LONG WINAPI RegQueryValueEx(
__in HKEY hKey, //子键句柄,可通过RegOpenKeyExt函数获得
__in_opt LPCTSTR lpValueName, //键的名称
__reserved LPDWORD lpReserved, //必须置为NULL
__out_opt LPDWORD lpType, //键的类型,此处使用REG_SZ或REG_MULTI_SZ
__out_opt LPBYTE lpData, //用于保存返回信息的变量
__inout_opt LPDWORD lpcbData //设置返回信息长度
);
c.关闭查询句柄
LONG WINAPI RegCloseKey(
__in HKEY hKey //子键句柄
);
二、功能实现
1.实现环境:Window 7、编程语言 VC++、 编程架构MFC Dialog、IDE-VS2010
2.实现代码
a.Dialog布局
b.查询操作代码:
void CReg_WRDlg::OnBtnWRreg() //WM_BTNCLICK消息响应函数
{
// 注册表层级概念: 根键 | 子键(包括子键、二级子键、三级子键、n级子键)| 键 | 键值
HKEY hkey;
char sz[256];
DWORD dwtype=REG_SZ, sl=256;
LONG ret;
LPCSTR extName = _T(".txt");
//不知道为什么一个函数中先后读取两个注册表项信息时就会导致第二读取信息有误
//因此才分离出一个函数单独读取“扩展名”子键的信息
CString lpcstrExt = FromExtGetRelateAppPath(extName);
CString cstrFullPath = lpcstrExt + _T("\\shell\\open\\command"); // EditPlus 3.txt\\shell\\open\\command
LPCSTR lpcstrFullPath = cstrFullPath.GetBuffer(); //将CString转成LPCSTR
cstrFullPath.ReleaseBuffer();
//通过获取的关联程序的注册表子键值来查找关联程序的路径
::memset(sz,0,sizeof(sz));
ret = RegOpenKeyEx(HKEY_CLASSES_ROOT,
lpcstrFullPath/*="EditPlus 3.txt\\shell\\open\\command"*/,
NULL,
KEY_QUERY_VALUE,
&hkey); //成功返回ERROR_SUCCESS,否则返回错误代码
if( ERROR_SUCCESS != ret )
MessageBox(_T("打开 EditPlus 3.txt\\shell\\open\\command失败"));
ret = RegQueryValueEx(hkey,NULL,NULL,&dwtype,(LPBYTE)sz,&sl); //2:为NULL时读取第一个默认键的值
if( ERROR_FILE_NOT_FOUND == ret )
{
MessageBox(_T("HKEY_CLASS_ROOT\EditPlus 3.txt\shell\open\command 下没有默认键项!"));
}
RegCloseKey(hkey);
//处理字串 -- D:\apps\EditPlus\EDITPLUS.EXE "%1" ,使其编程标准的路径格式
for( int i = 0; i < sizeof(sz) ; i++ )
{
if( sz[i] == ' ' ) //根据此字串的特性编写的代码
{
sz[i] = 0 ; //将空格换成'\0'用于清除其后不需要的字符
goto lable;
}
}
lable:
CString str(sz);
m_reg = str; //m_reg是一个static text控件的绑定变量
UpdateData(FALSE); //更新static text控件的内容
}
//不知道为什么一个函数中先后读取两个注册表项信息时就会导致第二项读取信息有误
//因此才分离出一个函数单独读取“扩展名”子键的信息
CString CReg_WRDlg::FromExtGetRelateAppPath(LPCSTR extName)
{
HKEY hExkey;
char szExt[256];
DWORD dwtype=REG_SZ, sl=256;
::memset(szExt,0,sizeof(szExt));
//通过扩展名获取关联程序的注册表子键
LONG ret = RegOpenKeyEx(HKEY_CLASSES_ROOT,
extName,
NULL,
KEY_QUERY_VALUE,
&hExkey);
if( ERROR_SUCCESS != ret )
MessageBox(_T("打开 .txt子键失败"));
ret = RegQueryValueEx(hExkey,NULL,NULL,&dwtype,(LPBYTE)szExt,&sl); //2:为NULL时读取第一个默认键的值
if( ERROR_FILE_NOT_FOUND == ret )
MessageBox(_T("查找 .txt的默认子键值失败!"));
RegCloseKey(hExkey);
CString cstrEx(szExt);
return cstrEx;
}
c.运行效果:
完整工程下载地址:http://download.csdn.net/detail/qq2399431200/6819159
三、应用前景
1.配合::ExtractIconEx(参数类表略)函数就可以获取任意扩展名文件对应的默认Icon图标(请看我的获取.exe/.dll/.icon文件的Icon图标资源博文)
2.检测系统是否有对应扩展名文件的打开程序
3.管理Windows操作系统中外部应用程序的信息
编者注:谢绝转载,欢迎参考,尊重原创!