Windows注册表的读写操作

这篇具有很好参考价值的文章主要介绍了Windows注册表的读写操作。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


本文介绍了Windows注册表的基本知识,以及C++中打开\关闭\查询\修改注册表的常用接口。
注册表的基本知识(本文第1节)参考 https://blog.csdn.net/weixin_45300266/article/details/122359920并作修改。

1 注册表(Registry)介绍

1.1 注册表简介

注册表是windows系统中具有层次结构的核心数据库,储存的数据对windows 和Windows上运行的应用程序和服务至关重要。注册表时帮助windows控制硬件、软件、用户环境和windows界面的一套数据文件。

1.2 注册表位置

windows 注册表的位置:C:\Windows\System32\config 。
Windows注册表的读写操作
以上红框中标注的就是注册表文件了,但是不能直接打开,只能使用注册表编辑器对这些文件进行操作。切记切记,不要轻易尝试删除注册表文件。

1.3 开启/禁用 注册表编辑器

首先,打开注册表,方法为:WIN+R 输入—> “regedit”或“regedit.exe”、“regedt32”或“regedt32.exe” —>回车
Windows注册表的读写操作
如果以上方法均不能打开数据库,那么说明你没有管理员权限,或者注册表被锁定。
权限问题可联系管理员解决,若是注册表被锁定可以使用以下方法进行解锁
1、创建一个文本文件,复制以下文字文本内容(注意开头之后第二行一定要是空行并且不可少),选择另存为,文件类型选择所有文件,文件名称为XX.reg,保存到桌面后,双击打开该文件,点击确定便可。

REGEDIT4
[HKEY_USERS.DEFAULT\Software\Microsoft\Windows\CurrentVersion\Policies\system]
“DisableRegistryTools”=dword:00000000

2、锁定注册表编辑器的方法
创建一个文本文件,复制以下文字文本内容(注意开头之后第二行一定要是空行并且不可少),选择另存为,文件类型选择所有文件,文件名称为SS.reg,保存到桌面后,双击打开该文件,点击确定便可。

Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\System]
“DisableRegistryTools”=dword:00000001

1.4 注册表的结构

注册表中,所有的数据都是通过一种树状结构以键和子键的方式组织起来的,就像磁盘文件系统的目录结构一样。
每个键包含一组特定的信息,每个键的键名都是和它所包含的信息相关联的。注册表的根键共有5个,且全为大写。
Windows注册表的读写操作

Windows注册表的读写操作

键值:
键值由三部分组成: 名称、类型、数据。

键值的类型:
键值类型由常用的6种组成
字符串值(REG_SZ)
二进制值(REG_BINARY)
32位值(4个字节)(REG_DWORD)
64位值(5个字节)(REG_QWORD)
多字符串值(REG_MULTI_SZ)
可扩充字符串值(REG_EXPAND_SZ)

1.5 修改注册表实例

假定我们需要设置一个程序为开机自启动,这可以通过修改注册表实现。
实现原理:windows 提供了专门的开机自启动注册表。每次开启时,它都会在这个注册表键下遍历键值,获取到键值中的程序路径,并创建进程启动程序。因此只需要将需要设置自启动的程序的路径添加到这个注册表中,便可以实现程序开启自启动功能。

常见的开机自启动注册表路径:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
注意:要修改 HKEY_LOCAL_MACHINE 主键的注册表需要管理员权限

现在我们尝试将计算器添加到开机自启动注册表,实现开机自启。
首先,打开注册表编辑器,并复制上述路径,回车后,跳到注册表自启动位置。
Windows注册表的读写操作
然后,新建 键值类型为 REG_SZ的键值,修改名称为 calcNew
Windows注册表的读写操作
最后,选中“calcNew”键值右键修改键值数据为:calc.exe的绝对路径,并点击确定。
Windows注册表的读写操作
启动系统,则可以看到计算器程序已经成功自启动。

2 程序中对注册表的读写操作

2.1 打开和关闭注册表

1.打开注册表键

LONG WINAPI RegOpenKeyEx(
__in HKEY hKey, //主键的名称
__in_opt LPCTSTR lpSubKey,//子键的名称
__reserved DWORD ulOptions, //保留,为0
__in REGSAM samDesired,//指定对键的访问权限
__out PHKEY phkResult //指定打开键的句柄
);

请注意,hKeyParent是一个打开的键(它充当即将打开的子健的父键),或者可以是以下值;
HKEY_CLASSES_ROOT
HKEY_CURRENT_CONFIG
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS

lpSubKey是需要打开的子键的名称。

2.关闭注册表

LONG WINAPI RegCloseKey(
__in HKEY hKey
);

以上接口的使用可以查看本文第3部分。

2.2 创建和删除指定的注册表键

  1. 创建注册表键

​LONG WINAPI RegCreateKeyEx(
HKEY hKey, //主键的名称
LPCTSTR lpSubKey, //子键的名称
DWORD Reserved, //保留,为0
LPTSTR lpClass, //指定此键的类(对象类型), 如果键已经存在,则忽略此参数
DWORD dwOptions, //指定键的特殊选项
REGSAM samDesired, //指定对键的访问权限
LPSECURITY_ATTRIBUTES lpSecurityAttributes, //可设为NULL
PHKEY phkResult, //句柄
LPDWORD lpdwDisposition //可设为NULL

  1. 删除某个注册表键

LONG WINAPI RegDeleteKeyEx(
__in HKEY hKey,
__in LPCTSTR lpSubKey,
__in REGSAM samDesired,
__reserved DWORD Reserved);

2.3 读取和设置指定注册表中某个键值

  1. 读取某个注册表键值

LONG RegQueryValueEx(
HKEY hKey, // 句柄
LPCTSTR lpValueName, // 要查询注册表键值的名字字符串
LPDWORD lpReserved, // 设为0
LPDWORD lpType, // 用于装载取回数据类型的一个变量
LPBYTE lpData, // 用于装载指定值的一个缓冲区
LPDWORD lpcbData // 用于装载lpData缓冲区长度的一个变量

  1. 在注册表某个键下设置指定键值

LONG RegSetValueEx(
HKEY hKey, // 句柄
LPCTSTR lpValueName, // 指向一个字符串的指针,该字符串包含要设置的值的名称
DWORD Reserved, // 保留,设为0
DWORD dwType, // 指定数据类型(字符串:REG_SZ, 数字:REG_DWORD)
CONST BYTE *lpData, // 指向一个缓冲区,该缓冲区包含了欲为指定值名称存储的数据
DWORD cbData // 指定由lpData参数所指向的数据的大小,单位是字节。

2.4 增加和删除注册表键中某个键值

  1. 增加键下某个键值
    这个接口就是上面讲的RegSetValueEx,它既可以设置,也可以新建一个键值。
  2. 删除键下某个键值

LONG WINAPI RegDeleteValue(
__in HKEY hKey,
__in_opt LPCTSTR lpValueName
);

2.5 迭代一个键下的所有子键

迭代一个注册表键下所有子键,需要用到RegQueryInfoKey、RegEnumKeyEx和RegEnumValue。
RegEnumKey可以迭代一个打开键下的所有子键。

LONG WINAPI RegEnumKey(
__in HKEY hKey,
__in DWORD dwIndex,
__out LPTSTR lpName,
__in DWORD cchName
);

RegEnumValue可以迭代一个指定键下所有的键值。

LONG WINAPI RegEnumValue(
__in HKEY hKey,
__in DWORD dwIndex,
__out LPTSTR lpValueName,
__inout LPDWORD lpcchValueName,
__reserved LPDWORD lpReserved,
__out_opt LPDWORD lpType,
__out_opt LPBYTE lpData,
__inout_opt LPDWORD lpcbData
);

下面一个接口,可以取出一个键下所有的子键,以及这个键的所有键值名称。

//获取一个注册表键下面的各个子键名称,以及该键下面所有值名称,根据MSDN实例修改
//parSubKey存储子键名称,parKeyValueName存储键下所有键值名称
void QueryKey(HKEY hKey,std::vector<CString>* parSubKey,std::vector<CString>* parKeyValueName)
{
	TCHAR    pszSubKeyName[MAX_KEY_LENGTH];   // buffer for subkey name
	DWORD    cbName;                   // size of name string 
	TCHAR    pszClass[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  pszValue[MAX_VALUE_NAME];
	DWORD cchValue = MAX_VALUE_NAME;

	// Get the class name and the value count. 
	retCode = RegQueryInfoKey(
		hKey,                    // key handle 
		pszClass,                // 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 (parSubKey)
	{
		for (i = 0; i < cSubKeys; i++)
		{
			cbName = MAX_KEY_LENGTH;
			retCode = RegEnumKeyEx(hKey, i, pszSubKeyName, &cbName,
				NULL, NULL, NULL, &ftLastWriteTime);
			if (retCode == ERROR_SUCCESS)
				parSubKey->push_back(pszSubKeyName);
		}
	}

	// Enumerate the key values. 
	if (parKeyValueName)
	{
		for (i = 0, retCode = ERROR_SUCCESS; i < cValues; i++)
		{
			cchValue = MAX_VALUE_NAME;
			pszValue[0] = _T('\0');
			retCode = RegEnumValue(hKey, i, pszValue, &cchValue,
				NULL, NULL, NULL, NULL);

			if (retCode == ERROR_SUCCESS)
				parKeyValueName->push_back(pszValue);
		}
	}
}

3 注册表读写的一个Demo

这个实例是读取注册表中自启动项,然后增加和删除其中的键值,从而改变自启动的程序。
Windows注册表的读写操作

新建一个基于对话框的MFC工程,名称为SetStartUp,在资源编辑器中增加1个List control和3个按钮,按钮分别对应查询启动项、删除启动项和增加启动项。
Windows注册表的读写操作
在对话框类的头文件中增加

private:
	void FillList();	//填充

	CListCtrl m_wndLst;
	static CString m_sPath;						//启动项的键路径
	std::vector<CString> m_arsStartItemPath;	//保持键值的名称
	std::vector<CString> m_arsStart;			//保持键值的数值

实现文件中增加下列内容。
首先,静态CString变量m_sPath存储注册表自启动键的路径,它的根键在 HKEY_CURRENT_USER中。

#define MAX_KEY_LENGTH 255
#define MAX_VALUE_NAME 16383
CString CSetStartUpDlg::m_sPath = _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");

在OnInitDialog中增加初始化列表控件的代码。

BOOL CSetStartUpDlg::OnInitDialog()
{
//.......省略

	// TODO: 在此添加额外的初始化代码
	m_wndLst.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
	CRect rect;
	m_wndLst.GetClientRect(rect);
	m_wndLst.InsertColumn(0, _T("程序名"), LVCFMT_LEFT, rect.Width() / 3.0, 0);
	m_wndLst.InsertColumn(1, _T("安装路径"), LVCFMT_LEFT, rect.Width()*2.0 / 3.0, 1);

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

填充list control的函数

void CSetStartUpDlg::FillList()
{
	CString sAppName;
	m_wndLst.DeleteAllItems();
	for (int i = 0; i < m_arsStartItemPath.size(); i++)
	{
		m_wndLst.InsertItem(i, m_arsStart[i]);
		m_wndLst.SetItemText(i, 1, m_arsStartItemPath[i]);
	}
}

OnBnClickedBtnShow为显示自启动项的按钮响应函数,注意这里面的对键值的迭代操作(采用函数RegEnumValue)。请特别注意RegOpenKeyEx函数第四个实参需要包括KEY_WOW64_64KEY,因为我Windows系统是64位,这样,无论程序是32位程序还是64位程序,都可以打开64位的注册表视图;没有这个掩码的话,32位的程序只能访问32位的注册表视图,64位的只能访问64位的注册表视图。在其后所有涉及打开注册表的接口中,都应该使用这个掩码位。

void CSetStartUpDlg::OnBnClickedBtnShow()
{
	// TODO: 在此添加控件通知处理程序代码
	m_arsStartItemPath.clear();
	m_arsStart.clear();
	
	HKEY hRegKey;
	if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_CURRENT_USER, m_sPath, NULL, KEY_READ | KEY_WRITE | KEY_WOW64_64KEY, &hRegKey))
		return;

#define _MAX_VALUE_BUF_	2048
	TCHAR  pszValueName[MAX_VALUE_NAME];
	DWORD cchValueName = MAX_VALUE_NAME;
	BYTE pszValue[_MAX_VALUE_BUF_] = {0};
	DWORD dwBufSize = _MAX_VALUE_BUF_;
	int i = 0;
	long lRetCode;
	DWORD dwType;
	while (ERROR_NO_MORE_ITEMS != 
		(lRetCode = RegEnumValue(hRegKey, i++, pszValueName, &cchValueName, NULL, &dwType, pszValue, &dwBufSize)))
	{
		if (ERROR_SUCCESS == lRetCode)
		{
			if (dwType == REG_SZ)
			{
				pszValue[dwBufSize] = '\0';
				m_arsStartItemPath.push_back((TCHAR*)pszValue);
				m_arsStart.push_back(pszValueName);
			}
		}
		dwBufSize = _MAX_VALUE_BUF_;
		cchValueName = MAX_VALUE_NAME;
	}

	RegCloseKey(hRegKey);
	FillList();
}

下面接口为按下“删除启动项”按钮的响应函数,注意这里面的删除键值操作。

void CSetStartUpDlg::OnBnClickedBtnDelItem()
{
	// TODO: 在此添加控件通知处理程序代码
	HKEY hRegKey;
	if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_CURRENT_USER, m_sPath, NULL, KEY_READ | KEY_WRITE | KEY_WOW64_64KEY, &hRegKey))
		return;
	int iSelect = m_wndLst.GetNextItem(-1, LVIS_SELECTED);
	if (-1 != iSelect)
	{
		CString sKeyName = m_wndLst.GetItemText(iSelect, 0);
		m_wndLst.DeleteItem(iSelect);
		RegDeleteValue(hRegKey, sKeyName);
	}
	RegCloseKey(hRegKey);
}

下面接口为单击“新增启动项”响应函数,提示用户选择一个*.exe文件,然后把它放入启动项键下。

void CSetStartUpDlg::OnBnClickedBtnAddStartup()
{
	// szFilters is a text string that includes two file name filters:
	TCHAR szFilters[] = _T("可执行文件 (*.exe)|*.exe|All Files (*.*)|*.*||");
	CFileDialog fileDlg(TRUE, NULL, NULL, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, szFilters);
	if (fileDlg.DoModal() == IDOK)
	{
		CString sPath = fileDlg.GetPathName();

		//将用户选择的文件放到启动项中
		HKEY hRegKey;
		if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_CURRENT_USER, m_sPath, NULL, KEY_READ | KEY_WRITE | KEY_WOW64_64KEY, &hRegKey))
			return;
		CString sAppName = sPath.Mid(sPath.ReverseFind(_T('\\')) + 1);
		if (ERROR_SUCCESS == RegSetValueEx(hRegKey, sAppName, NULL, REG_SZ,
			(const BYTE*)sPath.GetString(), (sPath.GetLength() + 1) * sizeof(TCHAR)))
		{
			int iNew = m_wndLst.InsertItem(m_wndLst.GetItemCount(), sAppName);
			m_wndLst.SetItemText(iNew, 1, sPath);
		}

		RegCloseKey(hRegKey);
	}
}

通过增加以上内容,即可完成这个小工具的制作!文章来源地址https://www.toymoban.com/news/detail-439715.html

到了这里,关于Windows注册表的读写操作的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Windows注册表清理

    伴随着系统运行时间不断增长,我们的电脑 注册表 中累积了许多垃圾文件。这些垃圾文件都是我们平常安装与卸载程序所留下的无用注册表信息,时间一长,垃圾文件与信息越来越多,我们电脑的运行速度越来越慢。 ​ 而且部分软件由于删除方式不对,导致一些残留注册表

    2024年02月08日
    浏览(50)
  • 【Windows基础】注册表

    注册表是Windows操作系统、硬件设备以及客户应用程序得以正常运行和保存设置的 核心\\\"数据库\\\" ,也可以说是一个非常巨大的 树状分层结构 的 数据库系统 注册表记录了用户安装在计算机上的软件和每个程序的相互关联信息,它包括了计算机的硬件配置,包括自动配置的即插

    2024年02月04日
    浏览(56)
  • windows注册表启动项

    实际应急响应案例时,发现很多非常规的启动项以及ARK工具未涵盖的启动项,故收集资料对注册表有关的启动项进行总结,以后处置病毒无从下手时可以考虑从启动项排查。 1.Load注册键 介绍该注册键的资料不多,实际上它也能够自动启动程序。位置: HKEY_CURRENT_USERSoftwareMi

    2024年02月05日
    浏览(49)
  • 【Windows注册表内容详解】

    一、什么是注册表 注册表是windows操作系统、硬件设备以及客户应用程序得以正常运行和保存设置的核心“数据库”,也可以说是一个非常巨大的树状分层结构的数据库系统。 注册表记录了用户安装在计算机上的软件和每个程序的相互关联信息,它包括了计算机的硬件配置,

    2024年02月09日
    浏览(42)
  • Windows技巧之注册表

    介绍 注册表是Windows操作系统中的一个核心数据库,其中存放着各种参数,直接控制着Windows的启动、硬件驱动程序的装载以及一些Windows应用程序的运行,从而在整个系统中起着核心作用。这些作用包括了软、硬件的相关配置和状态信息,比如注册表中保存有应用程序和资源管

    2023年04月08日
    浏览(44)
  • Unity 注册表操作

    内容将会持续更新,有错误的地方欢迎指正,谢谢!   Unity 注册表操作       TechX 坚持将创新的科技带给世界! 拥有更好的学习体验 —— 不断努力,不断进步,不断探索 TechX —— 心探索、心进取! 助力快速掌握 Registry 注册表操作 为初学者节省宝贵的学习时间,避免困惑

    2024年02月02日
    浏览(38)
  • 注册表操作01

    注册表的组织方式主要分为 根键 、 子键 和 键值项 三部分。 (1)根键,可以把它们理解成磁盘的五个分区。 1.HKEY_CLASSES_ROOT; 2.HKEY_CURRENT_USER; 3.HKEY_LOCAL_MACHINE; 4.HKEY_USERS; 5.HKEY_CURRENT_CONFIG; (2)子键,可以有多个子键和键值项。 (3)键值项由三部分组成,分别为:名称

    2024年02月03日
    浏览(38)
  • 【运维】Windows 通过注册表禁用服务

    【运维】Windows 通过注册表禁用服务 以这个服务为例子 Windows Push Notifications User Service 双击查看服务名称 WpnUserService_671f3   打开注册表 HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServices{服务名称} HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesWpnUserService_671f3 选中  将右侧的 Start 改为4  十六

    2024年02月12日
    浏览(38)
  • DOS下操作注册表

    下面以彻底关闭window10 操作为背景,通过命令行对注册表进行操作. 执行命令需要管理员权限 如果目录中存在空格 需要双引号 hklm为 HKEY_LOCAL_MACHINE 的缩写 查询: QUERY 添加: ADD 删除: DELETE 复制: COPY 保存: SAVE /t 表示 类型 如下 /v 表示 键名 效果如下图 /d 表示 键值 效果如

    2024年02月10日
    浏览(42)
  • 从Windows注册表中查看系统版本

    Windows 注册表项 键值 CurrentVersion 所显示的数据内容所对应的系统版本: Current Number 操作系统: 5 Windows 2000 5.1 Windows XP 5.2 Windows XP 64bit 5.2 Windows Server 2003 / R2 6 Windows Vista / Windows Server 2008 6.1 Windows 7 / Windows Server 2008 R2 6.2 Windows 8 / Windows Server 2012 6.3 Windows 8.1 / 10 / 11 / Windows Server

    2024年02月04日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包