Win32编程

9、注册表

1、课程目标

  1. 理解Windows注册表结构
  2. 掌握注册表操作API
  3. 学会实现程序持久化
  4. 掌握注册表监控技术

2、名词解释

术语 英文 说明
根键 Root Key HKEY_LOCAL_MACHINE等顶级键
子键 Subkey 注册表路径中的目录
Value 键下的数据项
句柄 HKEY 注册表键的句柄

3、代码实现

3.1、示例1:基本注册表操作

#include <windows.h>
#include <stdio.h>

void RegistryDemo() {
    HKEY hKey;
    
    // 创建/打开键
    LONG result = RegCreateKeyEx(
        HKEY_CURRENT_USER,
        TEXT("Software\\MyApp"),
        0, NULL,
        REG_OPTION_NON_VOLATILE,
        KEY_ALL_ACCESS,
        NULL,
        &hKey,
        NULL
    );
    
    if (result == ERROR_SUCCESS) {
        // 写入字符串值
        TCHAR value[] = TEXT("Hello Registry");
        RegSetValueEx(hKey, TEXT("Setting1"), 0, REG_SZ, 
                      (BYTE*)value, sizeof(value));
        
        // 写入DWORD值
        DWORD dwValue = 12345;
        RegSetValueEx(hKey, TEXT("Number"), 0, REG_DWORD,
                      (BYTE*)&dwValue, sizeof(dwValue));
        
        // 读取值
        TCHAR readBuf[256];
        DWORD bufSize = sizeof(readBuf);
        RegQueryValueEx(hKey, TEXT("Setting1"), NULL, NULL,
                        (BYTE*)readBuf, &bufSize);
        printf("Read: %ls\n", readBuf);
        
        RegCloseKey(hKey);
    }
}

3.2、示例2:枚举注册表

#include <windows.h>
#include <stdio.h>

void EnumerateRegistry(HKEY hRoot, const TCHAR* subKey) {
    HKEY hKey;
    
    if (RegOpenKeyEx(hRoot, subKey, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
        return;
    
    // 枚举子键
    TCHAR keyName[256];
    DWORD index = 0;
    DWORD nameLen;
    
    printf("Subkeys:\n");
    while (1) {
        nameLen = 256;
        if (RegEnumKeyEx(hKey, index++, keyName, &nameLen, 
                         NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
            break;
        printf("  %ls\n", keyName);
    }
    
    // 枚举值
    index = 0;
    DWORD type;
    printf("Values:\n");
    while (1) {
        nameLen = 256;
        if (RegEnumValue(hKey, index++, keyName, &nameLen,
                         NULL, &type, NULL, NULL) != ERROR_SUCCESS)
            break;
        printf("  %ls (Type: %d)\n", keyName, type);
    }
    
    RegCloseKey(hKey);
}

3.3、示例3:开机自启动

#include <windows.h>

void SetAutoStart(BOOL enable) {
    HKEY hKey;
    const TCHAR* runKey = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run");
    
    if (RegOpenKeyEx(HKEY_CURRENT_USER, runKey, 0, KEY_SET_VALUE, &hKey) 
        == ERROR_SUCCESS) {
        
        if (enable) {
            TCHAR path[MAX_PATH];
            GetModuleFileName(NULL, path, MAX_PATH);
            RegSetValueEx(hKey, TEXT("MyApp"), 0, REG_SZ,
                          (BYTE*)path, (lstrlen(path) + 1) * sizeof(TCHAR));
        } else {
            RegDeleteValue(hKey, TEXT("MyApp"));
        }
        
        RegCloseKey(hKey);
    }
}

3.4、示例4:注册表变更通知

#include <windows.h>
#include <stdio.h>

void WatchRegistry() {
    HKEY hKey;
    
    if (RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Software"), 
                     0, KEY_NOTIFY, &hKey) != ERROR_SUCCESS)
        return;
    
    HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    
    // 注册通知
    RegNotifyChangeKeyValue(
        hKey,
        TRUE,           // 监控子键
        REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET,
        hEvent,
        TRUE            // 异步
    );
    
    printf("Waiting for registry change...\n");
    WaitForSingleObject(hEvent, INFINITE);
    printf("Registry changed!\n");
    
    CloseHandle(hEvent);
    RegCloseKey(hKey);
}

4、课后作业

  1. 基础练习:实现程序配置的保存和读取
  2. 自启动:实现添加/删除开机启动项
  3. 注册表监控:实时监控注册表变化
  4. 安全分析:查找并分析恶意软件常用的注册表位置