WindowsAPI查缺补漏-INI配置文件与注册表操作
WindowsAPI查缺补漏-INI配置文件与注册表操作
碎碎念
INI文件即初始化文件,如Windows目录中Win.ini保存桌面设置和与应用程序运行有关信息,System.ini保存于硬件配置有关的信息,还有Control.ini等,但他们被映射到注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\Current Version\IniFileMapping中。单个INI文件大小不得超过64KB,注释以“;”开头且必须独占一行。键名不能存在“;”但键值可存在,键名不能为多行文本。
NT系统注册表由Windows\system32\Config目录中多个文件构成,文件运行时这些文件被系统独占,无任何权限(甚至是读),只能通过Windows提供的接口进行操作。常见键值数据类型有:
键值数据类型 | 含义 |
---|---|
REG_SZ | |
REG_DWORD | |
REG_QWORD | |
REG_BINARY | |
REG_MULTI_SZ | 字符串序列,每个字符串以1个\0结尾,最后一个以2个\0结尾 |
REG_EXPAND_SZ | 包含对环境变量的为扩展引用的字符串 |
REG_DWORD_LITTLE_ENDIAN | |
REG_DWORD_BIG_ENDIAN | |
REG_QWORD_LITTLE_ENDIAN | |
REG_LINK | 包含符号链接的目标路径的字符串 |
REG_NONE | 没定义的 |
注册表中有5个根键,其中HKEY_LOCAL_MACHINE和HEKY_USERS为两个大根键,其他根键都由他俩映射出来,如HEKY_CLASSES_ROOT是HEKY_LOCAL_MACHINE\SOFTWARE\Classes子键的映射。每个根键介绍有:
根键 | 含义 |
---|---|
HKEY_LOCAL_MACHINE | 系统和软件的设置,针对所有Windows系统用户 |
HKEY_USERS | 默认用户、当前登录用户与软件等信息。如未来将被创建的新用户根键默认用户.DEFAULT子键配置信息生成自己的配置文件,包括环境、屏幕、声音等 |
HKEY_CLASSES_ROOT | 系统中所有数据文件信息,主要为不同文件名后缀文件和与之关联的应用程序。 |
HKEY_CURRENT_USER | 当前用户信息 |
HKEY_CURRENT_CONFIG | 硬件配置文件,很少使用 |
键值数据不要大于2KB,否则影响效率。
INI配置文件
WritePrivateProfileString
在指定INI文件指定小节创建、更新或删除键值对,或删除整个小节:
1 | BOOL WINAPI WritePrivateProfileString( |
当lpAppName或lpKeyName不存在则自动创建该小节/键名。lpKeyName为NULL则删除lpAppName指定的小节。lpString为NULL则删除lpKeyName指定键。lpFileName文件不存在自动创建,但指定目录必须存在,不含完整路径时从Windows目录中搜索。
GetPrivateProfileString
获取指定INI文件指定小节键名对应的键值字符串,还可以枚举指定INI文件中所有小节名称,还可以枚举指定INI文件指定小节名称中所有键名。
1 | DWORD WINAPI GetPrivateProfileString( |
当lpAppName为NULL时将INI中所有小节名复制到lpReturnedString缓冲区中,每个小节名后以0结尾,最后一个小节名后有2个0。当lpKeyName为NULL时将指定节中所有键名复制到lpReturnedString缓冲区中,每个键名后以0结尾,最后一个键名后有2个0。当INI中没有lpKeyName时将lpDefault复制到lpReturnedString缓冲区。lpFileName如不包含完整路径则在Windows目录中搜索。
返回复制到缓冲区中字符数,不含终止空字符。求键值时缓冲区大小不足则返回nSize-1。枚举时缓冲区大小不足返回nSize-2。
GetPrivateProfileInt
同上,UINT型键值:
1 | UINT WINAPI GetPrivateProfileInt( |
GetPrivateProfileSectionNames
枚举指定INI中所有小节名称,用法同GetPrivateProfileString
。
1 | DWORD WINAPI GetPrivateProfileSectionNames( |
GetPrivateProfileSection
枚举指定INI文件指定小节中所有键值对,用法同GetPrivateProfileString
。
1 | DWORD WINAPI GetPrivateProfileSection( |
WritePrivateProfileSection
向指定INI指定小节批量写入键值对:
1 | BOOL WINAPI WritePrivateProfileSection( |
原键值对将被全部覆盖删除,lpString中每个键值以0结尾,最后一个键值对以2个0结尾。lpString理所当然的最大只能64KB。
注册表操作
RegOpenKeyEx
打开一个子键并获取一个子键句柄:
1 | LONG WINAPI RegOpenKeyEx( |
lpSubKey子键可以是多层目录,hKey为根键时用常量HKEY_LOCAL_MACHINE等。sammDesired有:
枚举值 | 访问权限 |
---|---|
KEY_QUERY_VALUE | 查询键值项数据 |
KEY_CREATE_SUB_KEY | 创建下一层子键 |
KEY_ENUMERATE_SUB_KEYS | 枚举子键 |
KEY_NOTIFY | 子键及下面子键发生更改时接收到通知 |
KEY_SET_VALUE | 创建、修改和删除键值项 |
KEY_READ/KEY_EXECUTE | STANDARD_RIGHTS_READ、KEY_QUERY_VALUE、KEY_ENUMERATE_SUB_KEYS、KEY_NOTIFY |
KEY_WRITE | STANDARD_RIGHTS_WRITE、KEY_SET_VALUE、KEY_CREATE_SUB_KEY |
KEY_WOW64_32KEY | 应用程序在32位注册表视图上运行 |
KEY_WOW64_64KEY | 应用程序在64位注册表视图上运行 |
KEY_ALL_ACCESS | STANDARD_RIGHTS_REQUIRED、KEY_QUERY_VALUE、KEY_SET_VALUE、KEY_CREATE_SUB_KEY、KEY_ENUMERATE_SUB_KEYS、KEY_NOTIFY、KEY_CREATE_LINK |
RegCloseKey
关闭子键句柄:
1 | LONG WINAPI RegCloseKey( |
RegCreateKeyEx
创建一个子键并返回子键句柄,已存在则打开,一些参数同RegOpenKeyEx
。注意不能在两个大根键下创建直系子键。
1 | LONG WINAPI RegCreateKeyEx( |
dwOptions有:
枚举值 | 含义 |
---|---|
REG_OPTION_NON_VOLATILE | 子键在系统重启时保留在注册表中 |
REG_OPTION_VOLATILE | 子键保存在内存中,系统重启即消失 |
REG_OPTION_BACKUP_RESTORE | 忽略samDesired,尝试用备份或还原子键所需访问权限打开子键 |
lpdwDisposition有:
枚举值 | 含义 |
---|---|
REG_CREATED_NEW_KEY | 子键不存在且已经被创建 |
REG_OPENED_EXISTING_KEY | 子键已存在,直接打开的 |
例如:
1 | HKEY hKey; |
RegDeleteKey
删除一个子键和该子键中所有键值项,要删除的子键下必须无子键。要递归删除子键用RegDeleteTree
或SHDeleteKey
,这俩与RegDeleteKey
参数完全一样。
1 | LONG WINAPI RegDeleteKey( |
RegSetValueEx
在指定子键中创建或设置键值项:
1 | LONG WINAPI RegSetValueEx( |
lpValueName不存在则创建,已存在则更改键值,为空字符或NULL则创建或设置子键默认键。lpData要求包含1个或2个终止\0。
RegQueryValueEx
获取指定子键中指定键名的键值数据或键值数据类型:
1 | LONG WINAPI RegQueryValueEx( |
hKey为空字符串或NULL表示子键中默认键。
RegGetValue
同RegQueryValueEx
,但不需要子键句柄:
1 | LONG WINAPI RegGetValue( |
dwFlags可取值有:
枚举值 | 含义 |
---|---|
RRT_RT_ANY | |
RRT_RT_REG_SZ | |
RRF_RT_REG_DWORD | |
RRF_RT_REG_QWORD | |
RRT_RT_REG_BINARY | |
RRT_RT_DWORD | |
RRT_RT_QWORD | |
RRT_RT_REG_EXPAND_SZ | |
RRT_RT_REG_MULTI_SZ | |
RRF_RT_REG_NONE | |
RRF_NOEXPAND | 数据类型为REG_EXPAND_SZ则不要自动扩展环境变量字符串 |
RRF_ZEROONFAILURE | 当pvData不为NULL则函数执行失败时将缓冲区清零 |
RRF_SUBKEY_WOW6464KEY | 当lpSubKey不为NULL则打开lpSubKey指定有KEY_WOW64_64KEY访问权限的子键 |
RRF_SUBKEY_WOW6432KEY | 当lpSubKey不为NULL则打开lpSubKey指定有KEY_WOW64_32KEY访问权限的子键 |
例如:
1 | RegGetValue(HKEY_CURRENT_USER, lpSubKey, lpValueNameX, RRF_RT_ANY, NULL, &dwX, &dwcbData); |
RegDeleteValue
删除指定子键中指定键值项:
1 | LONG WINAPI RegDeleteValue( |
RegEnumKeyEx
枚举指定子键下所有子键名称、类类型和最后写入时间:
1 | LONG RegEnumKeyEx( |
dwIndex枚举时循环调用,第一次设置为0,后续每次增加1,直到函数返回ERROR_NO_MORE_ITEMS。
例如枚举方式:
1 | DWORD dwIndex; |
RegEnumValue
枚举指定子键下所有键值项,部分参数同RegEnumKeyEx
。
1 | LONG WINAPI RegEnumValue( |
缓冲区过小时函数返回ERROR_MOR_DATA,lpcbData指向变量中返回所需缓冲区大小。当lpData为NULL时表示获取所需缓冲区大小,单位字节,返回在lpcbData指向DWORD变量中,这时函数返回ERROR_SUCCESS。
例如枚举方式:
1 | DWORD dwIndex; |
RegQueryInfoKey
查询指定子键相关信息,如一个子键下子键数量、键值项数量、子键名称、键名字符串最大长度、键值数据最大长度等。
1 | LONG WINAPI RegQueryInfoKey( |
应用:程序开机自动运行
下面路径选一个子键创建键值项,键值数据为程序完整路径,选后两个路径只运行1次:
1 | HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run |
例如:
1 | HKEY hKey; |
注册表重定向不用管。
应用:文件关联程序
在注册表HKEY_CLASSES_ROOT根键下新建2个子键。第1个子键为“.扩展名”,该子键下设置一个默认键,默认键键值数据类型为REG_SZ,键值数据是根键下新建的第2个子键名。对于第2个子键,当默认动作是“打开”时继续在该子键中创建“shell\open\command”子键,该子键下设置默认键,键值数据类型是REG_SZ或REG_EXPAND_SZ,键值数据为可执行文件完整路径;当默认动作是“打印”时继续在该子键中创建“shell\print\command”子键,默认键设置为执行打印操作的可执行文件名。
例如.txt文件用notepad.exe打开:HKEY_CLASSES_ROOT\.txt子键默认键键值为“txtfile”,HKEY_CLASSES_ROOT\txtfile\shell\open\command子键默认键键值为“%System Root%\system32\NOTEPAD.EXE %1”。