使用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”,如下图:


猜你喜欢

转载自blog.csdn.net/henter/article/details/79472568
今日推荐