前言:
我在編碼的時候,遇到了一個需求,是在程序中接收到一個文件名,要求我創建進程並根據目標文件的後綴啓動對應的打開程序打開目標文件。其中涉及到的詳細原理在http://blog.csdn.net/arvon2012/article/details/7818909有描述,對剛接觸註冊表編程的朋友請看入門文章http://blog.csdn.net/arvon2012/article/details/7839659.
本文對應的完整版代碼在http://download.csdn.net/detail/arvon2012/4482614
基本原理:
理論上的原理很簡單,就是在註冊表中查詢和後綴一致的鍵,通過一步一步的查詢,找到打開對應後綴文件的命令,然後在創建進程的時候,把查詢到並整理好的命令傳入創建進程的函數中。文件就會像被雙擊後一樣用默認打開方式打開。
實現步驟詳解:
1.打開註冊表中和後綴一致的鍵,並讀取該鍵默認值(這個值是另一個鍵的名稱)
//從文件名中得到後綴
subfix = wcsrchr(pathname, '.');//subfix負責存放後綴
//打開後綴對應的註冊表項
RegOpenKeyExW(HKEY_CLASSES_ROOT,subfix,0,KEY_ALL_ACCESS,&hKey);
//獲取上面打開項的默認(default)值
RegQueryValueExW(hKey,NULL,0,(LPDWORD)val,(BYTE *)result,dwSize);
RegCloseKey(hKey);
倒數第二行的result中存放了我們查到的值
2.用上面查到的值打開對應的鍵及其子鍵
下面要打開存放了打開這類文件命令的鍵,位置在result\shell\open\command,打開後獲取該鍵的默認值,就是一個打開命令
//根據result值打開存放打開命令的項:.xxx\shell\open\command
wcscat(result,L"\\shell\\open\\command");
if(ERROR_SUCCESS != RegOpenKeyExW(HKEY_CLASSES_ROOT,result,0,KEY_ALL_ACCESS,&hKey))
{
printf("Open target failed!\n");
}
//獲取命令
RegQueryValueExW(hKey,NULL,0,(LPDWORD)val,(BYTE *)result,dwSize1);
命令存放在最後一行的result中。
3.整理組裝可用的命令
獲得的命令不是直接可以用的格式,我們要提取需要的部分,然後組裝上目標文件路徑
一般獲得的命令有兩種形式,一種是%SystemRoot%開頭的,這種如下處理:
if(szCommandLine[0]=='%')
{
strcpy(TszCommandLine,"C:\\windows\\");
i = 13;
while(szCommandLine[i]!=' ')
{
TszCommandLine[i-2] = szCommandLine[i];
i++;
}
TszCommandLine[i-2] = '\0';
}
另一種格式是類似“C:\filename” “”這樣的。這類命令如下處理:
//否則:
else
{
i = 1;
while(szCommandLine[i]!='"')
{
TszCommandLine[i-1] = szCommandLine[i];
i++;
}
TszCommandLine[i-1] = '\0';
}
命令的前半部分整理好後,把目標文件的路徑拼接到後半部分上:
//將要打開的文件名組裝到命令中
strcat(TszCommandLine," ");
char *tmp_pathname = new char[260];
i = 0;
//用Char型變量存放原來寬字節形式的路徑名
while(pathname[i])
{
tmp_pathname[i] = pathname[i];
i++;
}
tmp_pathname[i] = '\0';
strcat(TszCommandLine,tmp_pathname);//正式組裝
3.創建進程打開文件
創建進程,把前面整理好的命令,作爲參數傳入createProcess中。文件打開成功
//創建進程,運行命令
BOOL bRet = CreateProcessA(
NULL, //不在此指定可執行文件的文件名
TszCommandLine, //命令行參數
NULL, //默認進程安全性
NULL, //默認線程安全性
FALSE, //當前進程內的句柄不可以被子進程繼承
CREATE_NEW_CONSOLE, //爲新進程創建一個新的控制檯窗口
NULL, //使用本進程的環境變量
NULL, //使用本進程的驅動器和目錄
&si, //父進程傳給子進程的一些信息
&pi); //保存新進程信息的結構