• [VC++]注册表简单操作


    用Visual C++实现注册表简单操作2005-07-25 10:09 作者: 刘涛


      Windows的注册表中包含了Windows的系统配置、PC机的硬件配置、Win32应用程序和用户的其他设置信息。注册表和INI文件不同,它是多层次的树状数据结构,具有六个分支(根键),每个分支又由许多的键和键值组成,而每个键则代表一个特定的配置项目。在注册表中键可以包括子键和值。我们可以对他做个比喻,键就是目录,而子键和值可以看成文件,这样比喻可能不科学但是很实际。在Windows
    98下注册表包括在两个文件内,他们是user.dat和system.dat两个文件。System.dat包括标准的系统信息,他们被保存在HKEY_LOCAL_MACHINE的根键内。User.dat文件包括用户指定的信息,如用户策略,桌面设定等等。

      为了平时查看方便,Windows为我们准备了一个小程序regedit.exe。执行他就可以看到注册表的树状结构。在实际编程工作中,我们经常会遇到如何在Visual
    C++中对Windows注册表整个树状结构信息进行访问和修改的问题,如查询和修改注册表中用户姓名和公司名称的有关信息等。为此,本实例将相关的注册表操作封装到函数中,并通过一个简单的例程给出了上述函数的调用方法,该例程可以在注册表中创建、删除、显示一个键值,同时还可以清空最近阅读过的文档历史记录。程序的界面效果如图一所示:


    图一、操作注册表示例程序界面效果图

      一、实现方法

      对注册表的编程要用到句柄,我们需要通过一个句柄访问注册表键值,当打开或创建一个键值的时候,会返回一个该键的句柄,并且调用和分析键和创建键值,在分析和创建的同时需要传递句柄到函数。WINDOWS提供预定义的用语---根一级键的保留句柄,如HKEY_CLASS_ROOT,HKEY_CURRENT_USER,HKEY_LOCAL_MACHINE,HKEY_USER等,这些都是与注册表的根键相对应并且同名的句柄。当访问一个根键的时候,传递这些通用句柄。这就不用打开根键啦,因为他们总是在打开状态下,可使用默认键的句柄访问。

      Win32
    API提供了大约25个有关注册表的函数,他提供了对注册表的读取,写入,删除,以及打开注册表的所有函数,并且可以实现对注册表备份,连接和对远端注册表进行查看等功能。但是在编程的时候首先需要考虑你是在什么操作系统编辑此类程序,虽然微软的操作系统,如NT和Windows98都是32位操作系统,但是有些API函数中并不支持98,这点是要注意的。API经历和发展了很多年,有些函数已经重复,比如RegSetValue()及RegSetValueEx()都是用来设置注册表键值的,两者的区别在于前者是设置注册表键的默认值,仅支持作为数据类型的字符串,而后者不仅继承了前者的所有功能而且还能对多值或类型进行操作。一般API对比较新的函数都会在后缀追加"Ex"的同样名称函数,建议在编程中均应尽可能的使用高级函数。下面介绍一些比较常用的操作注册表的API函数:

      1、RegCloseKey()

      原型:RegCloseKey(HKEY hKey)

      解释:关闭指定的主册表键,释放句柄。当对一个或多个键或值操作完成以后,需要关闭其键来进行保存操作结果,关闭一个键后,句柄变为非法,此时应释放句柄。

      2、RegCreateKeyEx()

      原型:LONG RegCreateKeyEx( HKEY hKey, LPCTSTR lpSubKey, DWORD
    Reserved,
    LPTSTR lpClass, DWORD dwOptions, REGSAM samDesired,
    LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    PHKEY phkResult, LPDWORD
    lpdwDisposition );

      解释:打开指定的键或子键。如果要打开的键不存在的话,本函数会试图建立它。提供该函数是为了向后兼容。所有的WIN32应用程序应使用函数RegCreateKeyEx()。各参数及返回值的含义如下:

      各参数及返回值的含义如下:

      ·hKey为主键值,可以取下面的一些数值:HKEY_CLASSES_ROOT、HKEY_CURRENT_CONFIG、  HKEY_CURRENT_USER、HKEY_LOCAL_MACHINE、HKEY_USER、HKEY_PERFORMANCE_DATA(WINNT操作系统)、HKEY_DYN_DATA(WIN9X操作系统);

      ·参数lpSubKey为一个指向以零结尾的字符串的指针,其中包含将要创建或打开的子键的名称。子键不可以用反斜线(\)开始。该参数可以为NULL;

      ·参数Reserved为保留值,必须设置为0;

      ·参数lpClass为一个指向包含键类型的字符串。如果该键已经存在,则忽略该参数;

      ·参数dwOptions为新创建的键设置一定的属性。可以取下面的一些数值:  REG_OPTION_NON_VOLATILE
    ,表示新创建的键为一个非短暂性的键(数据信息保存在文件中,当系统重新启动时,数据信息恢复);REG_OPTION_VOLATILE,表示新创建的键为一个短暂性的键(数据信息保存在内存中),Windows95忽略该数值;REG_OPTION_BACKUP_RESTORE
    仅在WINNT中支持,可以提供优先级支持;

      ·参数samDesired用来设置对键访问的权限,可以取下面的一些数值:KEY_CREATE_LINK,表示准许生成符号键;KEY_CREATE_SUB_KEY
    表示准许生成子键;KEY_ENUMERATE_SUB_KEYS 表示准许生成枚举子键;KEY_EXECUTE
    表示准许进行读操作;KEY_NOTIFY表示准许更换通告;   KEY_QUERY_VALUE 表示准许查询子键;KEY_ALL_ACCESS
    提供完全访问,是上面数值的组合;

      KEY_READ
    是下面数值的组合:KEY_QUERY_VALUE、KEY_ENUMERATE_SUB_KEYS、KEY_NOTIFY;  KEY_SET_VALUE
    表示准许设置子键的数值;KEY_WRITE 是下面数值的组合:KEY_SET_VALUE、KEY_CREATE_SUB_KEY;

      ·参数lpSecurityAttributes为一个指向SECURITY_ATTRIBUTES结构的指针,确定返回的句柄是否被子处理过程继承。如果该参数为NULL,则句柄不可以被继承。在WINNT中,该参数可以为新创建的键增加安全的描述;

      ·参数phkResult为一个指向新创建或打开的键的句柄的指针;

      ·参数lpdwDispition指明键是被创建还是被打开的,可以是下面的一些数值:  REG_CREATE_NEW_KEY
    表示键先前不存在,现在被创建;REG_OPENED_EXISTING_KEY 表示键先前已存在,现在被打开。

      如果该函数调用成功,则返回ERROR_SUCCESS。否则,返回值为文件WINERROR.h中定义的一个非零的错误代码,可以通过设置FORMAT_MESSAGE_FROM_SYSTEM标识调用FormatMessage()函数来获取一个对错误的总体描述。

      3、RegOpenKeyEx()

      原型:LONG RegOpenKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD
    ulOptions,
    REGSAM samDesired, PHKEY phkResult );

      解释:打开一个指定的键,并返回打开键的句柄。

      各参数及返回值的含义如下:

      ·参数hKey的含义同RegCreateKeyEx函数中的hKey参数;

      ·参数lpSubKey为一个指向以零结尾的字符串的指针,其中包含子键的名称,可以利用反斜线(\)分隔不同的子键名。如果字符串为空,则根据hKey参数创建一个新的句柄。在这种情况下,并不关闭先前打开的句柄;

      ·参数ulOption保留,通常必须设置为0;

      ·参数samDesired的含义同RegCreateKeyEx函数中的samDesired参数;

      ·参数phkResult为一个指针,用来指向打开的键的句柄。可以通过RegCloseKey函数关闭这个句柄;

      ·函数的返回值同RegCreateKeyEx函数的返回值。

      4、 查询某一个键值:RegQueryValueEx()

      原型:LONG RegQueryValueEx(HKEY hKey, LPCTSTR lpValueName, LPDWORD
    pReserved, LPDWORD lpType,
    LPBYTE lpData, LPDWORD lpcbData );

      解释:根据要查询的键的句柄,要返回的查询的数据。

      各个参数及返回值的含义如下:

      ·参数hKey为当前的一个打开的键的句柄,具体数值同RegCreateKeyEx函数的hKey参数;

      ·参数lpVauleName为一个指向非空的包含查询值的名称的字符串指针;

      ·参数lpReserved保留,必须为NULL;

      ·参数lpType为一个指向数据类型的指针,数据类型为下列类型之一:REG_BINARY 二进制数据、REG_DWORD
    32位整数、REG_DWORD_LITTLE_ENDIAN little-endian格式的数据,例如0X12345678以(0X78 0X56 0X34
    0X12)方式保存、REG_DWORD_BIG_ENDIAN big-endian格式的数据,例如0X12345678以(0X12 0X34 0X56
    0X78)方式保存、REG_EXPAND_SZ 一个包含未扩展环境变量的字符串、REG_LINK 一个Unicode类型的链接、REG_MULIT_SZ
    以两个零结尾的字符串、REG_NONE 无类型数值、REG_RESOURCE_LIST 设备驱动资源列表、REG_SZ
    一个以零结尾的字符串根据函数使用的字符集类型的不同而设置为Unicode或ANSI类型的字符串;

      ·参数lpData为一个指向保存返回值的变量的指针。如果不需要返回值,该参数可以为NULL;

      ·参数lpcbData为一个指向保存返回值长度的变量的指针。其中长度以字节为单位。如果数据类型为REG_SZ、REG_MULTI_SZ或REG_EXPAND_SZ,那么长度也包括结尾的零字符,只有在参数lpData为NULL时,参数lpcbData才可以为NULL;返回值同RegCreateKeyEx函数的返回值;

      5、RegSetValueEx()

      原型:LONG RegSetValueEx(HKEY hKey, LPCTSTR lpValueName, LPDWORD lpReserved,
    DWORD dwType,
    const BYTE *lpData, DWORD cbData);

      解释:设置注册表中的一个键值。

      各个参数及返回值的含义如下:

      ·参数hKey的含义同RegCreateKeyEx函数中的hKey参数;

      ·参数lpValueName为一个指向包含值名的字符串指针;Reserved保留,通常必须设置为0;

      ·参数dwType确定了设置的值的类型同RegQueryValueKeyEx的lyType参数;

      ·参数lpData为一个指向包含数据的缓冲区的指针;

      ·参数cbData以字节为单位,指定数据的长度;

      返回值同RegCreateKeyEx函数的返回值。

      6、RegDeketeKey()

      原型:LONG RegDeleteKey(HKEY hKey,LPCTSTR lpSubKEY);

      解释:函数RegDeketeKey删除一个键及所有的子键。

      各个参数及返回值的含义如下:

      ·参数hKey的含义同RegCreateKeyEx函数中的hKey参数;

      ·参数lpSubKey的含义同RegCreateKeyEx函数中的lpSubKey参数。  

      二、编程步骤

      1、启动Visual C++6.0,生成一个基于对话框的应用程序RegDemo,按照上文中的图一所示设计程序界面;

      2、使用Class Wizard为对话框中的按钮添加鼠标单击响应处理函数;

      3、添加代码,编译运行程序。
    三、程序代码

    /////////////////////////////////////
    #include "stdafx.h"
    #include
    "RegDemo.h"
    #include "RegDemoDlg.h"
    #ifdef _DEBUG
    #define new
    DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] =
    __FILE__;
    #endif
    //注册表操作时用的变量;
    HKEY hKey;
    char content[256];
    //所查询注册表键值的内容
    DWORD dwType=REG_SZ; //定义读取数据类型
    DWORD dwLength=256;
    HKEY
    RootKey; //注册表主键名称
    TCHAR *SubKey; //欲打开注册表项的地址
    TCHAR *KeyName;
    //欲设置项的名字
    TCHAR *ValueName; //欲设置值的名称
    LPBYTE SetContent_S; //字符串类型
    int
    SetContent_D[256]; //DWORD类型
    BYTE SetContent_B[256];
    //二进制类型
    ///////////设置注册表操作函数;
    int ShowContent ( HKEY ReRootKey,TCHAR
    *ReSubKey,TCHAR *ReValueName);
    int SetValue_S ( HKEY ReRootKey,TCHAR
    *ReSubKey,TCHAR *ReValueName,
    LPBYTE ReSetContent_S);
    int SetValue_D (
    HKEY ReRootKey,TCHAR *ReSubKey,TCHAR
    *ReValueName,int
    ReSetContent_D[256]);
    int SetValue_B ( HKEY
    ReRootKey,TCHAR *ReSubKey,TCHAR *ReValueName,
    BYTE
    ReSetContent_B[256]);
    int DeleteKey ( HKEY ReRootKey,TCHAR *ReSubKey,TCHAR
    *ReKeyName);
    int DeleteValue ( HKEY ReRootKey,TCHAR *ReSubKey,TCHAR
    *ReValueName);
    ///////////////////////////////////////////////
    ShowContent
    ( HKEY ReRootKey,TCHAR *ReSubKey,TCHAR *ReValueName)
    {//查看键值的函数;
     int i=0;
    //操作结果:0==succeed
     if(RegOpenKeyEx(ReRootKey,ReSubKey,0,KEY_READ,&hKey)==ERROR_SUCCESS)
     {
      if(RegQueryValueEx(hKey,ReValueName,NULL,&dwType,(unsigned
    char
    *)
    content,&dwLength)!=ERROR_SUCCESS)
      {
       AfxMessageBox("错误:无法查询有关的注册表信息");
       i=1;
      }
      RegCloseKey(hKey);
     }
     else
     {
      AfxMessageBox("错误:无法打开有关的hKEY");
      i=1;
     }
     return
    i;
    }
    SetValue_S ( HKEY ReRootKey,TCHAR *ReSubKey,TCHAR
    *ReValueName,LPBYTE
    ReSetContent_S)
    {
     //设置字符串值函数
     int i=0;
    //操作结果:0==succeed
     //int
    StrLength;
     //StrLength=CString(SetContent_S).GetLength();
     if(RegOpenKeyEx(ReRootKey,ReSubKey,0,KEY_WRITE,&hKey)==ERROR_SUCCESS)
     {
      if(RegSetValueEx(hKey,ReValueName,NULL,REG_SZ,ReSetContent_S,
    CString(SetContent_S).GetLength())!=ERROR_SUCCESS)
      {
       AfxMessageBox("错误:无法设置有关的注册表信息");
       i=1;
      }
      RegCloseKey(hKey);
     }
     else
     {
      AfxMessageBox("错误:无法查询有关的注册表信息");
      i=1;
     }
     return
    i;
    }

    SetValue_D ( HKEY ReRootKey,TCHAR *ReSubKey,TCHAR *ReValueName,
    int
    ReSetContent_D[256])
    {
     //设置DWORD值函数
     int i=0;
    //操作结果:0==succeed
     if(RegOpenKeyEx(ReRootKey,ReSubKey,0,KEY_WRITE,&hKey)==ERROR_SUCCESS)
     {
      if(RegSetValueEx(hKey,ReValueName,NULL,REG_DWORD,(const
    unsigned char
    *)ReSetContent_D,4)!=ERROR_SUCCESS)
      {
       AfxMessageBox("错误:无法设置有关的注册表信息");
       i=1;
      }
      RegCloseKey(hKey);
     }
     else
     {
      AfxMessageBox("错误:无法查询有关的注册表信息");
      i=1;
     }
     return
    i;
    }
    SetValue_B (HKEY ReRootKey,TCHAR *ReSubKey,TCHAR *ReValueName,BYTE
    ReSetContent_B[256])
    {
     //设置二进制值函数
     int i=0;
    //操作结果:0==succeed
     if(RegOpenKeyEx(ReRootKey,ReSubKey,0,KEY_WRITE,&hKey)==ERROR_SUCCESS)
     {
      if(RegSetValueEx(hKey,ReValueName,NULL,REG_BINARY,
    (const
    unsigned char
    *)ReSetContent_B,4)!=ERROR_SUCCESS)
      {
       AfxMessageBox("错误:无法设置有关的注册表信息");
       i=1;
      }
      RegCloseKey(hKey);
     }
     else
     {
      AfxMessageBox("错误:无法查询有关的注册表信息");
      i=1;
     }
     return
    i;
    }

    DeleteKey ( HKEY ReRootKey,TCHAR *ReSubKey,TCHAR
    *ReKeyName)
    {
     //删除子项函数
     int i=0;
    //操作结果:0==succeed
     if((RegOpenKeyEx(ReRootKey,ReSubKey,0,KEY_WRITE,&hKey))==ERROR_SUCCESS)
     {
      if((RegDeleteKey(hKey,ReKeyName))!=ERROR_SUCCESS)
      {
       //AfxMessageBox("清除指定项失败!");
       i=1;
      }
      RegCloseKey(hKey);
     }
     else
     {
      //AfxMessageBox("错误:无法打开有关的hKEY");
      i=1;
     }
     return
    i;
    }

    DeleteValue (HKEY ReRootKey,TCHAR *ReSubKey,TCHAR
    *ReValueName)
    {
     //删除键值函数
     int i=0;
    //操作结果:0==succeed
     if(RegOpenKeyEx(ReRootKey,ReSubKey,0,KEY_WRITE,&hKey)==ERROR_SUCCESS)
     {
      if(RegDeleteValue(hKey,ReValueName)!=ERROR_SUCCESS)
      {
       //AfxMessageBox("清除指定值失败!");
       i=1;
      }
      RegCloseKey(hKey);
     }
     else
     {
      //AfxMessageBox("错误:无法打开有关的hKEY");
      i=1;
     }
     return
    i;
    }
    ///////////////////////////////////
    void
    CRegDemoDlg::OnSetValue_S()
    {
     // TODO: Add your control notification
    handler code here
     RootKey=HKEY_CURRENT_USER;
    //注册表主键名称
     SubKey="Software\\Microsoft"; //欲打开注册表值的地址
     ValueName="例1";
    //欲设置值的名称
     SetContent_S=LPBYTE("Visual C++编程实例");
    //值的内容
     if((SetValue_S(RootKey,SubKey,ValueName,SetContent_S))!=0)
      AfxMessageBox("操作失败!");
    }
    void
    CRegDemoDlg::OnSetContent_B()
    {
     // TODO: Add your control notification
    handler code here
     RootKey=HKEY_CURRENT_USER;
    //注册表主键名称
     SubKey="Software\\Microsoft"; //欲打开注册表值的地址
     ValueName="例2";
    //欲设置值的名称
     SetContent_B[0]=1;
    //值的内容
     if((SetValue_B(RootKey,SubKey,ValueName,SetContent_B))!=0)
      AfxMessageBox("操作失败!");
    }

    void CRegDemoDlg::OnSetContent_D()
    {
     // TODO: Add your control
    notification handler code here
     RootKey=HKEY_CURRENT_USER;
    //注册表主键名称
     SubKey="Software\\Microsoft"; //欲打开注册表值的地址
     ValueName="例3";
    //欲设置值的名称
     SetContent_D[0]=4294967295;
    //值的内容
     if((SetValue_D(RootKey,SubKey,ValueName,SetContent_D))!=0)
      AfxMessageBox("操作失败!");
    }

    void CRegDemoDlg::OnDeleteValue_1()
    {
     // TODO: Add your control
    notification handler code here
     RootKey=HKEY_CURRENT_USER;
    //注册表主键名称
     SubKey="Software\\Microsoft"; //欲打开注册表值的地址
     ValueName="例1";
    //欲设置值的名称
     if((DeleteValue
    (RootKey,SubKey,ValueName))!=0)
     AfxMessageBox("操作失败!");
    }

    void CRegDemoDlg::OnDeleteValue_2()
    {
     // TODO: Add your control
    notification handler code here
     RootKey=HKEY_CURRENT_USER;
    //注册表主键名称
     SubKey="Software\\Microsoft"; //欲打开注册表值的地址
     ValueName="例2";
    //欲设置值的名称
     if((DeleteValue
    (RootKey,SubKey,ValueName))!=0)
      AfxMessageBox("操作失败!");
    }

    void CRegDemoDlg::OnDeleteValue_3()
    {
     // TODO: Add your control
    notification handler code here
     RootKey=HKEY_CURRENT_USER;
    //注册表主键名称
     SubKey="Software\\Microsoft"; //欲打开注册表值的地址
     ValueName="例3";
    //欲设置值的名称
     if((DeleteValue
    (RootKey,SubKey,ValueName))!=0)
      AfxMessageBox("操作失败!");
    }
    void
    CRegDemoDlg::OnDeleteKey()
    {
     // TODO: Add your control notification
    handler code here
     RootKey=HKEY_CURRENT_USER;
    //注册表主键名称
     SubKey="Software\\Microsoft\\Windows\\CurrentVersion\\Explorer";
     //欲打开注册表值的地址
     KeyName="Doc Find Spec MRU"; //欲设置项的名称
     if((DeleteKey
    (RootKey,SubKey,KeyName))!=0)
      AfxMessageBox("操作失败!");
    }
    void
    CRegDemoDlg::OnShowContent()
    {
     // TODO: Add your control notification
    handler code here
     RootKey=HKEY_CURRENT_USER;
    //注册表主键名称
     SubKey="Software\\Microsoft"; //欲打开注册表值的地址
     ValueName="例1";
    //欲设置值的名称
     if
    ((ShowContent(RootKey,SubKey,ValueName))==0)
      MessageBox(content,"本操作是利用ShowContent()函数完成的。");
    }

      四、小结

      注册表的操作在实际编程中使用频率极高,在很多地方都要用到,比如,程序员自定义文件的图标就需要操作注册表,所以一个成熟优秀开发人员应掌握Windows灵魂--注册表存取技术,尽可能的利用注册表来发挥操作系统的各种优势。

  • 相关阅读:
    五个字符就能让你电脑死机
    易语言e.exe在一些系统运行出错解决方法
    检测是否联网
    JS判断设备的类型
    JavaScript判断移动端及pc端访问不同的网站
    代码片段
    WEB前端知识在乱花渐欲迷人眼的当下,如何分清主次和学习优先级呢?
    说说JSON和JSONP,也许你会豁然开朗
    HTML5 LocalStorage 本地存储
    namenode 和datanode无法启动,错误:FSNamesystem initialization failed. datanode.DataNode: Incompatible namespaceIDs
  • 原文地址:https://www.cnblogs.com/boneking/p/1337806.html
Copyright © 2020-2023  润新知