`
hr106hr
  • 浏览: 14235 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

读写windows注册表

 
阅读更多

读写windows注册表
2011年05月22日
  Windows注册表是Windows的灵魂,它不仅保存了windows运行时所有配置信息,而且包括所有应用程序的运行环境。下面我们通过一个实例来展示一下如何利用windows提供的api来操作注册表。
  注册表函数对注册表的操作是通过句柄来完成的,与文件操作一样,在对某个键下的子键或者键值项进行操作之前,需要先将这个键打开,然后使用键句柄来引用这个键,在操作完毕以后再将键句柄关闭。注册表的根键不需要打开,它们的句柄是固定不变的,要使用根键的时候只要把这些句柄直接拿来用就是了,在WinReg.h已经定义了这些句柄值, 下面是常用的:
  #define HKEY_CLASSES_ROOT           (( HKEY ) (ULONG_PTR)((LONG)0x80000000) )
  #define HKEY_CURRENT_USER           (( HKEY ) (ULONG_PTR)((LONG)0x80000001) )
  #define HKEY_LOCAL_MACHINE          (( HKEY ) (ULONG_PTR)((LONG)0x80000002) )
  #define HKEY_USERS                  (( HKEY ) (ULONG_PTR)((LONG)0x80000003) )
  #define HKEY_CURRENT_CONFIG         (( HKEY ) (ULONG_PTR)((LONG)0x80000005) )
  在程序中可以随时将这些助记符当做句柄来引用对应的根键。在程序结束的时候,不需要关闭这些根键句柄。
  打开子键使用RegOpenKeyEx函数,在Win16中还存在一个RegOpenKey函数,虽然在Win32中这个函数仍然存在,但这仅是为了兼容的目的而设置的。API手册中推荐使用RegOpenKeyEx函数:
  LONG RegOpenKeyEx( HKEY hKey,
  LPCWSTR lpSubKey,
  DWORD ulOptions,
  REGSAM samDesired,
  PHKEY phkResult );
  函数的hKey参数指定父键句柄,lpSubKey指向一个字符串,用来表示要打开的子键名称,在系统中一个子键的全称是以“根键\第1层子键\第2层子键\第n层子键”类型的字符串表示的,中间用“\”隔开,字符串的最后以0字符结束,这和目录名的表示方法是很像的。
  既然子键的全称是这样表示的,那么要打开一个子键的时候,下面的两种表示方法有什么不同呢?
  (1)父键=HKEY_LOCAL_MACHINE,子键=Software\RegTest\MySubkey
  (2)父键=HKEY_LOCAL_MACHINE\Software,子键=RegTest\MySubkey
  答案是:这两种表示方法是完全相同的。在使用RegOpenKeyEx函数打开子键的时候,既可以将hKey参数设置为HKEY_LOCAL_MACHINE根键的句柄,并将lpSubKey参数指向“Software\RegTest\MySubkey”字符串;也可以将hKey参数设置为“HKEY_LOCAL_ MACHINE\Software”的句柄,将lpSubKey参数指向“RegTest\MySubkey”字符串,得到的结果是一样的。但是,使用第一种方法时,hKey参数可以直接使用助记符HKEY_LOCAL_ MACHINE来表示,因为根键的句柄是固定的,不需要打开;而使用第二种方法时,还需要先打开“HKEY_LOCAL_MACHINE\Software”键来获取它的句柄,所以具体使用哪种方法还要根据具体情况灵活选用。
  函数的其他几个参数的含义如下。
  ●   ulOptions参数――系统保留参数,必须指定为0。
  ●   samDesired参数――子键的打开方式,根据使用子键的方式,可以设置为下列取值的组合,只有指定了打开的方式,才能在打开子键后进行相应的操作:
  ■   KEY_ALL_ACCESS――允许所有的存取。
  ■   KEY_CREATE_LINK――允许建立符号列表。
  ■   KEY_CREATE_SUB_KEY――允许建立下一层子键。
  ■   KEY_ENUMERATE_SUB_KEYS――允许枚举下一层子键。
  ■   KEY_EXECUTE――允许读操作。
  ■   KEY_QUERY_VALUE――允许查询键值数据。
  ■   KEY_READ―KEY_QUERY_VALUE,KEY_ENUMERATE_SUB_KEYS和KEY_ NOTIFY的组合。
  ■   KEY_SET_VALUE――允许修改或创建键值数据。
  ■   KEY_WRITE――KEY_SET_VALUE和KEY_CREATE_SUB_KEY的组合。
  ●   phkResult参数――指向一个双字变量,函数在这里返回打开的子键句柄。
  如果函数执行成功,返回值是ERROR_SUCCESS,并且函数在phkResult参数指向的变量中返回子键句柄。
  当不再需要继续使用键句柄的时候,可以使用RegCloseKey函数将它关闭:
  invoke  RegCloseKey,hKey
  如果句柄被成功关闭,函数返回ERROR_SUCCESS。
  创建一个子键可以使用RegCreateKeyEx函数:
  LONG RegCreateKeyEx( HKEY hKey,
  LPCWSTR lpSubKey,
  DWORD Reserved,
  LPWSTR lpClass,
  DWORD dwOptions,
  REGSAM samDesired,
  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  PHKEY phkResult,
  LPDWORD lpdwDisposition );
  函数中与RegOpenKeyEx函数中同名参数的含义和用法是相同的,hKey也是用来指定父键句柄,lpSubKey指向要创建的子键名称字符串,samDesired参数指明子键建立后的操作方式,phkResult指向用来返回键句柄的双字变量。
  其余一些参数的含义如下。
  ●   Reserved参数――保留参数,必须设置为0。
  ●   lpClass参数――为创建的子键定义一个类名,这个参数一般设置为NULL。
  ●   dwOptions参数――创建子键时的选项,它可以是以下取值之一:
  ■   REG_OPTION_NON_VOLATILE――默认值,子键被创建到注册表文件中。
  ■   REG_OPTION_VOLATILE――创建易失性的子键,子键被保存在内存中,当系统重新启动的时候,子键消失。这个选项仅对Windows NT系统有效,在9x系统中被忽略。
  ●   lpSecurityAttributes参数――指向一个SECURITY_ATTRIBUTES结构,用来指定键句柄的继承性,如果句柄不需要被继承,可以使用NULL。
  ●   lpdwDisposition参数――这个参数一般使用NULL。
  当需要创建的子键已经存在的时候,函数仅起到RegOpenKeyEx函数的作用;如果子键不存在,那么函数将创建子键。如果函数执行成功,返回值是ERROR_SUCCESS。
  如果要创建“HKEY_LOCAL_MACHINE\Key1\Key2\Key3”子键,既可以将hKey参数设置为HKEY_LOCAL_MACHINE,将lpSubKey参数指向“Key1\Key2\Key3”字符串;也可以先打开“HKEY_LOCAL_MACHINE\Key1”键,将hKey设置为打开的键句柄,然后将lpSubKey参数指向“Key2\Key3”字符串,这和RegOpenKeyEx函数中的用法是类似的。在第二种用法中,打开父键的时候注意要指定KEY_CREATE_SUB_KEY方式。
  当被创建子键的上层键不存在的时候,函数连上层的子键一起创建。如上面的例子中,假如Key2也不存在,那么函数先在“HKEY_LOCAL_MACHINE\Key1”下创建Key2,然后在Key2下继续创建Key3。
  删除子键使用RegDeleteKey函数:
  LONG RegDeleteKey( HKEY hKey,
  LPCWSTR lpSubKey );
  hKey参数为父键句柄,lpSubKey参数指向要删除的子键名称字符串。函数仅删除最后一层子键以及下面的全部键值项。比如在“HKEY_LOCAL_MACHINE\Key1\Key2\Key3”子键存在的情况下,当hKey指定为HKEY_LOCAL_MACHINE,lpSubKey指向“Key1\Key2\Key3”的时候,函数仅删除Key3子键,不会连同Key2,Key1全部删除。但如果Key3子键下有键值项的话,这些键值项会被一起删除。
  如果要删除的子键下还存在下一层子键,比如上例中的Key3子键下还存在Key4子键,那么对Key3子键进行删除时,Windows 9x和Windows NT系统的做法是不同的:在Windows 9x中,Key3子键本身、Key3子键下所有的键值项和下层子键(包括上面举例的Key4)会被全部删除;而在Windows NT中,只有在不存在下层子键的情况下删除才能成功,如果Key3子键下还存在Key4子键,那么对Key3子键的删除是不会成功的。
  应用程序不能直接在HKEY_LOCAL_MACHINE根键下面创建和删除子键,只能在下一层由系统定义的子键下进行操作,如果要保存配置信息的话,用户应用程序一般在HKEY_LOCAL_MACHINE\SOFTWARE子键下再创建自己的子键,然后将键值项保存在自己的子键中。
  配置信息是存放在键值项中的,打开或者创建一个键的最终目的都是为了在键下面存取键值项,这就像磁盘上的目录是用来合理组织和管理文件用的,数据还是存放在文件中的。当使用打开或者创建键的函数得到键句柄后,就可以通过它来存取键值项了。
  在一个键下面设置和创建键值项使用RegSetValueEx函数:
  LONG RegSetValueEx( HKEY hKey,
  LPCWSTR lpValueName,
  DWORD Reserved,
  DWORD dwType,
  const BYTE *lpData,
  DWORD cbData );
  hKey参数指定一个键句柄,键值项将保存在这个键下,lpValueName参数指向定义键值项名称的字符串。假如lpValueName参数指向一个空串或者设置为NULL,并且设置的键值类型是REG_SZ的话,那么函数设置的是键的默认值。
  Reserved参数是保留的,必须设置为0。
  dwType参数指出了要设置的键值数据的类型,可以使用的类型如下:
  REG_BINARY
  任何方式的二进制数据
  REG_DWORD
  一个32位的双字(同REG_DWORD_LITTLE_ENDIAN)
  REG_DWORD_BIG_ENDIAN
  高位排在低字节的双字
  REG_EXPAND_SZ
  扩展字符串,可以将中间类似于“%PATH%”类型的子串按照环境变量中的定义值扩展
  REG_LINK
  Unicode符号链接
  REG_MULTI_SZ
  多字符串,格式为“字符串1,0,字符串2,0,0”类型
  REG_RESOURCE_LIST
  设备驱动程序资源列表
  REG_SZ
  以0结尾的字符串(最常用的类型!)
  lpData参数是一个指针,指向包含键值数据的缓冲区,cbData参数为要保存的数据长度。缓冲区中的数据格式以及cbData参数指定的数据长度需要和dwType参数指出的键值类型相对应,比如要设置REG_SZ类型的键值项,就要将cbData参数设置为字符串的长度+1(加上尾部的0);同样对于REG_MULTI_SZ类型的键值项来说,最后的两个0的长度都必须包括到cbData参数中;对于REG_DWORD类型的键值项,需要将双字数据放在缓冲区中并将cbData参数设置为4(不像其他函数一样当参数是双字的时候一般将双字在参数中直接传递)。
  当子键中的键值项不存在的时候,函数新建键值项;当键值项已经存在的时候,函数将新的键值数据写入。如果键值数据保存成功,函数返回ERROR_SUCCESS。
  虽然键值数据的最大长度没有规定,其大小仅受限于可用的内存大小,应用程序甚至可以使用REG_BINARY格式的键值项将整个文件都保存到注册表中,但在实际的使用中还是建议不要将大于2 KB的数据放到注册表中,因为这将影响注册表的使用效率。
  要在一个键中创建或修改键值项,键的打开方式中必须包括KEY_SET_VALUE方式。
  读取键值项中的数据或者查询键值项的属性使用RegQueryValueEx函数,用法如下:
  LONG RegQueryValueEx( HKEY hKey,
  LPCWSTR lpValueName,
  LPDWORD lpReserved,
  LPDWORD lpType,
  LPBYTE lpData,
  LPDWORD lpcbData );
  参数hKey和lpValueName用来指定要读取的键值项所处的子键句柄和键值项的名称, lpReserved参数是保留参数,必须使用0。lpData参数指向一个缓冲区,用来接收返回的键值数据。
  函数的其余几个参数使用时必须注意的是它们都是指向双字变量的指针,这一点和使用RegSetValueEx函数时是不同的:
  ●   lpType参数――函数在这个参数指向的双字变量中返回读取的键值类型,如果不需要返回键值项的类型,可以将这个参数设置为NULL。
  ●   lpcbData参数――在调用的时候,程序必须在这个参数指向的双字变量中放置缓冲区的长度(并不是直接用lpcbData参数指出缓冲区长度)。当函数返回的时候,双字变量被函数改为返回到缓冲区中的数据的实际长度。
  当函数执行成功的时候,函数的返回值是ERROR_SUCCESS。当程序指定的缓冲区长度不足以容纳返回的数据的时候,函数的返回值是ERROR_MORE_DATA,这时lpcbData参数指向的双字变量中返回需要的长度。
  如果仅需要查询键值长度而不需要返回实际的数据,可以将lpData参数设置为NULL,但是lpcbData参数不能为NULL,这时函数会在lpcbData参数指向的双字变量中返回键值数据的长度。如果仅想查询键值项的类型,也可以同时将lpcbData和lpData参数设置为NULL。在这些情况下如果函数查询成功,返回值也是ERROR_SUCCESS。
  如果要在一个键中查询键值数据的话,键的打开方式中必须包括KEY_QUERY_VALUE方式。
  删除一个键值项的操作则比较简单,使用RegDeleteValue函数就可以了:
  LONG RegDeleteKey( HKEY hKey,
  LPCWSTR lpSubKey );
  hKey参数和lpValueName指定父键句柄和被删除键值项的名称。惟一需要注意的是父键句柄的打开方式必须包括KEY_SET_VALUE。如果键值项被成功删除,则函数返回ERROR_SUCCESS。
  有时候我们需要枚举所有的子键:
  LONG RegEnumKeyEx( HKEY hKey,
  DWORD dwIndex,
  LPWSTR lpName,
  LPDWORD lpcbName,
  LPDWORD lpReserved,
  LPWSTR lpClass,
  LPDWORD lpcbClass,
  PFILETIME lpftLastWriteTime );
  hKey参数指定被枚举的键句柄,dwIndex参数指定需要返回信息的子键索引编号,lpName指向一个缓冲区,函数在这里返回子键名称,lpClass指向用于返回子键类名的缓冲区,lpftLastWriteTime指向一个FILETIME结构,函数在这里返回子键上一次被写入的时间。lpReserved参数是保留参数,必须设置为0。
  要注意的是:lpcbName和lpcbClass指向两个双字变量,调用函数前,这两个双字变量中必须放入lpName和lpClass指定的缓冲区的长度,当函数返回的时候,函数在里面返回实际返回到缓冲区中的字符串的长度。如果函数执行成功,返回值是ERROR_SUCCESS。
  RegEnumKeyEx函数每次返回一个子键的名称信息,所以要枚举全部子键的话,必须用循环多次调用这个函数,并且每次将dwIndex参数指定的子键索引号递增,当子键全部被枚举后,继续调用函数将得到一个ERROR_NO_MORE_ITEMS返回值,这时就可以结束循环了。
  RegEnumKeyEx函数仅枚举一个键下面的全部子键,对键下面的键值项则不会去理会。如果要枚举一个键下面的键值项,那么必须使用RegEnumValue函数:
  LONG RegEnumValue( HKEY hKey,
  DWORD dwIndex,
  LPWSTR lpValueName,
  LPDWORD lpcbValueName,
  LPDWORD lpReserved,
  LPDWORD lpType,
  LPBYTE lpData,
  LPDWORD lpcbData );
  函数的hKey,dwIndex和lpReserved参数的使用同RegEnumKeyEx函数中的同名参数。其余的一些参数中,lpValueName和lpData参数指向两个缓存区,函数在里面分别返回键值项的名称和数据。lpcbValueName和lpcbData参数指向两个双字变量,调用函数前里面必须放入键值项名称缓冲区和键值数据缓冲区的长度,函数返回后这两个变量的值被改为返回到缓冲区中的数据长度。lpType参数则指向一个用于返回键值数据类型的双字变量。
  如果不需要返回键值数据,lpData和lpcbData参数可以设置为NULL,如果不需要返回键值数据类型,lpType参数也可以设置为NULL。
  下面的是例子源代码:
  新建一个VC6++win32应用程序的空工程,加入以下文件:
  // reg.h
  /*******************************************************************************/
  /*  下面的一组自定义函数,为操作注册表提供了方便,可以直接在其他的例程中使用   */
  /*******************************************************************************/
  /*******************************************************************************
  _RegQueryValue: 查询键值
  hRootKey: 根键
  lpszKey: 子键
  lpszValueName: 要查询的键值名称
  lpszValue: 返回键值的缓冲区
  lpdwSize: 返回键值的缓冲区大小
  lpdwType: 返回键值的类型
  例:
  char szValue[256];
  DWORD dwType;
  _RegQueryValue(HKEY_LOCAL_MACHINE,
  "SoftWare\\Microsoft\\Windows\\CurrentVersion\\Run",
  "MyProgram", szValue, sizeof(szValue), &dwType);                   
  ********************************************************************************/
  DWORD    _RegQueryValue(HKEY hRootKey, LPCTSTR lpszKey, LPCTSTR lpszValueName, LPTSTR lpszValue,
  LPDWORD lpdwSize, LPDWORD lpdwType);
  /**********************************************************************************
  _RegSetValue: 添加键值
  hRootKey: 根键
  lpszKey: 子键
  lpszValueName: 键值名称
  lpszValue: 键值
  dwValueType: 键值类型
  dwSize: 键值长度
  例:
  char szValue[] = TEXT("C:\\abc.exe");
  _RegSetValue(HKEY_LOCAL_MACHINE,
  "SoftWare\\Microsoft\\Windows\\CurrentVersion\\Run",
  "MyProgram", szValue, REG_SZ, sizeof(szValue));
  ***********************************************************************************/
  void    _RegSetValue(HKEY hRootKey, LPCTSTR lpszKey, LPCTSTR lpszValueName, LPCTSTR lpszValue,
  DWORD dwValueType, DWORD dwSize);
  /*************************************************************************************
  _RegCreateKey: 创建子键
  hRootKey: 根键
  lpszKey: 子键
  lpszSubKeyName: 要创建的子键名称
  例:
  _RegCreateKey(HKEY_LOCAL_MACHINE,
  "SoftWare\\Microsoft\\Windows\\CurrentVersion\\Run",
  "MySubKey");
  **************************************************************************************/
  void    _RegCreateKey(HKEY hRootKey, LPCTSTR lpszKey, LPCTSTR lpszSubkeyName);
  /*************************************************************************************
  _RegDelValue: 删除键值
  hRootKey: 根键
  lpszKey: 子键
  lpszValueName: 要删除的键值名称
  例:
  _RegDelValue(HKEY_LOCAL_MACHINE,
  "SoftWare\\Microsoft\\Windows\\CurrentVersion\\Run",
  "MyProgram");
  **************************************************************************************/
  void    _RegDelValue(HKEY hRootKey, LPCTSTR lpszKey, LPCTSTR lpszValueName);
  /*************************************************************************************
  _RegDelSubKey: 删除子键
  hRootKey: 根键
  lpszKey: 子键
  lpszSubkeyName: 要删除的子键名称
  例:
  _RegDelSubkey(HKEY_LOCAL_MACHINE,
  "SoftWare\\Microsoft\\Windows\\CurrentVersion\\Run",
  "MySubKey");
  **************************************************************************************/
  void    _RegDelSubkey(HKEY hRootKey, LPCTSTR lpszKey, LPCTSTR lpszSubkeyName);
  /************************************************************************************/
  /*************************下面是具体的实现****************************************/
  DWORD    _RegQueryValue(HKEY hRootKey, LPCTSTR lpszKey, LPCTSTR lpszValueName, LPTSTR lpszValue,
  LPDWORD lpdwSize, LPDWORD lpdwType)
  {
  HKEY hKey;
  DWORD dwRtn = -1;
  // 打开子键
  dwRtn = RegOpenKeyEx(hRootKey, lpszKey, NULL, KEY_QUERY_VALUE, &hKey);
  if ( dwRtn == ERROR_SUCCESS )
  {
  // 查询当前子键下的某一键值, lpszValueName为键的名称, lpszValue为返回的键值
  dwRtn = RegQueryValueEx(hKey, lpszValueName, NULL, lpdwType, lpszValue, lpdwSize);
  RegCloseKey(hKey);
  }
  return dwRtn;
  }
  void    _RegSetValue(HKEY hRootKey, LPCTSTR lpszKey, LPCTSTR lpszValueName, LPCTSTR lpszValue,
  DWORD dwValueType, DWORD dwSize)
  {
  HKEY hKey;
  // 获取将要创建键值的子键的句柄
  if  ( ERROR_SUCCESS == RegCreateKey(hRootKey, lpszKey, &hKey) )
  {
  // 设置键值
  RegSetValueEx(hKey, lpszValueName, 0, dwValueType, lpszValue, dwSize);
  RegCloseKey(hKey);
  }
  }
  void    _RegCreateKey(HKEY hRootKey, LPCTSTR lpszKey, LPCTSTR lpszSubkeyName)
  {
  HKEY hKey, hSubkey;
  DWORD dwDisp;
  // 打开要创建子键的键
  if ( ERROR_SUCCESS == RegOpenKeyEx(hRootKey, lpszKey, NULL, KEY_CREATE_SUB_KEY, &hKey))
  {
  // 创建子键
  RegCreateKeyEx(hKey, lpszSubkeyName, 0, NULL, 0, 0, NULL, &hSubkey, &dwDisp);
  RegCloseKey(hKey);
  RegCloseKey(hSubkey);
  }
  }
  void    _RegDelValue(HKEY hRootKey, LPCTSTR lpszKey, LPCTSTR lpszValueName)
  {
  HKEY hKey;
  //获取将要删除一个键值的子键的句柄
  if ( ERROR_SUCCESS == RegOpenKeyEx(hRootKey, lpszKey, NULL, KEY_WRITE, &hKey) )
  {
  // 删除下面的某一个键值,lpszValueName为键值名称
  RegDeleteValue(hKey, lpszValueName);
  RegCloseKey(hKey);
  }
  }
  void    _RegDelSubkey(HKEY hRootKey, LPCTSTR lpszKey, LPCTSTR lpszSubkeyName)
  {
  HKEY hKey;
  // 获取将要删除子键的子键句柄
  if ( ERROR_SUCCESS == RegOpenKeyEx(hRootKey, lpszKey, NULL, KEY_WRITE, &hKey) )
  {
  // 删除子键
  RegDeleteKey(hKey, lpszSubkeyName);
  RegCloseKey(hKey);
  }
  }
  // reg.c
  #include
  #include "resource.h"
  #include "reg.h"
  HWND    hWinMain = NULL;
  char    szLocalMachine[] = TEXT("HKEY_LOCAL_MACHINE");
  char    szUsers[] = TEXT("HKEY_USERS");
  char    szCurrentUser[] = TEXT("HKEY_CURRENT_USER");
  char    szClassRoot[] = TEXT("HKEY_CLASSES_ROOT");
  char    szCurrentConfig[] = TEXT("HKEY_CURRENT_CONFIG");
  char    szTypeSz[] = TEXT("REG_SZ");
  char    szTypeDw[] = TEXT("REG_DWORD");
  char    szFmtSubkey[] = TEXT("【子键】%s\r\n");
  char    szFmtSz[] = TEXT("【键值】%s=%s (REG_SZ类型)\r\n");
  char    szFmtDw[] = TEXT("【键值】%s=%08X (REG_DWORD类型)\r\n");
  char    szFmtValue[] = TEXT("【键值】%s (其它类型)\r\n");
  char    szNotSupport[] = TEXT("程序暂不显示其它类型键值!");
  void    EnumKey(HKEY hRootKey, LPCTSTR lpSubkey);
  LRESULT CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  void    AutoRun(BYTE bAutoRun);
  void    GetFileName(char *szFullPath, char *szFileName);
  void    CheckAutoRun();
  int WINAPI WinMain(IN HINSTANCE hInstance, IN HINSTANCE hPrevInstance, IN LPSTR lpCmdLine, IN int nShowCmd )
  {
  DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, DialogProc, 0);
  return 0;
  }
  void    EnumKey(HKEY hRootKey, LPCTSTR lpSubkey)
  {
  HKEY    hKey;
  DWORD    dwIndex;
  FILETIME    dwLastTime;
  char    szBuffer[512];
  char    szBuffer1[512];
  char    szValue[256];
  DWORD    dwSize1, dwSize, dwType;
  dwIndex = 0;
  // 将显示文本框清空
  SendDlgItemMessage(hWinMain, IDC_KEYLIST, WM_SETTEXT, 0, 0);
  // 获取当前子键下的所有子键
  if ( ERROR_SUCCESS == RegOpenKeyEx(hRootKey, lpSubkey, NULL, KEY_ENUMERATE_SUB_KEYS, &hKey))
  {
  while ( TRUE )
  {
  dwSize = sizeof(szBuffer);           
  // 枚举子键
  if ( ERROR_NO_MORE_ITEMS == RegEnumKeyEx(hKey, dwIndex, szBuffer, &dwSize,
  NULL, NULL, NULL, NULL))
  break;
  wsprintf(szBuffer1, szFmtSubkey, szBuffer);
  SendDlgItemMessage(hWinMain, IDC_KEYLIST, EM_REPLACESEL, 0, szBuffer1);
  ++dwIndex;
  }
  RegCloseKey(hKey);
  }
  dwIndex = 0;
  // 枚举当前子键下的所有键值
  if ( ERROR_SUCCESS == RegOpenKeyEx(hRootKey, lpSubkey, NULL, KEY_QUERY_VALUE, &hKey))
  {
  while ( TRUE )
  {
  dwSize = sizeof(szBuffer);
  dwSize1 = sizeof(szValue);
  // 枚举键值
  if ( ERROR_NO_MORE_ITEMS == RegEnumValue(hKey, dwIndex, szBuffer, &dwSize, NULL,
  &dwType, szValue, &dwSize1))
  break;
  if ( dwType == REG_SZ )
  wsprintf(szBuffer1, szFmtSz, szBuffer, szValue);
  else if ( dwType == REG_DWORD )
  wsprintf(szBuffer1, szFmtDw, szBuffer, (DWORD)szValue);
  else
  wsprintf(szBuffer1, szFmtValue, szBuffer, szValue);
  SendDlgItemMessage(hWinMain, IDC_KEYLIST, EM_REPLACESEL, 0, szBuffer1);
  ++dwIndex;
  }
  RegCloseKey(hKey);
  }
  }
  LRESULT CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  {
  char szKey[256], szSubKey[256], szValueName[256], szValue[256];
  DWORD dwType, dwSize;
  int nIndex;
  HKEY hKey = NULL;
  int nValue;
  BYTE *pB = NULL;
  nIndex = SendDlgItemMessage(hWnd, IDC_ROOTKEY, CB_GETCURSEL, 0, 0);
  if ( nIndex != CB_ERR )
  hKey = SendDlgItemMessage(hWnd, IDC_ROOTKEY, CB_GETITEMDATA, nIndex, 0);
  if ( hWinMain != NULL )
  {
  GetDlgItemText(hWinMain, IDC_KEY, szKey, sizeof(szKey));
  GetDlgItemText(hWinMain, IDC_SUBKEY, szSubKey, sizeof(szSubKey));
  GetDlgItemText(hWinMain, IDC_VALUENAME, szValueName, sizeof(szValueName));
  GetDlgItemText(hWinMain, IDC_VALUE, szValue, sizeof(szValue));
  }
  switch ( uMsg )
  {
  case WM_CLOSE:
  EndDialog(hWnd, 0);
  break;
  case WM_INITDIALOG:
  hWinMain = hWnd;
  SendDlgItemMessage(hWnd, IDC_TYPE, CB_INSERTSTRING, 0, szTypeSz);
  SendDlgItemMessage(hWnd, IDC_TYPE, CB_INSERTSTRING, 1, szTypeDw);
  SendDlgItemMessage(hWnd, IDC_TYPE, CB_SETCURSEL, 0, 0);
  SendDlgItemMessage(hWnd, IDC_ROOTKEY, CB_INSERTSTRING, 0, szLocalMachine);
  SendDlgItemMessage(hWnd, IDC_ROOTKEY, CB_SETITEMDATA, 0, HKEY_LOCAL_MACHINE);
  SendDlgItemMessage(hWnd, IDC_ROOTKEY, CB_INSERTSTRING, 1, szUsers);
  SendDlgItemMessage(hWnd, IDC_ROOTKEY, CB_SETITEMDATA, 1, HKEY_USERS);
  SendDlgItemMessage(hWnd, IDC_ROOTKEY, CB_INSERTSTRING, 2, szCurrentUser);
  SendDlgItemMessage(hWnd, IDC_ROOTKEY, CB_SETITEMDATA, 2, HKEY_CURRENT_USER);
  SendDlgItemMessage(hWnd, IDC_ROOTKEY, CB_INSERTSTRING, 3, szCurrentConfig);
  SendDlgItemMessage(hWnd, IDC_ROOTKEY, CB_SETITEMDATA, 3, HKEY_CURRENT_CONFIG);
  SendDlgItemMessage(hWnd, IDC_ROOTKEY, CB_INSERTSTRING, 4, szClassRoot);
  SendDlgItemMessage(hWnd, IDC_ROOTKEY, CB_SETITEMDATA, 4, HKEY_CLASSES_ROOT);
  SendDlgItemMessage(hWnd, IDC_ROOTKEY, CB_SETCURSEL, 0, 0);       
  EnumKey(HKEY_LOCAL_MACHINE, NULL);
  CheckAutoRun();
  break;
  case WM_COMMAND:
  switch ( LOWORD(wParam) )
  {
  case IDC_KEY:
  case IDC_VALUENAME:
  case IDC_VALUE:
  case IDC_TYPE:
  case IDC_KEYLIST:
  case IDC_SUBKEY:
  return TRUE;
  case IDC_ROOTKEY:
  if ( HIWORD(wParam) == CBN_SELENDOK )
  {
  if ( hKey != CB_ERR )
  EnumKey(hKey, NULL);
  }
  return TRUE;
  case IDC_REMOVEVALUE:
  if ( hKey != CB_ERR )
  _RegDelValue(hKey, szKey, szValueName);
  break;
  case IDC_GETVALUE:
  if ( hKey != CB_ERR )
  {
  dwSize = sizeof(szValue);
  RtlZeroMemory(szValue, dwSize);
  if ( ERROR_SUCCESS == _RegQueryValue(hKey, szKey, szValueName, szValue, &dwSize, &dwType))
  {
  if ( dwType == REG_SZ )
  {
  SetDlgItemText(hWnd, IDC_VALUE, szValue);
  SendDlgItemMessage(hWnd, IDC_TYPE, CB_SETCURSEL, 0, 0);
  }
  else if ( dwType == REG_DWORD )
  {
  // 读出来的是一个DWORD值,但是放在了一个字符数组的前4个元素当中
  // 所以必须把这个四个字节取出来合成一个DWORD值
  pB = (BYTE*)&nValue;
  pB[3] = szValue[3];
  pB[2] = szValue[2];
  pB[1] = szValue[1];
  pB[0] = szValue[0];
  SendDlgItemMessage(hWnd, IDC_TYPE, CB_SETCURSEL, 1, 0);
  SetDlgItemInt(hWnd, IDC_VALUE, nValue, FALSE);
  }
  else
  {
  SetDlgItemText(hWnd, IDC_VALUE, szNotSupport);
  }
  }
  }
  break;
  case IDC_SETVALUE:
  if ( hKey != CB_ERR)
  {
  nIndex = SendDlgItemMessage(hWnd, IDC_TYPE, CB_GETCURSEL, 0, 0);
  if ( !nIndex ) // REG_SZ
  {
  GetDlgItemText(hWnd, IDC_VALUE, szValue, 256);
  _RegSetValue(hKey, szKey, szValueName, szValue, REG_SZ, lstrlen(szValue) + 1);
  }
  else // REG_DWORD
  {
  nValue = GetDlgItemInt(hWnd, IDC_VALUE, NULL, FALSE);
  // 我们得到的是一个整形值, 但是这里要求写入一个REG_DWORD类型的值
  // 参数又是字符串, 一个整形值是4个字节,它和字符串不能直接转换,
  // 所以必须把这个整形值的4个字节拆开放在字符串的前4个元素(字节)当中
  pB = (BYTE*)&nValue;
  szValue[3] = pB[3];
  szValue[2] = pB[2];
  szValue[1] = pB[1];
  szValue[0] = pB[0];
  _RegSetValue(hKey, szKey, szValueName, szValue, REG_DWORD, 4);
  }
  }
  break;
  case IDC_CREATESUBKEY:
  if ( hKey != CB_ERR )
  _RegCreateKey(hKey, szKey, szSubKey);
  break;
  case IDC_REMOVESUBKEY:
  if ( hKey != CB_ERR )
  _RegDelSubkey(hKey, szKey, szSubKey);
  break;
  case IDC_AUTORUN:
  if ( HIWORD(wParam) == BN_CLICKED )
  {
  AutoRun(IsDlgButtonChecked(hWinMain, IDC_AUTORUN));
  }
  break;
  default:
  break;
  }
  if ( hKey != CB_ERR)
  EnumKey(hKey, szKey);
  break;       
  default:
  return FALSE;
  }   
  return TRUE;
  }
  void AutoRun(BYTE bAutoRun)
  {
  char    szFileName[MAX_PATH];
  char    szPathName[MAX_PATH];
  char    szKeyAutoRun[] = TEXT("SoftWare\\Microsoft\\Windows\\CurrentVersion\\Run");
  DWORD    dwRtn;
  // 获取可执行文件的全路径
  dwRtn = GetModuleFileName(NULL, szPathName, sizeof(szPathName));
  dwRtn++;
  GetFileName(szPathName, szFileName);
  if ( bAutoRun )
  {
  _RegSetValue(HKEY_LOCAL_MACHINE, szKeyAutoRun, szFileName, szPathName, REG_SZ, dwRtn);
  }
  else
  {
  _RegDelValue(HKEY_LOCAL_MACHINE, szKeyAutoRun, szFileName);
  }
  }
  // 由文件的全路径获取文件的名称
  void GetFileName(char *szFullPath, char *szFileName)
  {
  int nLen, i, j, k;
  if ( szFullPath == NULL || szFileName == NULL )
  return;
  nLen = strlen(szFullPath);
  for ( i = nLen - 1; i >= 0; i--)
  {
  if ( szFullPath == '\\' )
  break;
  }
  k = 0;
  for ( j = i + 1; j < nLen; j++ )
  {
  szFileName[k] = szFullPath[j];
  k++;
  }
  szFileName[k] = 0;
  }
  // 检测本程序是否是开机自动运行,如果是,则将开机自动运行的CheckBox打上勾
  void CheckAutoRun()
  {
  char    szFileName[MAX_PATH];
  char    szPathName[MAX_PATH];
  char    szValue[MAX_PATH];
  char    szKeyAutoRun[] = TEXT("SoftWare\\Microsoft\\Windows\\CurrentVersion\\Run");
  DWORD    dwRtn;
  DWORD    dwSize;
  // 获取可执行文件的全路径
  dwRtn = GetModuleFileName(NULL, szPathName, sizeof(szPathName));
  dwRtn++;
  GetFileName(szPathName, szFileName);
  if ( ERROR_SUCCESS == _RegQueryValue(HKEY_LOCAL_MACHINE, szKeyAutoRun, szFileName, szValue, &dwSize, NULL) )
  {
  CheckDlgButton(hWinMain, IDC_AUTORUN, BST_CHECKED);
  }
  }
  // resource.h
  #define IDD_MAIN                        101
  #define IDC_KEY                         1000
  #define IDC_VALUENAME                   1001
  #define IDC_REMOVEVALUE                 1002
  #define IDC_VALUE                       1003
  #define IDC_TYPE                        1004
  #define IDC_GETVALUE                    1005
  #define IDC_SETVALUE                    1006
  #define IDC_KEYLIST                     1007
  #define IDC_SUBKEY                      1008
  #define IDC_CREATESUBKEY                1009
  #define IDC_REMOVESUBKEY                1010
  #define IDC_ROOTKEY                     1011
  #define IDC_AUTORUN                     1012
  #define IDC_STATIC                      -1
  // reg.rc
  #include "resource.h"
  #include "afxres.h"
  /////////////////////////////////////////////////////////////////////////////
  //
  // Dialog
  //
  IDD_MAIN DIALOG DISCARDABLE  0, 0, 343, 255
  STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
  CAPTION "注册表操作"
  FONT 10, "宋体"
  BEGIN
  LTEXT           "根键:",IDC_STATIC,7,9,32,8
  EDITTEXT        IDC_KEY,53,25,284,14,ES_AUTOHSCROLL
  LTEXT           "键值名:",IDC_STATIC,7,48,31,8
  EDITTEXT        IDC_VALUENAME,53,43,225,14,ES_AUTOHSCROLL
  PUSHBUTTON      "删除键值",IDC_REMOVEVALUE,286,43,50,14
  LTEXT           "键值:",IDC_STATIC,7,68,31,8
  EDITTEXT        IDC_VALUE,53,62,283,14,ES_AUTOHSCROLL
  LTEXT           "类型:",IDC_STATIC,7,88,23,8
  COMBOBOX        IDC_TYPE,53,83,97,52,CBS_DROPDOWNLIST | CBS_SORT |
  WS_VSCROLL | WS_TABSTOP
  PUSHBUTTON      "读取键值",IDC_GETVALUE,169,82,50,14
  PUSHBUTTON      "保存键值",IDC_SETVALUE,232,82,50,14
  LTEXT           "当前键下的所有子键名:",IDC_STATIC,7,105,104,8
  EDITTEXT        IDC_KEYLIST,7,119,329,110,ES_MULTILINE | ES_AUTOVSCROLL |
  ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL | WS_HSCROLL
  LTEXT           "子键名:",IDC_STATIC,7,240,31,8
  EDITTEXT        IDC_SUBKEY,40,234,136,14,ES_AUTOHSCROLL
  PUSHBUTTON      "创建子键",IDC_CREATESUBKEY,191,234,50,14
  PUSHBUTTON      "删除子键",IDC_REMOVESUBKEY,255,234,50,14
  COMBOBOX        IDC_ROOTKEY,53,7,129,59,CBS_DROPDOWNLIST | CBS_SORT |
  WS_VSCROLL | WS_TABSTOP
  LTEXT           "键名:",IDC_STATIC,7,28,23,8
  CONTROL         "开机自动运行本程序",IDC_AUTORUN,"Button",
  BS_AUTOCHECKBOX | WS_TABSTOP,250,7,86,10
  END
  本程序具体演示了如何向注册表中添加、删除一个子键,添加、删除一个键值,以及查询键值等操作,并且演示了如何开机自动运行一个程序。
  其中reg.h中的几个函数可以直接用到你自己的工程当中,简化操作。
分享到:
评论

相关推荐

    windows读写注册表封装库

    将Windows读写注册表封装的非常好,读写都很方便,方便学习c++。

    Delphi 读写注册表的单元(修改后)

    封装 Windows API 函数,用来读写 Windows 注册表的单元文件,可以方便读写各种类型的注册表键值,可以枚举注册表键值,添加删除键值

    Process Monitor v3.2 windows 注册表监控, 文件读写监控

    线程监控, dll监控, 文件监控, 注册表监控 Introduction Process Monitor is an advanced monitoring tool for Windows that shows real-time file system, Registry and process/thread activity. It combines the...

    内置了Delphi读写INI文件,读写注册表,Winsock的Windows助手程序.rar

    一款内置了提取图标、打开程序、显示程序信息、读写INI文件,读写注册表,Winsock等简单的技术的Windows助手程序,适合Delphi初学者学习!相比上一版,本次版本做了如下改动:  1.取消了上一版本使用的VclSkin皮肤控件...

    C++ 操作注册表读写

    这个一个C++ 使用Windows API 操作注册表的代码,注册表操作包括:创建注册表、写入注册表、查询注册表;写入注册表的过程包括:打开注册表、读取注册表、关闭注册表;查询的过程包括:打开注册表、查询注册表、关闭...

    注册表读写实时监控

    Windows注册表监视工具。工作于内核模式,可以实时监控任何程序对注册表的操作,如读写等等。很有用。

    c#读写注册表 文档和源码

    c#读写注册表 文档和源码 内有详细说明和代码

    水滴电脑闹钟 v1.4.0.1 绿色版.rar

    设置时需读写Windows注册表,杀毒软件提示时请允许。 密码保护:提前退出强制休息、打开设置界面、关闭软件操作需输入密码。建议在孩子使用时选中此项。 密码可直接修改,忘记时可删除软件后重新安装。 休息设置:可...

    C/C++读写注册表中二进制数据(代码示例)

    主要介绍了使用Windows API 函数中的RegOpenKeyEx()函数和RegSetValueEx()函数来实现对注册表某项写入二进制键值,需要的朋友可以参考下

    注册表监控

    RegSnap 是一个可以帮助你分析 Windows 注册表的更改的工具. 使用它, 你可以比较已保存的快照, 了解哪个键被修改,删除或者增加,操作简单快捷

    注册表操作类C#源码

    C#语言, 可对WINDOWS注册表进行读写修改等操作。

    一个封装注册表操作代码vc 类

    注册表在Windows系统中有着重要的地位。一个VC封装的注册表操作类,能实现注册表的添加,修改,删除等操作,加人VC工程中就可以用

    自动化测试读写64位操作系统的注册表

    Windows注册表简介 C#修改注册表 32位机器和64位机器注册表的区别 C#程序访问64位操作系统的注册表 自动化测试经常需要修改注册表 很多系统的设置(比如:IE的设置)都是存在注册表中。 桌面应用程序的设置也是...

    如何用注册表方法启用USB

    电脑通过注册表方法禁用USB接口后,可通过双击本注册表文件,可以迅速实现开启USB接口,刷新即可无需重启。

    c++读取、写入、删除 注册表.doc

    c++读取、写入、删除 注册表.doc C++删除注册表 C++读注册表 C++写注册表 #include #include &lt;windows.h&gt; using namespace std;

    Windows环境变量读写

    利用LabVIEW中的注册表模块读取编辑Windows系统中的环境变量

    VB注册表相关源码示例学习43个

    压缩包内共有43个VB操作注册表的源码,极为实用 包括: 进入winxp前发出警告 ...注册表随WINDOWS自动启动 RegQueryValueEx读取注册表的数据 RegQueryValueEx读取软件试用次数 …… ……等共43个文件夹,43个源码实例

    判断windows系统中ip是静态的还是固定的方法

    根据小应用:判断windows系统中ip是静态的还是固定的需求,通过读取注册表进行判断。多网卡时,注意注册表的遍历。程序涉及windows注册表的遍历和读取键值的方法,对于读写注册表具有很好的学习参考。

    300个注册表优化修改文件

    提高光驱的读写能力.reg 提高历史缓冲区的个数.reg 提高软驱的性能.reg 提高显示器刷新频率.reg 停用Windows的文件高速缓存.reg 退出时不保存环境设置.reg 完全禁用系统还原.reg 消除软件显示乱码.reg 修改...

    Delphi编程访问注册表

     第二、明确如何在程序中完成对注册表的读写操作;  第三、你可以将本文所述的方法移植到VC、VB等语言中,举一反三、触类旁通,达到随心所欲修改注册表的目的。  通过实践,你完全有可能编写出象"超级兔子"那样...

Global site tag (gtag.js) - Google Analytics