Windows API 教程(十) 注册表操作

注册表在系统中也是一个很重要的部分。通过 win + R -> regedit 可以调出系统自带的注册表编辑
regedit

可以看到系统常用的注册表有五个大类:

名称 描述
HKEY_CLASSES_ROOT 用于存储文档类型(type or classes)及其相关联的特性(如图标、打开方式等)。该类注册表中的信息常用于 Shell 和 COM 应用程序。
HKEY_CURRENT_USER 用于存储当前用户的偏好(preferences)设置。其中包括当前用户的环境变量、项目组数据、颜色、字体、网络连接、应用程序偏好。
HKEY_LOCAL_MACHINE

存储计算机的物理状态,包括总线类型数据、系统内存、已安装的硬件和软件。

HKEY_USERS 存储用于新注册用户的默认配置以及当前用户的配置。
HKEY_CURRENT_CONFIG

包含本地计算机系统的当前硬件简介信息。其中保存的信息仅描述当前硬件配置和标准配置之间的差异. 标准硬件配置的信息保存在 HKEY_LOCAL_MACHINESoftwareSystem 键之中.

HKEY_CURRENT_CONFIGHKEY_LOCAL_MACHINESystemCurrentControlSetHardware ProfilesCurrent 的别名.

更多信息,详见 注册表预定义键(Predefined Keys)

RegOpenKeyEx

打开已存在的注册表项,更多信息详见 RegOpenKeyEx On MSDN

函数原型

LONG WINAPI RegOpenKeyEx(
  _In_        HKEY hKey,        // 要打开的键的句柄
  _In_opt_    LPCTSTR lpSubKey, // 其子项
  _Reserved_  DWORD ulOptions,  // 保留位,无用,请无视
  _In_        REGSAM samDesired,// 打开权限
  _Out_       PHKEY phkResult   // 返回打开的句柄
);

参数

参数一 hKey (输入参数)
可以传入已存在的注册表句柄(HKEY类型),也可以传入默认存在的项如:HKEY_CLASSES_ROOTHKEY_CURRENT_USERHKEY_LOCAL_MACHINEHKEY_USERSHKEY_CURRENT_CONFIG

参数二 lpSubKey (输入参数、可选)

子项字符串,可不填。如果有填写的话,那么久相当于打开 “hKeylpSubKey” (参数一与参数二拼接起来) 的注册表项。

参数三 ulOptions (保留参数)

保留参数,必须填 0。

参数四 samDesired (输入参数)

打开的注册表项句柄的权限。常见如下:

权限名 描述
KEY_READ (0x20019) 读取权限
KEY_WRITE (0x20006) 写入权限
KEY_SET_VALUE (0x0002) 创建、删除或修改
KEY_QUERY_VALUE (0x0001) 查询值
KEY_CREATE_LINK (0x0020) 系统保留(无用)
KEY_CREATE_SUB_KEY (0x0004) 注册键和创建子键
KEY_ENUMERATE_SUB_KEYS (0x0008) 遍历子键
KEY_EXECUTE (0x20019) 相当于KEY_READ
KEY_NOTIFY (0x0010)
KEY_WOW64_32KEY (0x0200)
KEY_WOW64_64KEY (0x0100)
KEY_ALL_ACCESS (0xF003F) 所有权限

详细请参见 MSDN:注册表项的安全和访问权限

参数五 phkResult (输出参数)

返回输出的句柄。

返回值

成功返回 ERROR_SUCCESS 即 0,失败则返回错误码。可以使用 FormatMessage 函数读取相应错误码的信息。

RegCreateKey

创建注册表项,详见 RegCreateKey on MSDN

LONG WINAPI RegCreateKey(
  _In_      HKEY hKey,          // 创建在哪个注册表项之下
  _In_opt_  LPCTSTR lpSubKey,   // 项名
  _Out_     PHKEY phkResult     // 返回创建的句柄
);

参数

不赘述,不明的同学可以参见稍后的例子。

返回值

同 RegOpenKeyEx 的返回值描述。

创建注册表项实例

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

void showErrorText(DWORD error_num);

int main()
{
    HKEY hKey;
    HKEY subKey;
    DWORD result;
    char sname[] = "Write some thing as you like"; // 随便写点什么

    //打开注册表, HKEY_CURRENT_USERSoftware
    result = RegOpenKeyEx(
                 HKEY_CURRENT_USER, "Software", // 打开
                 0,              // 保留参数必须填 0
                 KEY_WRITE,      // 打开权限,写入
                 &hKey           // 打开之后的句柄
             );

    if (result == ERROR_SUCCESS)
    {
        printf("open success!n");
    }
    else
    {
        printf("open failed!n");
        showErrorText(result);
    }

    // 添加注册表项, 即 HKEY_CURRENT_USERSoftwareAnywayCompany
    RegCreateKey(hKey, "AnywayCompany", &subKey);

    // 设置 HKEY_CURRENT_USERSoftwareAnywayCompanyName 的值
    result = RegSetValueEx(
                 subKey,
                 "Name",         // Name字段
                 0,              // 保留参数必须填 0
                 REG_SZ,         // 键值类型为字符串
                 (const unsigned char *)sname, // 字符串首地址
                 sizeof(sname)   // 字符串长度
             );

    if (result == ERROR_SUCCESS)
    {
        printf("set success!n");
    }
    else
    {
        printf("set failed!n");
        showErrorText(result);
    }

    //关闭注册表:
    RegCloseKey(hKey);
    // 暂停
    system("pause");
    return 0;
}

/*
 * 根据错误码输出错误信息
 */
void showErrorText(DWORD error_num)
{
    char *msg = NULL;
    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        error_num,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 使用默认语言
        (LPSTR)&msg,
        0,
        NULL
    );

    printf("Error code %d: ", error_num);
    if (msg == NULL)
        printf("%sn", "Unknown error");
    else
        printf("%sn", msg);
}

截图:

PS:打开 HKEY_CURRENT_USER 中的项来操作是不需要管理员权限的。

RegDeleteValue

删除某个注册表项的值,更多信息详见 RegDeleteValue on MSDN

LONG WINAPI RegDeleteValue(
  _In_      HKEY hKey,          // 要删除目标注册表项的主体
  _In_opt_  LPCTSTR lpValueName // 具体要删除的值
);

删除注册表项值的实例

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

void showErrorText(DWORD error_num);

int main()
{
    HKEY hKey;
    HKEY subKey;
    DWORD result;
    char sname[] = "Write some thing as you like"; // 随便写点什么

    //打开注册表
    result = RegOpenKeyEx(
                 // 打开 HKEY_CURRENT_USERSoftwareAnywayCompany
                 HKEY_CURRENT_USER, "Software\AnywayCompany", 
                 0,              // 保留参数必须填 0
                 KEY_WRITE,      // 打开权限,写入
                 &hKey           // 打开之后的句柄
             );

    if (result == ERROR_SUCCESS)
    {
        printf("open success!n");
    }
    else
    {
        printf("open failed!n");
        showErrorText(result);
    }

    // 删除 HKEY_CURRENT_USERSoftwareAnywayCompany 下的 Name
    result = RegDeleteValue(hKey, "Name");

    if (result == ERROR_SUCCESS)
    {
        printf("delete success!n");
    }
    else
    {
        printf("delete failed!n");
        showErrorText(result);
    }

    //关闭注册表:
    RegCloseKey(hKey);
    // 暂停
    system("pause");
    return 0;
}

/*
 * 根据错误码输出错误信息
 */
void showErrorText(DWORD error_num)
{
    char *msg = NULL;
    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        error_num,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 使用默认语言
        (LPSTR)&msg,
        0,
        NULL
    );

    printf("Error code %d: ", error_num);
    if (msg == NULL)
        printf("%sn", "Unknown error");
    else
        printf("%sn", msg);
}

RegDeleteKey

删除注册表中的某个键, RegDeleteKey on MSDN

LONG WINAPI RegDeleteKey(
  _In_  HKEY hKey,          // 要删除目标注册表项的主体
  _In_  LPCTSTR lpSubKey    // 具体要删除的键
);

删除注册表项键的实例

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

void showErrorText(DWORD error_num);

int main()
{
    HKEY hKey;
    HKEY subKey;
    DWORD result;
    char sname[] = "Write some thing as you like"; // 随便写点什么

    //打开注册表
    result = RegOpenKeyEx(
                 // 打开 HKEY_CURRENT_USERSoftwareAnywayCompany
                 HKEY_CURRENT_USER, "Software", 
                 0,              // 保留参数必须填 0
                 KEY_WRITE,      // 打开权限,写入
                 &hKey           // 打开之后的句柄
             );

    if (result == ERROR_SUCCESS)
    {
        printf("open success!n");
    }
    else
    {
        printf("open failed!n");
        showErrorText(result);
    }

    // 删除 HKEY_CURRENT_USERSoftwareAnywayCompany
    result = RegDeleteKey(hKey, "AnywayCompany");

    if (result == ERROR_SUCCESS)
    {
        printf("delete success!n");
    }
    else
    {
        printf("delete failed!n");
        showErrorText(result);
    }

    //关闭注册表:
    RegCloseKey(hKey);
    // 暂停
    system("pause");
    return 0;
}

/*
 * 根据错误码输出错误信息
 */
void showErrorText(DWORD error_num)
{
    char *msg = NULL;
    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        error_num,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 使用默认语言
        (LPSTR)&msg,
        0,
        NULL
    );

    printf("Error code %d: ", error_num);
    if (msg == NULL)
        printf("%sn", "Unknown error");
    else
        printf("%sn", msg);
}

列举某个注册表项之下的所有子项实例

内容有些复杂,不过平常都是直接 copy 这个 RegCloseKey 函数过去用,大家知道去哪里 copy 就行了。

// 出处:http://msdn.microsoft.com/en-us/library/ms724256(v=vs.85).aspx
// QueryKey - 列举目标注册表项之下关联的子项
//     hKey - Key whose subkeys and values are to be enumerated.

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

#define MAX_KEY_LENGTH 255
#define MAX_VALUE_NAME 16383

void QueryKey(HKEY hKey)
{
    TCHAR    achKey[MAX_KEY_LENGTH];   // buffer for subkey name
    DWORD    cbName;                   // size of name string
    TCHAR    achClass[MAX_PATH] = TEXT("");  // buffer for class name
    DWORD    cchClassName = MAX_PATH;  // size of class string
    DWORD    cSubKeys = 0;             // number of subkeys
    DWORD    cbMaxSubKey;              // longest subkey size
    DWORD    cchMaxClass;              // longest class string
    DWORD    cValues;              // number of values for key
    DWORD    cchMaxValue;          // longest value name
    DWORD    cbMaxValueData;       // longest value data
    DWORD    cbSecurityDescriptor; // size of security descriptor
    FILETIME ftLastWriteTime;      // last write time

    DWORD i, retCode;

    TCHAR  achValue[MAX_VALUE_NAME];
    DWORD cchValue = MAX_VALUE_NAME;

    // Get the class name and the value count.
    retCode = RegQueryInfoKey(
                  hKey,                    // key handle
                  achClass,                // buffer for class name
                  &cchClassName,           // size of class string
                  NULL,                    // reserved
                  &cSubKeys,               // number of subkeys
                  &cbMaxSubKey,            // longest subkey size
                  &cchMaxClass,            // longest class string
                  &cValues,                // number of values for this key
                  &cchMaxValue,            // longest value name
                  &cbMaxValueData,         // longest value data
                  &cbSecurityDescriptor,   // security descriptor
                  &ftLastWriteTime);       // last write time

    // Enumerate the subkeys, until RegEnumKeyEx fails.

    if (cSubKeys)
    {
        printf( "nNumber of subkeys: %dn", cSubKeys);

        for (i = 0; i < cSubKeys; i++)
        {
            cbName = MAX_KEY_LENGTH;
            retCode = RegEnumKeyEx(hKey, i,
                                   achKey,
                                   &cbName,
                                   NULL,
                                   NULL,
                                   NULL,
                                   &ftLastWriteTime);
            if (retCode == ERROR_SUCCESS)
            {
                printf(TEXT("(%d) %sn"), i + 1, achKey);
            }
        }
    }

    // Enumerate the key values.

    if (cValues)
    {
        printf( "nNumber of values: %dn", cValues);

        for (i = 0, retCode = ERROR_SUCCESS; i < cValues; i++)
        {
            cchValue = MAX_VALUE_NAME;
            achValue[0] = '\0';
            retCode = RegEnumValue(hKey, i,
                                   achValue,
                                   &cchValue,
                                   NULL,
                                   NULL,
                                   NULL,
                                   NULL);

            if (retCode == ERROR_SUCCESS )
            {
                printf(TEXT("(%d) %sn"), i + 1, achValue);
            }
        }
    }
}

int main(void)
{
    HKEY hTestKey;

    if ( RegOpenKeyEx(
                // 打开 HKEY_CURRENT_USERSOFTWARE\Microsoft
                HKEY_CURRENT_USER, TEXT("SOFTWARE\Microsoft"),
                0,
                KEY_READ,
                &hTestKey) == ERROR_SUCCESS
       )
    {
        // 如果打开成功, 则遍历其下的子项
        QueryKey(hTestKey);
    }

    RegCloseKey(hTestKey);

    system("pause");
}

你可能感兴趣的:

文章索引

上一讲: Windows API 教程(九) 网络编程

Advertisements

1 thought on “Windows API 教程(十) 注册表操作

  1. 博主快快更新剩余的部分吧,万分期待!!
    Windows API 教程(十一) 系统服务
    Windows API 教程(十二) 进程间通信
    Windows API 教程(十三) 进程线程同步

发表评论

Fill in your details below or click an icon to log in:

WordPress.com 徽标

You are commenting using your WordPress.com account. Log Out /  更改 )

Google+ photo

You are commenting using your Google+ account. Log Out /  更改 )

Twitter picture

You are commenting using your Twitter account. Log Out /  更改 )

Facebook photo

You are commenting using your Facebook account. Log Out /  更改 )

Connecting to %s