使用VC編寫ocx控件,通過讀註冊表項獲取客戶端軟件版本號

    有時候需要在 Web 頁面上檢測用戶計算機上是否安裝了某個軟件的特定版本,接下來就可以做以下處理:如果用戶安裝的軟件版本過低或未安裝該軟件,就提示用戶安裝該軟件的最新版本。本文提供一個實現示例,其實現的功能是:使用VC編寫一個 ocx 控件,該控件通過讀取註冊表,獲取計算機上安裝的 Apple 公司 iTunes 客戶端軟件的版本號。

    如果用戶計算機上安裝了 Apple 公司的 iTunes 客戶端軟件(本文中計算機上安裝的 iTunes 的版本號爲 12.5.3.17),那麼在註冊表中,可以看到有關於 iTunes 版本號的項存在,如下圖:



    本文使用的 IDE 是 Visual Studio 2010,先寫一個 Win32 控制檯應用程序,讀取一下 iTunes 在註冊表中的版本,該程序如下:

/************************************************** 
* File name: ReadReg.cpp 
* Author: HAN Wei 
* Author's blog: http://blog.csdn.net/henter/ 
* Date: Mar 5th, 2018 
* Description: demonstrate how to get iTunes client version
               by means of reading Windows registry
**************************************************/   

#include <Windows.h>
#include <comutil.h>
#include <iostream>
#include <tchar.h>

using namespace std;

#pragma comment(lib, "comsuppwd.lib")

BSTR GetClientVersion(void)
{
    const TCHAR SoftwareRegPath[] = { _TEXT("SOFTWARE\\Apple Computer, Inc.\\iTunes") };
    HKEY hKey;
    TCHAR SoftwareVersion[128];
    DWORD type = 0;
    DWORD DataLen = 1024;
    long ErrorCode;
    BSTR ClientVerBstr;

    memset(SoftwareVersion, 0, sizeof(SoftwareVersion));
    if ( (ErrorCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SoftwareRegPath, 0, KEY_READ, &hKey)) != ERROR_SUCCESS )
    {
      return SysAllocString(_TEXT("RegOpenKeyEx function failed."));
     }
    if ( RegQueryValueEx(hKey, _TEXT("Version"), 0, &type, (LPBYTE)(SoftwareVersion), &DataLen) != ERROR_SUCCESS )
    {
	  RegCloseKey(hKey);
      return SysAllocString(_TEXT("RegQueryValueEx function failed."));
     }
    if ( RegCloseKey(hKey) != ERROR_SUCCESS )
    {
      return SysAllocString(_TEXT("RegCloseKey function failed."));
     }

    ClientVerBstr = SysAllocString(SoftwareVersion);
    return ClientVerBstr;
}

int main(void)
{
	BSTR bstring;
	char *version_string;

	if ( bstring = GetClientVersion() )
	{
		version_string = _com_util::ConvertBSTRToString(bstring);
		cout<<"iTunes version: "<<version_string<<endl;
		delete[] version_string;
		SysFreeString(bstring);
		return 0;
	}
	else
	{
		cout<<"Get iTunes version from Windows registry failed!"<<endl;
		SysFreeString(bstring);
		return (-1);
	}
}

   函數 GetClientVersion( ) 的返回值類型爲 BSTR,是爲了方便以後將該函數移植到 ocx 控件程序中。運行後報告RegOpenKeyEx( ) 函數執行失敗,原因在於當前計算機上安裝的是 64 位的 Windows 7 操作系統,安裝的 iTunes 是一個 64 位的應用程序,當前在編譯命令行程序時,“解決方案”平臺被設置爲“Win32”,32 位應用程序在 64 位 的 Windows 操作系統上,讀取不到 64 位程序對應的註冊表項。要解決這個問題,只需要將 RegOpenKeyEx( ) 函數的第 4 個輸入參數由 KEY_READ 改爲 KEY_READ | KEY_WOW64_64KEY ,這樣就能讓 32 位應用程序讀取到 64 位程序在註冊表中的相關項了。在 32 位 Windows 操作系統上,將會自動忽略 KEY_WOW64_64KEY 參數。修改以後的程序如下:

/************************************************** 
* File name: ReadReg.cpp 
* Author: HAN Wei 
* Author's blog: http://blog.csdn.net/henter/ 
* Date: Mar 5th, 2018 
* Description: demonstrate how to get iTunes client version
               by means of reading Windows registry
**************************************************/   

#include <Windows.h>
#include <comutil.h>
#include <iostream>
#include <tchar.h>

using namespace std;

#pragma comment(lib, "comsuppwd.lib")

BSTR GetClientVersion(void)
{
   const TCHAR SoftwareRegPath[] = { _TEXT("SOFTWARE\\Apple Computer, Inc.\\iTunes") };
    HKEY hKey;
    TCHAR SoftwareVersion[128];
    DWORD type = 0;
    DWORD DataLen = 1024;
    long ErrorCode;
    BSTR ClientVerBstr;

    memset(SoftwareVersion, 0, sizeof(SoftwareVersion));
    if ( (ErrorCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SoftwareRegPath, 0, KEY_READ  | KEY_WOW64_64KEY, &hKey)) != ERROR_SUCCESS )
    {
      return SysAllocString(_TEXT("RegOpenKeyEx function failed."));
     }
    if ( RegQueryValueEx(hKey, _TEXT("Version"), 0, &type, (LPBYTE)(SoftwareVersion), &DataLen) != ERROR_SUCCESS )
    {
	  RegCloseKey(hKey);
      return SysAllocString(_TEXT("RegQueryValueEx function failed."));
     }
    if ( RegCloseKey(hKey) != ERROR_SUCCESS )
    {
      return SysAllocString(_TEXT("RegCloseKey function failed."));
     }

    ClientVerBstr = SysAllocString(SoftwareVersion);
    return ClientVerBstr;
}

int main(void)
{
	BSTR bstring;
	char *version_string;

	if ( bstring = GetClientVersion() )
	{
		version_string = _com_util::ConvertBSTRToString(bstring);
		cout<<"iTunes version: "<<version_string<<endl;
		delete[] version_string;
		SysFreeString(bstring);
		return 0;
	}
	else
	{
		cout<<"Get iTunes version from Windows registry failed!"<<endl;
		SysFreeString(bstring);
		return (-1);
	}
}

    注意在編譯設置中,“字符集”要設爲“使用Unicode字符集”。程序執行結果如下:



    接下來開始編寫 ocx 控件。以管理員身份運行 Visual Studio, 這樣做的好處是將來在編譯 ocx 控件時,Visual Studio 能自動註冊控件。在“新建項目”中選擇“MFC ActiveX控件”,假定將要創建的ocx控件名爲 ReadRegistry,一步一步操作如下:






    點擊“完成”按鈕,Visual Studio 自動創建了相關的文件。接下來添加一個方法,如下圖:


    假定方法名稱爲 GetClientVersion,添加方法的過程如下:


    點擊“下一步”按鈕,顯示如下:


    點擊“完成”按鈕。在 ReadRegistryCtrl.cpp 文件中,找到函數 BSTR CReadRegistryCtrl::GetClientVersion(void) ,如下圖:


    刪去圖中選定部分的代碼,將前面實現的 Win32 控制檯應用程序中 GetClientVersion( ) 函數的實現代碼粘貼過來,如下圖:



   爲 ocx 控件實現安全接口,具體過程請參考博文:http://blog.csdn.net/henter/article/details/79424020,這裏不再詳述。完成後重新生成 ReadRegistry.ocx 等文件,如果有條件的話,最好對 ReadRegistry.ocx 做數字簽名。在 ReadRegistry.idl 文件中找到以下字樣:
//  CReadRegistryCtrl 的類信息
[
uuid(8976F52E-4096-4C8D-B845-11350BA3E2AD)

]

    在不同計算機上產生的 uudi 值是不同的,將 uuid 後面括號中的值記錄下來,

    接下來編寫以下名爲 index.html 的網頁文件:

<!DOCTYPE HTML>
<html>
<BODY>
<OBJECT id="ReadRegistry" classid="clsid:8976F52E-4096-4C8D-B845-11350BA3E2AD" width="0" height="0">
</OBJECT>

<SCRIPT Language="JavaScript" type="text/JavaScript">
function ReadReg()
{
  var myOcx=document.getElementById("ReadRegistry");
  if (myOcx)
  {
  alert("ocx 控件存在。");
  var version = myOcx.GetClientVersion();
  alert("iTunes version: "+ version);
  }
  else
  {
  alert("ocx 控件不存在!");
  }
}
</SCRIPT>

<button type="button" onclick="JavaScript:ReadReg()">讀取註冊表中iTunes的版本號</button>
</BODY>
</html>

    注意在 html 文件中用到了剛纔記錄下來的 uuid 值。將文件  index.html  和 ReadRegistry.ocx 放到 Web 服務器上,這裏使用一個輕量級的 Web 服務器軟件 Abyss Web Server X1。將文件  index.html  和 ReadRegistry.ocx 拷貝到 Abyss Web Server X1 服務器軟件的  \Abyss Web Server\htdocs 目錄下,啓動 Abyss Web Server X1 服務器軟件,啓動 IE 瀏覽器,輸入網址:http://localhost/index.html ,頁面顯示如下:



    點擊“讀取註冊表中iTunes的版本號”按鈕,頁面依次顯示如下:



    可以看到成功地獲取到了 iTunes 軟件的版本號。爲了保證在用戶計算機上執行 ocx 控件時能夠找到必要的庫文件,建議在編譯控件程序時,在設置中將“MFC的使用”設爲“在靜態庫中使用 MFC”,如下圖:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章