注册表操作总结

参考及摘抄自文章:http://www.cnblogs.com/lartely/archive/2011/04/10/2011770.html

              http://blog.csdn.net/sunboy_2050/article/details/7753662

基础知识:


注册表的组织方式跟文件目录比较相似,主要分为根键、子键和键值项三部分,与文件目录对应的话就是根目录、子目录和文件。分别介绍一下这三部分:
1.根键:共有5个,分别为HKEY_CLASSES_ROOT,HKEY_CURRENT_USER,HKEY_LOCAL_MACHINE,HKEY_USERS和HKEY_CURRENT_CONFIG,把它们理解成磁盘的五个分区可以了。
2.子键:可以有多个子键和键值项,就像一个目录中可以有多个子目录和多个文件一样。
3.键值项:可以理解为文件,它由三部分组成,分别为:名称、类型、数据。
类型又分为多种主要包括如下:
REG_BINARY 二进制数据
REG_DWORD 32位双字节数据
REG_SZ 以0结尾的字符串
REG_DWORD_BIG_ENDIAN 高位排在底位的双字
REG_EXPAND_SZ 扩展字符串,可以加入变量如%PATH%
REG_LINK UNICODE 符号链接
REG_RESOURCE_LIST 设备驱动程序资源列表
REG_MULTI_SZ 多字符串
注册表数据项的数据类型有8种,但最常用的主要是前3种。

常用API:


1.打开/关闭注册表键

LONG WINAPI RegOpenKeyEx(
  _In_        HKEY hKey,         // 父键句柄
  _In_opt_    LPCTSTR lpSubKey,  // 子键的名称
  _Reserved_  DWORD ulOptions,   // 保留项,传0即可
  _In_        REGSAM samDesired, // 访问权限
  _Out_       PHKEY phkResult    // 返回子键的句柄
);

HKEY hKey------

    父键的句柄,可为RegCreateKeyEx或RegOpenKeyEx返回的注册表键句柄

    或为预定义的根键HKEY_CLASSES_ROOT,HKEY_CURRENT_USER,HKEY_LOCAL_MACHINE,HKEY_USERS或HKEY_CURRENT_CONFIG

REGSAM samDesired------

    访问权限,想方便的话可以指定为KEY_ALL_ACCESS,这样什么权限都有了。其他常用的权限还有KEY_READ,KEY_WRITE等。

成功开启子键则返回ERROR_SUCCESS

LONG WINAPI RegCloseKey(
  _In_  HKEY hKey
);

这两个函数需配对使用

[cpp] view plaincopy
 
  1. // 打开注册表键------  
  2. HKEY hKey;  
  3. LPCTSTR lpszSubKey = TEXT("SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");  
  4. int ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpszSubKey, 0, KEY_ALL_ACCESS, &hKey);  
  5. if (ret != ERROR_SUCCESS)  
  6. {  
  7.     // 打开失败  
  8.     ......  
  9. }  
  10.   
  11. ......  
  12.           
  13. // 关闭注册表键------  
  14. RegCloseKey(hKey);  

2.获取注册表键的子键及键值的信息

每个注册表键下面都包含子键及键值项,RegQueryInfoKey函数用于获取子键的数量,键值项的数量等信息。

LONG WINAPI RegQueryInfoKey(
  _In_        HKEY hKey,               // 要获取信息的注册表键句柄
  _Out_opt_   LPTSTR lpClass,          // 一般传NULL
  _Inout_opt_ LPDWORD lpcClass,        // 一般传NULL
  _Reserved_  LPDWORD lpReserved,      // NULL
  _Out_opt_   LPDWORD lpcSubKeys,      // hKey下的子键数量
  _Out_opt_   LPDWORD lpcMaxSubKeyLen, // hKey下的子键名称的最大长度(不包含结尾的null字符)
  _Out_opt_   LPDWORD lpcMaxClassLen,  // 一般传NULL
  _Out_opt_   LPDWORD lpcValues,       // hKey下的键值的数量
  _Out_opt_   LPDWORD lpcMaxValueNameLen, // hKey下键值Name的最大长度(不包含结尾的null字符)
  _Out_opt_   LPDWORD lpcMaxValueLen,     // hKey下的键值Data的最大长度(in bytes)
  _Out_opt_   LPDWORD lpcbSecurityDescriptor, // 安全描述符长度,一般传NULL
  _Out_opt_   PFILETIME lpftLastWriteTime     // 最后修改时间,一般传NULL
);

通过RegQueryInfoKey获取了子键及键值项的信息后,这才知道子键的数量,键值项的数量等信息,后面就可以通过RegEnumKeyEx枚举子键信息,通过RegEnumValue枚举键值项信息。

[cpp] view plaincopy
 
  1. DWORD dwSubKeyCnt;          // 子键的数量  
  2. DWORD dwSubKeyNameMaxLen;   // 子键名称的最大长度(不包含结尾的null字符)  
  3. DWORD dwKeyValueCnt;        // 键值项的数量  
  4. DWORD dwKeyValueNameMaxLen; // 键值项名称的最大长度(不包含结尾的null字符)  
  5. DWORD dwKeyValueDataMaxLen; // 键值项数据的最大长度(in bytes)  
  6. int ret = RegQueryInfoKey(  
  7.     hKey,  
  8.     NULL,  
  9.     NULL,  
  10.     NULL,  
  11.     &dwSubKeyCnt,  
  12.     &dwSubKeyNameMaxLen,  
  13.     NULL,  
  14.     &dwKeyValueCnt,  
  15.     &dwKeyValueNameMaxLen,  
  16.     &dwKeyValueDataMaxLen,  
  17.     NULL,  
  18.     NULL);  
  19. if (ret != ERROR_SUCCESS) // Error  
  20. {  
  21.     ......  
  22. }  

3.枚举子键信息

LONG WINAPI RegEnumKeyEx(
  _In_         HKEY hKey,
  _In_         DWORD dwIndex,      // 索引,从0开始
  _Out_        LPTSTR lpName,      // 接收子键的名称
  _Inout_      LPDWORD lpcName,    // lpName的大小(in characters,包含null)
  _Reserved_   LPDWORD lpReserved, // NULL
  _Inout_      LPTSTR lpClass,     // 一般传NULL
  _Inout_opt_  LPDWORD lpcClass,   // 一般传NULL
  _Out_opt_    PFILETIME lpftLastWriteTime  // 一般传NULL
);

前面通过RegQueryInfoKey获取了hKey下子键的数量以及子键名称的最大长度,那么接下来通过RegEnumKeyEx就可以获取每个子键的名称了。为什么要获取子键的名称,因为获取了这个名称之后,就可以通过RegOpenKeyEx开启子键获得其句柄。

整个流程差不多是这样子的:RegQueryInfoKey-->获得某注册表键下的子键的数量及子键名称的最大长度-->RegEnumKeyEx-->枚举获取每个子键的名称-->RegOpenKeyEx-->开启子键句柄-->做你想要的操作。

lpName------

    前面通过RegQueryInfoKey获取了子键名称的最大长度(没有包含结尾的null字符),所有可以通过定义一个[最大长度+1]大小的Buffer来接收

lpcName------

    RegQueryInfoKey获取的子键名称的最大长度 + 1

[cpp] view plaincopy
 
  1. //  
  2. // 以下代码中的变量dwSubKeyNameMaxLen&dwSubKeyCnt由  
  3. // RegQueryInfoKey获取  
  4. //  
  5. LPTSTR lpszSubKeyName = new TCHAR[dwSubKeyNameMaxLen+1];  
  6. for (int index = 0; index < dwSubKeyCnt; ++index)  
  7. {  
  8.     memset(lpszSubKeyName, 0, sizeof(TCHAR)*(dwSubKeyNameMaxLen+1));  
  9.     DWORD dwNameCnt = dwSubKeyNameMaxLen + 1;  
  10.     int ret = RegEnumKeyEx(  
  11.         hKey,  
  12.         index,  
  13.         lpszSubKeyName,  
  14.         &dwNameCnt,  
  15.         NULL,  
  16.         NULL,  
  17.         NULL,  
  18.         NULL);  
  19.     if (ret != ERROR_SUCCESS)  
  20.     {  
  21.         ......  
  22.     }  
  23. }  
  24. delete[] lpszSubKeyName;  

4.枚举键值项信息

LONG WINAPI RegEnumValue(
  _In_         HKEY hKey,
  _In_         DWORD dwIndex,         // 索引,从0开始
  _Out_        LPTSTR lpValueName,    // 接收键值项的名称
  _Inout_      LPDWORD lpcchValueName,// lpValueName的大小,包含null character
  _Reserved_   LPDWORD lpReserved,    // NULL
  _Out_opt_    LPDWORD lpType,        // 接收键值项的类型
  _Out_opt_    LPBYTE lpData,         // 接收键值项的数据
  _Inout_opt_  LPDWORD lpcbData       // lpData的Buffer大小(in bytes)
);

前面通过RegQueryInfoKey获取了hKey下键值项的数量以及键值项名称的最大长度,键值项数据的最大长度,那么接下来通过RegEnumValue就可以获取每个键值项的名称、类型、数据。

[cpp] view plaincopy
 
  1. //  
  2. // 以下代码中变量:dwKeyValueCnt & dwKeyValueNameMaxLen &  
  3. //                dwKeyValueDataMaxLen  
  4. // 均为通过RegQueryInfoKey获取的  
  5. //  
  6. for (unsigned int index = 0; index < dwKeyValueCnt; ++index)  
  7. {  
  8.     LPTSTR lpszKeyValueName = new TCHAR[dwKeyValueNameMaxLen + 1];  
  9.     memset(lpszKeyValueName, 0, sizeof(TCHAR)*(dwKeyValueNameMaxLen + 1));  
  10.     DWORD  dwNameCnt = dwKeyValueNameMaxLen + 1;  
  11.     DWORD  dwKeyValueType;  
  12.     LPBYTE lpbKeyValueData = new BYTE[dwKeyValueDataMaxLen];  
  13.     DWORD  dwKeyValueDataLen;  
  14.       
  15.     int ret = RegEnumValue(  
  16.         hKey,   
  17.         index,   
  18.         lpszKeyValueName,  
  19.         &dwNameCnt,   
  20.         NULL,   
  21.         &dwKeyValueType,    
  22.         lpbKeyValueData,  
  23.         &dwKeyValueDataLen);  
  24.     if (ret != ERROR_SUCCESS)  
  25.     {  
  26.         ......  
  27.     }  
  28.     delete[] lpszKeyValueName;  
  29.     delete[] lpbKeyValueData;  
  30. }  

5.由键值项名称获取键值项的类型及键值项数据

LONG WINAPI RegQueryValueEx(
  _In_         HKEY hKey,
  _In_opt_     LPCTSTR lpValueName, // 键值项名称
  _Reserved_   LPDWORD lpReserved,  // NULL
  _Out_opt_    LPDWORD lpType,      // 接收键值项类型
  _Out_opt_    LPBYTE lpData,       // 接收键值项数据
  _Inout_opt_  LPDWORD lpcbData     // lpData的Buffer大小(in bytes)
);

有时候,我们知道某注册表键下的键值项的名称,而想获取键值项的类型及键值项数据,就可以通过该函数获取。

比如:我们知道HKEY_CURRENT_USEREnvironment注册表键下存在名为"Path"的键值项,通过该函数就可以获取其值。

通常情况下,虽然我们知道键值项的名称,却不知道键值项数据的大小,也即lpData该如何定义?可以分两步实现:一、调用RegQueryValueEx,但传lpData为NULL,函数执行成功后,lpcbData会返回键值项数据的大小。二、根据上一步获取的键值项数据的大小,new一个对应大小的Buffer,然后再调用RegQueryValueEx,传递lpData为新开辟的Buffer,这样就可以了。

[cpp] view plaincopy
 
  1. // 获取键值项Data的大小  
  2. LPCTSTR lpszKeyValueName = TEXT("???");  
  3. DWORD dwKeyValueType;  
  4. DWORD dwKeyValueDataSize;  
  5. int ret = RegQueryValueEx(hKey, lpszKeyValueName, NULL, &dwKeyValueType, NULL, &dwKeyValueDataSize);  
  6. if (ret != ERROR_SUCCESS)  
  7. {  
  8.     ......  
  9. }  
  10.   
  11. // 获取键值项Data  
  12. LPBYTE lpbKeyValueData = new BYTE[dwKeyValueDataSize];  
  13. ret = RegQueryValueEx(hKey, lpszKeyValueName, NULL, &dwKeyValueType, lpbKeyValueData, &dwKeyValueDataSize);  
  14. if (ret != ERROR_SUCCESS)  
  15. {  
  16.     ......  
  17. }  
  18.   
  19. delete[] lpbKeyValueData;  

6.设置键值项的值/新建键值项

LONG RegSetValueEx(
  HKEY hKey,
  LPCWSTR lpValueName,
  DWORD Reserved,
  DWORD dwType,
  const BYTE* lpData,
  DWORD cbData
);

该函数也可以新建键值项,当lpValueName指定名称的键值项不存在时,会新建键值项。

7.删除键值项

LONG RegDeleteValue( 
  HKEY hKey, 
  LPCWSTR lpValueName 
); 

8.创建、删除子键

LONG RegCreateKeyEx( 
  HKEY hKey, 
  LPCWSTR lpSubKey, 
  DWORD Reserved, 
  LPWSTR lpClass, 
  DWORD dwOptions, 
  REGSAM samDesired, 
  LPSECURITY_ATTRIBUTES lpSecurityAttributes, 
  PHKEY phkResult, 
  LPDWORD lpdwDisposition 
); 
LONG WINAPI RegDeleteKey(
  _In_  HKEY hKey,
  _In_  LPCTSTR lpSubKey
);

示例程序一:读取注册表获取计算机上已安装程序的信息


Windows 系统中,安装程序都可以在注册表 HKEY_LOCAL_MACHINESoftWareMicrosoftWindowsCurrentVersionUninstall 获取,并且xp、vista、win7、win8都一样

以下示例程序中:

结构体ApplicationInfoA用于记录每个安装程序的具体信息,至于为何在名称后面加A,主要是为了表明其下的信息全是用string记录的。

函数GetAllInstalledAppInfoA用于获取计算机上已安装程序的全部信息,它接受vector<ApplicationInfoA>引用类型的参数,并将获取的全部信息存放在该vector中。该程序执行成功返回0,执行失败则返回-1。

main()函数中演示了怎么使用:

vector<ApplicationInfoA> vAppInfo;     

GetAllInstalledAppInfoA(vAppInfo);

在获取了安装程序的信息后,输出到D盘下的InstalledAppInfo.txt文件中。

[cpp] view plaincopy
 
  1. #include <windows.h>  
  2. #include <iostream>  
  3. #include <TCHAR.H>  
  4. #include <vector>  
  5.   
  6. using namespace std;  
  7.   
  8. //  
  9. // 用于记录安装软件信息的结构体  
  10. //  
  11. struct ApplicationInfoA  
  12. {  
  13.     string strName;            // 软件名  
  14.     string strDisplayName;     // 显示的软件名  
  15.     string strPublisher;       // 发布者  
  16.     string strVersion;         // 版本  
  17.     string strDisplayVersion;  // 显示的版本  
  18.     string strInstallLocation; // 安装的位置  
  19. };  
  20.   
  21. //  
  22. // 获取具体的程序的键值Data  
  23. // hKey [in]  
  24. //     --- 指向HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionUninstall的子键句柄  
  25. // lpszKeyValueName [in]  
  26. //     --- hKey下面的子键名称  
  27. // lpszKeyValueName [in]  
  28. //     --- 正如其名,键值的名称  
  29. // strKeyValue [out]  
  30. //     --- 键值的Data  
  31. //  
  32. int _GetAppInfoA_(HKEY hKey, LPCSTR lpszAppName, LPCSTR lpszKeyValueName, string& strKeyValue)  
  33. {  
  34.     int ret;  
  35.   
  36.     // 打开已安装软件的注册表键------------------------------------------------  
  37.     HKEY hInstallAppKey;  
  38.     ret = RegOpenKeyEx(hKey, lpszAppName, 0, KEY_ALL_ACCESS, &hInstallAppKey);  
  39.     if (ret != ERROR_SUCCESS)  
  40.     {  
  41.         return -1;  
  42.     }  
  43.   
  44.     // 获取已安装软件的注册表键的键值------------------------------------------  
  45.     // 1.获取字符串大小(默认为字符串即REG_SZ)  
  46.     DWORD dwKeyValueType = REG_SZ;  
  47.     DWORD dwKeyValueDataSize = 0;  
  48.     ret = RegQueryValueExA(  
  49.         hInstallAppKey,  
  50.         lpszKeyValueName,  
  51.         NULL,  
  52.         &dwKeyValueType,  
  53.         NULL,  
  54.         &dwKeyValueDataSize);  
  55.     if (ret == ERROR_FILE_NOT_FOUND)  
  56.     {  
  57.         RegCloseKey(hInstallAppKey);  
  58.         return 0;  
  59.     }  
  60.     else if (ret != ERROR_SUCCESS)  
  61.     {  
  62.         RegCloseKey(hInstallAppKey);  
  63.         return -1;  
  64.     }  
  65.   
  66.     // 2.获取字符串值  
  67.     if (dwKeyValueType != REG_SZ)   // 如果不是字符串类型则返回,有的安装程序此项不为字符串而为其他类型,忽略  
  68.     {  
  69.         RegCloseKey(hInstallAppKey);  
  70.         return 0;  
  71.     }  
  72.     LPSTR lpszKeyValueData = new char[dwKeyValueDataSize + 1];  
  73.     memset(lpszKeyValueData, 0, dwKeyValueDataSize + 1);  
  74.     ret = RegQueryValueExA(  
  75.         hInstallAppKey,  
  76.         lpszKeyValueName,  
  77.         NULL,  
  78.         &dwKeyValueType,  
  79.         (LPBYTE)lpszKeyValueData,  
  80.         &dwKeyValueDataSize);  
  81.     if (ret != ERROR_SUCCESS)  
  82.     {  
  83.         delete[] lpszKeyValueData;  
  84.         RegCloseKey(hInstallAppKey);  
  85.         return -1;  
  86.     }  
  87.     strKeyValue = lpszKeyValueData;  
  88.     delete[] lpszKeyValueData;  
  89.   
  90.     // 关闭注册表键------------------------------------------------------------  
  91.     RegCloseKey(hInstallAppKey);  
  92.   
  93.     return 0;  
  94. }  
  95.   
  96.   
  97. //  
  98. // 获取系统安装的程序信息并存储于参数vector中  
  99. // 成功执行返回0  
  100. // 执行失败则返回-1  
  101. //  
  102. int GetAllInstalledAppInfoA(vector<ApplicationInfoA>& vAppInfo)  
  103. {  
  104.     int ret;  
  105.   
  106.     // 打开注册表键------------------------------------------------------------  
  107.     HKEY hKey;  
  108.     LPCSTR lpszSubKey = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";  
  109.     ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszSubKey, 0, KEY_ALL_ACCESS, &hKey);  
  110.     if (ret != ERROR_SUCCESS)  
  111.     {  
  112.         return -1;  
  113.     }  
  114.   
  115.     // 获取子键&键值信息-------------------------------------------------------  
  116.     DWORD dwSubKeysCnt;           // 子键数量  
  117.     DWORD dwMaxSubKeyNameLen;     // 子键名字的最大长度(not including the terminating null character)  
  118.     DWORD dwKeyValueCnt;          // 键值的数量  
  119.     DWORD dwMaxKeyValueNameLen;   // 键值名字的最大长度(not including the terminating null character)  
  120.     DWORD dwMaxKeyValueDataLen;   // 键值数据的最大长度(in Bytes)  
  121.   
  122.     ret = RegQueryInfoKey(  
  123.         hKey,  
  124.         NULL,  
  125.         NULL,  
  126.         NULL,  
  127.         &dwSubKeysCnt,  
  128.         &dwMaxSubKeyNameLen,  
  129.         NULL,  
  130.         &dwKeyValueCnt,  
  131.         &dwMaxKeyValueNameLen,  
  132.         &dwMaxKeyValueDataLen,  
  133.         NULL,  
  134.         NULL);  
  135.     if (ret != ERROR_SUCCESS)  
  136.     {  
  137.         RegCloseKey(hKey);  
  138.         return -1;  
  139.     }  
  140.   
  141.     // 枚举子键信息------------------------------------------------------------  
  142.     DWORD dwIndex;  
  143.     LPSTR lpszSubKeyName = new char[dwMaxSubKeyNameLen + 1];  
  144.     DWORD dwNameLen = dwMaxSubKeyNameLen + 1;  
  145.   
  146.     for (dwIndex = 0; dwIndex < dwSubKeysCnt; ++dwIndex)  
  147.     {  
  148.         dwNameLen = dwMaxSubKeyNameLen + 1;  
  149.         memset(lpszSubKeyName, 0, dwMaxSubKeyNameLen + 1);  
  150.   
  151.         ret = RegEnumKeyEx(  
  152.             hKey,  
  153.             dwIndex,  
  154.             lpszSubKeyName,  
  155.             &dwNameLen,  
  156.             NULL,  
  157.             NULL,  
  158.             NULL,  
  159.             NULL);  
  160.         if (ret != ERROR_SUCCESS)  
  161.         {  
  162.             RegCloseKey(hKey);  
  163.             delete[] lpszSubKeyName;  
  164.             return -1;  
  165.         }  
  166.   
  167.         //************获取具体的程序的安装信息BEG*************  
  168.         ApplicationInfoA appInfo;  
  169.         appInfo.strName = lpszSubKeyName;  
  170.         _GetAppInfoA_(hKey, lpszSubKeyName, "DisplayName", appInfo.strDisplayName);  
  171.         _GetAppInfoA_(hKey, lpszSubKeyName, "Publisher", appInfo.strPublisher);  
  172.         _GetAppInfoA_(hKey, lpszSubKeyName, "Version", appInfo.strVersion);  
  173.         _GetAppInfoA_(hKey, lpszSubKeyName, "DisplayVersion", appInfo.strDisplayVersion);  
  174.         _GetAppInfoA_(hKey, lpszSubKeyName, "InstallLocation", appInfo.strInstallLocation);  
  175.         vAppInfo.push_back(appInfo);  
  176.         //************获取具体的程序的安装信息END*************  
  177.     }  
  178.   
  179.     delete[] lpszSubKeyName;  
  180.   
  181.     // 关闭注册表键------------------------------------------------------------  
  182.     RegCloseKey(hKey);  
  183.     return 0;  
  184. }  
  185.   
  186. int main()  
  187. {  
  188.     cout << "Reg Demo Test" << endl;  
  189.   
  190.     vector<ApplicationInfoA> vAppInfo;  
  191.     cout << GetAllInstalledAppInfoA(vAppInfo) << endl;  
  192.   
  193.     //输出到文件  
  194.     vector<ApplicationInfoA>::iterator iter = vAppInfo.begin();  
  195.     FILE *fp = fopen("D:\InstalledAppInfo.txt", "a");  
  196.     while (iter != vAppInfo.end())  
  197.     {  
  198.         fprintf(fp, "---------------- ");  
  199.         fprintf(fp, "Name: %s  DisplayName: %s  Publisher: %s  Version: %s  DisplayVersion: %s  InstallLocation: %s ",   
  200.             iter->strName.c_str(), iter->strDisplayName.c_str(),  
  201.             iter->strPublisher.c_str(), iter->strVersion.c_str(),   
  202.             iter->strDisplayVersion.c_str(), iter->strInstallLocation.c_str());  
  203.         fprintf(fp, "---------------- ");  
  204.         ++iter;  
  205.     }  
  206.     fclose(fp);  
  207.   
  208.     return 0;  
  209. }  

示例程序二:增加Path环境变量


我们常常需要手工添加环境变量,如下图所示:

那么怎样用程序实现呢?环境变量的配置存储在注册表当中,可以通过读写注册表来实现读写环境变量。

系统变量存储在注册表的如下位置:HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession ManagerEnvironment

而用户变量则存储在注册表的如下位置:HKEY_CURRENT_USEREnvironment

下面示例程序用于向系统变量中的Path环境变量中增加内容。

main函数中调用AddPathEnvValue(";HelloKitty")就用于向Path环境变量后面添加;HelloKitty。当然程序中有防呆机制,如果系统变量下刚开始没有Path环境变量则先新增Path环境变量。程序执行成功返回0,执行失败返回-1。

代码如下:

[cpp] view plaincopy
 
    1. #include <windows.h>  
    2. #include <iostream>  
    3.   
    4. using namespace std;  
    5.   
    6. //  
    7. // 为系统变量下的Path环境变量增加内容lpszPathValue  
    8. // 成功则返回0  
    9. // 失败则返回-1  
    10. // 若刚开始Path环境变量为"D:\123"  
    11. // 则调用AddPathEnvValue(";HelloKitty")后为"D:\123;HelloKitty"  
    12. //  
    13. int AddPathEnvValue(LPCSTR lpszPathValue)  
    14. {  
    15.     int ret;  
    16.   
    17.     // 打开注册表键----------------------------------------  
    18.     HKEY hKey;  
    19.     LPCSTR lpszSubKey = "SYSTEM\CurrentControlSet\Control\Session Manager\Environment";  
    20.     ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszSubKey, 0, KEY_ALL_ACCESS, &hKey);  
    21.     if (ERROR_SUCCESS != ret)  
    22.     {  
    23.         cout << "RegOpenKeyExA():Error" << endl;  
    24.         return -1;  
    25.     }  
    26.       
    27.     // 读取注册表键的键值"Path"----------------------------  
    28.     // 1.获取KeyValueData即字符串的大小  
    29.     LPCSTR lpszKeyValueName = "Path";  
    30.     DWORD  dwKeyValueType = REG_EXPAND_SZ;  
    31.     DWORD  dwKeyValueDataSize = 0;     
    32.     ret = RegQueryValueExA(hKey, lpszKeyValueName, NULL, &dwKeyValueType, NULL, &dwKeyValueDataSize);  
    33.     if (ret == ERROR_FILE_NOT_FOUND)  
    34.     {  
    35.         //不存在Path环境变量则新增一个Path环境变量  
    36.         ret = RegSetValueExA(hKey, lpszKeyValueName, 0, REG_EXPAND_SZ, (const BYTE*)"", 1);  
    37.         if (ret != ERROR_SUCCESS)  
    38.         {  
    39.             cout << "RegSetValueExA():Error" << endl;  
    40.             RegCloseKey(hKey);  
    41.             return -1;  
    42.         }  
    43.     }  
    44.     else if (ret != ERROR_SUCCESS)  
    45.     {  
    46.         cout << "RegQueryValueExA():Error" << endl;  
    47.         RegCloseKey(hKey);  
    48.         return -1;  
    49.     }  
    50.     else if (dwKeyValueType != REG_EXPAND_SZ)  
    51.     {  
    52.         cout << "It is impossible" << endl;  
    53.         cout << dwKeyValueType << endl;  
    54.         RegCloseKey(hKey);  
    55.         return -1;  
    56.     }  
    57.   
    58.     // 2.获取KeyValueData即字符串的值  
    59.     CHAR *lpszKeyValueData = new CHAR[dwKeyValueDataSize + 1];  
    60.     memset(lpszKeyValueData, 0, dwKeyValueDataSize + 1);  
    61.     ret = RegQueryValueExA(hKey, lpszKeyValueName, NULL, &dwKeyValueType, (LPBYTE)lpszKeyValueData, &dwKeyValueDataSize);  
    62.     if (ret != ERROR_SUCCESS)  
    63.     {  
    64.         cout << "RegQueryValueExA():Error" << endl;  
    65.         RegCloseKey(hKey);  
    66.         delete[] lpszKeyValueData;  
    67.         return -1;  
    68.     }  
    69.   
    70.     // 在原注册表键值的基础上添加新的值  
    71.     unsigned int nLen = strlen(lpszPathValue);  
    72.     nLen += strlen(lpszKeyValueData);  
    73.     CHAR *lpszKeyValueData_New = new CHAR[nLen + 1];  
    74.     memset(lpszKeyValueData_New, 0, nLen + 1);  
    75.     sprintf(lpszKeyValueData_New, "%s%s", lpszKeyValueData, lpszPathValue);  
    76.     ret = RegSetValueExA(hKey, lpszKeyValueName, 0, REG_EXPAND_SZ, (const BYTE*)lpszKeyValueData_New, strlen(lpszKeyValueData_New) + 1);  
    77.     if (ret != ERROR_SUCCESS)  
    78.     {  
    79.         cout << "RegSetValueExA:Error" << endl;  
    80.         RegCloseKey(hKey);  
    81.         delete[] lpszKeyValueData;  
    82.         delete[] lpszKeyValueData_New;  
    83.   
    84.         return -1;  
    85.     }  
    86.   
    87.   
    88.     delete[] lpszKeyValueData;  
    89.     delete[] lpszKeyValueData_New;  
    90.   
    91.     // 关闭注册表键----------------------------------------  
    92.     RegCloseKey(hKey);  
    93.   
    94.     return 0;  
    95. }  
    96.   
    97. int main()  
    98. {  
    99.     cout << AddPathEnvValue(";HelloKitty") << endl;  
    100.   
    101.     return 0;  
    102. }  
原文地址:https://www.cnblogs.com/liaocheng/p/4266079.html