成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

使用URI Scheme實(shí)現(xiàn)從web網(wǎng)頁(yè)上打開本地C++應(yīng)用程序

不知名網(wǎng)友 / 4795人閱讀

摘要:從網(wǎng)頁(yè)中啟動(dòng)本地應(yīng)用程序的規(guī)范中,需要將本地應(yīng)用程序的信息通過(guò)寫注冊(cè)表的方式注冊(cè)到系統(tǒng)中,然后在網(wǎng)頁(yè)中使用就可以只在啟動(dòng)本地程序了。如果使用不帶參數(shù)的,則無(wú)法啟動(dòng)目標(biāo)程序。

目錄

1、需求描述

2、選擇URI Scheme實(shí)現(xiàn)

3、何為URI Scheme?

4、將自定義的URL Scheme信息寫入注冊(cè)表的C++源碼實(shí)現(xiàn)

5、如何實(shí)現(xiàn)最開始的3種需求

6、后續(xù)需要考慮的細(xì)節(jié)問題


? ? ? ?最近接連收到一些關(guān)于從web頁(yè)面上啟動(dòng)我們C++軟件的需求,希望我們能提供一些技術(shù)上的支持與協(xié)助。于是我們大概地研究了相關(guān)的實(shí)現(xiàn)方法,下面把研究的過(guò)程與結(jié)果在此做一個(gè)分享,希望能給朋友們提供一個(gè)借鑒或參考。

1、需求描述

? ? ? ?最近很多第三方開發(fā)廠商為了快速集成我們的系統(tǒng)及軟件(作為子系統(tǒng)融入到他們的大型web業(yè)務(wù)系統(tǒng)中),不想基于SDK做費(fèi)時(shí)費(fèi)力的二次開發(fā),提出直接從web網(wǎng)頁(yè)啟動(dòng)我們軟件的需求。簡(jiǎn)單地歸納了一下,類似的需求可以分以下幾類:

1)僅僅是從web網(wǎng)頁(yè)上將C++軟件啟動(dòng)起來(lái),即將軟件調(diào)起來(lái)就行了,沒有后續(xù)操作;

2)從web網(wǎng)頁(yè)上將C++軟件啟動(dòng)起來(lái),并且啟動(dòng)時(shí)傳遞服務(wù)器地址和賬戶信息,讓軟件自動(dòng)發(fā)起登陸;

3)從web網(wǎng)頁(yè)上將C++軟件啟動(dòng)起來(lái),并且啟動(dòng)時(shí)傳遞一些信息,讓軟件執(zhí)行指定的一些操作。

? ? ? ?其實(shí)上述需求可以簡(jiǎn)單的歸結(jié)為,將C++軟件啟動(dòng)起來(lái),并給C++軟件傳遞一些命令行參數(shù),C++軟件解析出參數(shù),執(zhí)行指定的操作。

2、選擇URI Scheme實(shí)現(xiàn)

? ? ? ?如果是C++程序要啟動(dòng)C++軟件,會(huì)比較簡(jiǎn)單,只要讀一下安裝程序時(shí)寫入的程序安裝路徑,就能直接通過(guò)軟件的全路徑,直接就可以將C++軟件啟動(dòng)起來(lái)。

? ? ? ?現(xiàn)在越來(lái)越多的系統(tǒng)都轉(zhuǎn)向了B/S架構(gòu),用戶可以隨處隨地訪問到系統(tǒng)里面去,只要有網(wǎng)絡(luò)有電腦就行了,不用再安裝各種客戶端軟件了。但就像我們上面提到的一些客戶一樣,因?yàn)槟承I(yè)務(wù)的需要,需要從web網(wǎng)頁(yè)上啟動(dòng)基于C/S架構(gòu)的客戶端軟件。

? ? ? ?web網(wǎng)頁(yè)一般都是在瀏覽器中的打開的,出于安全的原因,web瀏覽器既不能直接讀寫注冊(cè)表,也不能直接啟動(dòng)二進(jìn)制文件,所以在web網(wǎng)頁(yè)中想啟動(dòng)本地的應(yīng)用程序似乎遇到了問題。其實(shí)這并不是問題,我們使用URI Scheme技術(shù)就能輕松地實(shí)現(xiàn)這樣的需求。

3、何為URI Scheme?

? ? ? ?URI,全稱是Uniform Resource Identifier,統(tǒng)一資源標(biāo)志符。在web開發(fā)領(lǐng)域,其表示的是web上每一種可用的資源,如HTML文檔、圖片、視頻等。URI Scheme,我們稱之為URI方案,是一種技術(shù)規(guī)范,其中的URI是個(gè)更寬泛的概念,它可以是一個(gè)本地的文件,也可以是一個(gè)網(wǎng)絡(luò)上的視頻。

? ? ? ?從web網(wǎng)頁(yè)中啟動(dòng)本地應(yīng)用程序的URI Scheme規(guī)范中,需要將本地應(yīng)用程序的信息通過(guò)寫注冊(cè)表的方式注冊(cè)到系統(tǒng)中,然后在網(wǎng)頁(yè)中使用“SchemeName://”就可以只在啟動(dòng)本地程序了。具體的做法是,在注冊(cè)表的HKEY_CLASSES_ROOT下創(chuàng)建一個(gè)自定義的SchemeName注冊(cè)表節(jié)點(diǎn),然后再在該節(jié)點(diǎn)下創(chuàng)建多個(gè)節(jié)點(diǎn),并在給相關(guān)節(jié)點(diǎn)設(shè)置注冊(cè)表鍵值。

? ? ? ?以QQ內(nèi)嵌的QQGame為例,添加注冊(cè)表信息的步驟如下:

1)在HKEY_CLASSES_ROOT下創(chuàng)建QQGameProtocol節(jié)點(diǎn)

? ? ? QQGameProtocol就是對(duì)應(yīng)的Scheme方案名稱,也是web頁(yè)面上啟動(dòng)對(duì)應(yīng)程序的URL的前綴名稱,即QQGameProtocol://。然后給該節(jié)點(diǎn)添加一個(gè)URL Protocol名稱的鍵值,將其Value設(shè)置為本地應(yīng)用程序的完整路徑。對(duì)于當(dāng)前的QQGameProtocol,就是C:/Users/Public/Documents/Tencent/QQGameMicro/QQGwp.exe,如上圖所示。

2)在QQGameProtocol根節(jié)點(diǎn)下創(chuàng)建DefaultIcon節(jié)點(diǎn)

? ? ? ?給DefaultIcon節(jié)點(diǎn)設(shè)置默認(rèn)的字符串鍵值(REG_SZ類型),其Value的格式為“應(yīng)用程
序全路徑,圖標(biāo)索引”的形式,該鍵值是用來(lái)指定該URI方案使用的圖標(biāo)。本例中的Value
為:C:/Users/Public/Documents/Tencent/QQGameMicro/QQGwp.exe,1,如上圖所示。

3)在QQGameProtocol下創(chuàng)建shell節(jié)點(diǎn)

? ? ? ?先在QQGameProtocol下創(chuàng)建shell節(jié)點(diǎn),然后在shell節(jié)點(diǎn)下創(chuàng)建open節(jié)點(diǎn),然后在open節(jié)點(diǎn)創(chuàng)建command節(jié)點(diǎn)。shell節(jié)點(diǎn)和open節(jié)點(diǎn)不需要設(shè)置鍵值,command節(jié)點(diǎn)需要設(shè)置鍵值,其鍵值用來(lái)指定啟動(dòng)目標(biāo)應(yīng)用程序時(shí)是否給目標(biāo)程序傳遞命令行參數(shù)。

? ? ? ?一般只需要設(shè)置傳遞一個(gè)參數(shù)即可,比如當(dāng)前Scheme下的"C:/Users/Public/Documents/Tencent/QQGameMicro/QQGwp.exe" "%1"。如果要傳遞多個(gè)參數(shù),可以自定義一個(gè)組合格式,命令行只用一個(gè)參數(shù)即可。比如我們要給目標(biāo)程序傳遞服務(wù)器地址、用戶名和密碼,可以采用這樣的組合格式:

#serveraddr=192.168.72.135#username=admin1#password=123456

即將要傳遞的多個(gè)參數(shù)按指定的格式組合起來(lái)生成一個(gè)命令行字符串參數(shù)即可。

? ? ? ?當(dāng)在web頁(yè)面上點(diǎn)擊“SchemeName://”鏈接時(shí),就會(huì)到系統(tǒng)注冊(cè)表的HKEY_CLASSES_ROOT節(jié)點(diǎn)下查找SchemeName節(jié)點(diǎn)項(xiàng),找到后取出目標(biāo)應(yīng)用程序的全路徑,并查找傳遞的命令行參數(shù)個(gè)數(shù),這樣就能把本地的目標(biāo)應(yīng)用程序啟動(dòng)起來(lái)了。

? ? ? ?如果要給目標(biāo)程序傳遞參數(shù),則使用“SchemeName://參數(shù)”的形式。經(jīng)測(cè)試發(fā)現(xiàn),如果在command節(jié)點(diǎn)中設(shè)置了%1傳遞參數(shù)的標(biāo)識(shí),則web網(wǎng)頁(yè)中設(shè)置的URL必須要帶參數(shù),即“SchemeName://參數(shù)”。如果使用不帶參數(shù)的URL:“SchemeName://”,則無(wú)法啟動(dòng)目標(biāo)程序。

? ? ? ?那如何既要支持不傳參數(shù)啟動(dòng),也要支持傳參數(shù)啟動(dòng)呢?難道要在注冊(cè)表中創(chuàng)建兩個(gè)不同的SchemeName節(jié)點(diǎn)?其實(shí)不用這么麻煩,使用一個(gè)帶參數(shù)的SchemeName節(jié)點(diǎn)就夠了,對(duì)于直接啟動(dòng)目標(biāo)程序不帶啟動(dòng)參數(shù)的,也可以攜帶一個(gè)標(biāo)識(shí)參數(shù),在程序中約定不傳參數(shù)的標(biāo)識(shí)符,比如noparam,當(dāng)程序中解析出noparam,則表示是不帶參數(shù)啟動(dòng)的,直接啟動(dòng)程序即可,不用做后續(xù)的操作。

4、將自定義的URL Scheme信息寫入注冊(cè)表的C++源碼實(shí)現(xiàn)

? ? ? ?下面給出將自定義的URL Scheme信息寫入注冊(cè)表的C++源碼實(shí)現(xiàn):

BOOL WriteURISchemaReg(){	// exe程序的完整路徑	CString strExePath = m_strInstallPath + _T("xyzlink.exe");	// URI Scheme名稱	CString strProtocolName = _T("XyzlinkProtocol");	HKEY hRootKey = NULL;	DWORD dwKeyValue = 0;	DWORD dwDisposition = 0;	UCHAR szBuf[MAX_PATH] = { 0 };	// 1、在HKEY_CLASSES_ROOT下創(chuàng)建URI Schema相關(guān)注冊(cè)表的根節(jié)點(diǎn)RootNode	long lRet = ::RegCreateKeyEx(HKEY_CLASSES_ROOT, ProtocalNodeName, 0, NULL, 0,		KEY_ALL_ACCESS, NULL, &hRootKey, &dwDisposition);	if (lRet != ERROR_SUCCESS)	{		return FALSE;	}	// 給根節(jié)點(diǎn)RootNode設(shè)置值1	lRet = ::RegSetValueEx(hRootKey, NULL, 0, REG_SZ, (LPBYTE)(LPCTSTR)strProtocolName,		strProtocolName.GetLength() * sizeof(TCHAR));	if (lRet != ERROR_SUCCESS)	{		RegCloseKey(hRootKey);		return FALSE;	}	// 給根節(jié)點(diǎn)RootNode設(shè)置值2	CString strKey = _T("URL Protocol");	lRet = RegSetValueEx(hRootKey, strKey.GetBuffer(0), 0, REG_SZ, (LPBYTE)(LPCTSTR)strExePath,		strExePath.GetLength() * sizeof(TCHAR));	if (lRet != ERROR_SUCCESS)	{		RegCloseKey(hRootKey);		return FALSE;	}	// 2、在根節(jié)點(diǎn)RootNode下創(chuàng)建DefaultIcon節(jié)點(diǎn)	strKey = _T("DefaultIcon");	HKEY hDefaultIconKey = NULL;	lRet = RegCreateKeyEx(hRootKey, strKey, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hDefaultIconKey, &dwDisposition);	if (lRet != ERROR_SUCCESS)	{		RegCloseKey(hRootKey);		return FALSE;	}	// 給RootNode/DefaultIcon節(jié)點(diǎn)設(shè)置值	CString strExePathPlus = strExePath + _T(",1");	lRet = RegSetValueEx(hDefaultIconKey, NULL, 0, REG_SZ, (LPBYTE)(LPCTSTR)strExePathPlus,		strExePathPlus.GetLength() * sizeof(TCHAR));	if (lRet != ERROR_SUCCESS)	{		RegCloseKey(hDefaultIconKey);		RegCloseKey(hRootKey);		return FALSE;	}	// 3、在RootNode/DefaultIcon節(jié)點(diǎn)下創(chuàng)建子節(jié)點(diǎn)shell	strKey = _T("shell");	HKEY hShellKey = NULL;	lRet = RegCreateKeyEx(hDefaultIconKey, strKey, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hShellKey, &dwDisposition);	if (lRet != ERROR_SUCCESS)	{		RegCloseKey(hDefaultIconKey);		RegCloseKey(hRootKey);		return FALSE;	}	// 4、在RootNode/DefaultIcon/shell節(jié)點(diǎn)下創(chuàng)建子節(jié)點(diǎn)open	strKey = _T("open");	HKEY hOpenKey = NULL;	lRet = RegCreateKeyEx(hShellKey, strKey, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hOpenKey, &dwDisposition);	if (lRet != ERROR_SUCCESS)	{		RegCloseKey(hDefaultIconKey);		RegCloseKey(hRootKey);		return FALSE;	}	// 5、在RootNode/DefaultIcon/shell/open節(jié)點(diǎn)下創(chuàng)建子節(jié)點(diǎn)command	strKey = _T("command");	HKEY hCommandKey = NULL;	lRet = RegCreateKeyEx(hOpenKey, strKey, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hCommandKey, &dwDisposition);	if (lRet != ERROR_SUCCESS)	{		RegCloseKey(hOpenKey);		RegCloseKey(hDefaultIconKey);		RegCloseKey(hRootKey);		return FALSE;	}	// 給command節(jié)點(diǎn)設(shè)置值(命令行參數(shù))	CString strCmdParam;	strCmdParam.Format(_T("/"%s/" /"%%1/""), strExePath);	lRet = RegSetValueEx(hCommandKey, NULL, 0, REG_SZ, (LPBYTE)(LPCTSTR)strCmdParam,		strCmdParam.GetLength() * sizeof(TCHAR));	if (lRet != ERROR_SUCCESS)	{		RegCloseKey(hCommandKey);		RegCloseKey(hOpenKey);		RegCloseKey(hDefaultIconKey);		RegCloseKey(hRootKey);		return FALSE;	}	RegCloseKey(hCommandKey);	RegCloseKey(hOpenKey);	RegCloseKey(hDefaultIconKey);	RegCloseKey(hRootKey);	return TRUE;}

5、如何實(shí)現(xiàn)最開始的3種需求

? ? ? ?搞清楚了使用URI Scheme規(guī)范實(shí)現(xiàn)從web頁(yè)面中啟動(dòng)本地應(yīng)用程序的方法,下面我們?cè)倩氐阶铋_始提出的3個(gè)需求,看看如何去實(shí)現(xiàn)。

? ? ? ?第一種需求不需要傳遞參數(shù),后面兩種需求則需要傳遞參數(shù),我們使用一個(gè)帶參數(shù)傳遞的Scheme節(jié)點(diǎn)即可。我們可以定義一個(gè)啟動(dòng)type類型標(biāo)識(shí)launchtype,對(duì)于直接啟動(dòng)的,type為noparam。對(duì)于啟動(dòng)后發(fā)起自動(dòng)登錄的,type為autologin;對(duì)于啟動(dòng)后需要執(zhí)行具體操作的,可以根據(jù)具體的業(yè)務(wù),定義具體的type類型,這樣更靈活。

? ? ? ?對(duì)于目標(biāo)應(yīng)用程序,則可以根據(jù)不同的type類型,解析對(duì)應(yīng)的參數(shù)數(shù)據(jù),并對(duì)參數(shù)的合法性進(jìn)行校驗(yàn)。

? ? ? ?下面把web網(wǎng)頁(yè)的測(cè)試代碼給出來(lái),保存成.html文件,用瀏覽器打開即可:

        Start exe demo打開目標(biāo)程序 

6、后續(xù)需要考慮的細(xì)節(jié)問題

? ? ? ?上面大概說(shuō)了一下問題的解決辦法和思路,其實(shí)還有很多細(xì)節(jié)需要去考慮。比如下面的幾種場(chǎng)景:

1)程序可能沒有安裝

? ? ? ?如果目標(biāo)應(yīng)用程序沒有安裝,肯定是啟動(dòng)不起來(lái)的,是不是要檢測(cè)啟動(dòng)失敗的原因,然后自動(dòng)跳轉(zhuǎn)到安裝程序的下載頁(yè)面。

2)僅將目標(biāo)程序啟動(dòng)起來(lái),但目標(biāo)程序已經(jīng)運(yùn)行

? ? ? ?一般情況下,很多程序都是單實(shí)例運(yùn)行的,即只允許運(yùn)行一個(gè)實(shí)例。假定目標(biāo)程序是單實(shí)例運(yùn)行的,點(diǎn)擊web頁(yè)面中的啟動(dòng)程序的鏈接時(shí),已經(jīng)有個(gè)進(jìn)程在運(yùn)行了,目標(biāo)程序中要彈出程序已經(jīng)運(yùn)行的提示,并將已經(jīng)啟動(dòng)的程序拉到前端顯示。

3)啟動(dòng)程序后需要有后續(xù)操作,但目標(biāo)程序已經(jīng)運(yùn)行

? ? ? ?啟動(dòng)程序后需要有后續(xù)操作,比如自動(dòng)發(fā)起登錄,但此時(shí)目標(biāo)應(yīng)用程序已經(jīng)運(yùn)行。如果已啟動(dòng)的進(jìn)程還沒登錄,是要自動(dòng)發(fā)起登錄?還是擱置不管?如果已啟動(dòng)的進(jìn)程已經(jīng)登錄,則提示已經(jīng)啟動(dòng),并將已啟動(dòng)的主窗口拉到最前顯示。如果目標(biāo)程序已經(jīng)啟動(dòng)且已經(jīng)登錄成功,則需要將命令行參數(shù)發(fā)給已啟動(dòng)的進(jìn)程,讓該進(jìn)程執(zhí)行要執(zhí)行的操作,比如加入會(huì)議。

PS:微軟官方說(shuō)明連接:

Registering an Application to a URI Schemehttps://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa767914(v=vs.85)?redirectedfrom=MSDNhttps://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa767914(v=vs.85)?redirectedfrom=MSDN

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/125389.html

相關(guān)文章

  • 徹底理解輸入U(xiǎn)RL與頁(yè)面展現(xiàn)

    摘要:五瀏覽器繪制網(wǎng)頁(yè)繪制過(guò)程主要是結(jié)構(gòu)與樣式的結(jié)合,以及行為動(dòng)態(tài)效果的展現(xiàn)。之后會(huì)寫系列文章,歡迎圍觀主要參考文章基礎(chǔ)進(jìn)階詳解與編碼前端面試題從到頁(yè)面展現(xiàn),這之中發(fā)生了什么圖解 流程概述: 地址欄輸入U(xiǎn)RL ——> 域名解析 ——> 服務(wù)器處理請(qǐng)求 ——> 瀏覽器處理響應(yīng) ——> 瀏覽器繪制網(wǎng)頁(yè) 一.地址欄輸入U(xiǎn)RL 認(rèn)識(shí)URL showImg(https://segmentfault....

    abson 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<