Windows注册表的读写操作

news2024/11/27 14:43:18

目录

  • 1 注册表(Registry)介绍
    • 1.1 注册表简介
    • 1.2 注册表位置
    • 1.3 开启/禁用 注册表编辑器
    • 1.4 注册表的结构
    • 1.5 修改注册表实例
  • 2 程序中对注册表的读写操作
    • 2.1 打开和关闭注册表
    • 2.2 创建和删除指定的注册表键
    • 2.3 读取和设置指定注册表中某个键值
    • 2.4 增加和删除注册表键中某个键值
    • 2.5 迭代一个键下的所有子键
  • 3 注册表读写的一个Demo

本文介绍了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 。
在这里插入图片描述
以上红框中标注的就是注册表文件了,但是不能直接打开,只能使用注册表编辑器对这些文件进行操作。切记切记,不要轻易尝试删除注册表文件。

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

首先,打开注册表,方法为:WIN+R 输入—> “regedit”或“regedit.exe”、“regedt32”或“regedt32.exe” —>回车
在这里插入图片描述
如果以上方法均不能打开数据库,那么说明你没有管理员权限,或者注册表被锁定。
权限问题可联系管理员解决,若是注册表被锁定可以使用以下方法进行解锁
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个,且全为大写。
在这里插入图片描述

在这里插入图片描述

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

键值的类型:
键值类型由常用的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 主键的注册表需要管理员权限

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

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

这个实例是读取注册表中自启动项,然后增加和删除其中的键值,从而改变自启动的程序。
在这里插入图片描述

新建一个基于对话框的MFC工程,名称为SetStartUp,在资源编辑器中增加1个List control和3个按钮,按钮分别对应查询启动项、删除启动项和增加启动项。
在这里插入图片描述
在对话框类的头文件中增加

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);
	}
}

通过增加以上内容,即可完成这个小工具的制作!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/372904.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典

文章目录2023 年用 Python 语言解华为 OD 机试题&#xff0c;一篇博客找全。华为 OD 机试题清单&#xff08;机试题库还在逐日更新&#xff09;2023 年用 Python 语言解华为 OD 机试题&#xff0c;一篇博客找全。 在 2023 年&#xff0c;Python 已成为广泛使用的编程语言之一&…

rabbitmq添加用户,虚拟机步,设置rabbitmq配置文件

第一步&#xff0c;登录后台控制页面 http://ip:15672第二步&#xff0c;添加用户和权限 重点&#xff1a;选择Admin和Users 第三步&#xff0c;添加虚拟机 点击侧边的Virtual Hosts 第四步将虚拟机和用户搭配 注意新建好后&#xff0c;在虚拟机列表中&#xff0c;点击虚拟机…

ubuntu安装spinningup

ubuntu安装spinningup 经过这篇博客安装好mujoco和mujoco-py后&#xff0c;下面安装强化学习代码库spinningup 按照spinningup官网的安装步骤走&#xff0c;下面我总结一下安装过程中出现的问题 在安装spinningup的时候&#xff0c;最好重建一个新的虚拟环境&#xff0c;因为…

基于springboot+vue的校园招聘系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

Java基础语法的心得总结

一、数据存储的理解可以参考第四大部分https://blog.csdn.net/xiaoxixicc/article/details/124222375个人理解&#xff1a;栈内存中保存的实际上是对象在堆内存中的引用地址。通过这个引用地址可以快速查找到保存中堆内存中的对象。二、static静态变量&#xff08;共享的作用&a…

[数据结构]:05-循环队列(链表)(C语言实现)

目录 前言 已完成内容 循环队列实现 01-开发环境 02-文件布局 03-代码 01-主函数 02-头文件 03-QueueCommon.cpp 04-QueueFunction.cpp 结语 前言 此专栏包含408考研数据结构全部内容&#xff0c;除其中使用到C引用外&#xff0c;全为C语言代码。使用C引用主要是为了…

(三十七)大白话SQL标准中对事务的4个隔离级别,都是如何规定的呢?

之前我们给大家讲了数据库中多个事务并发时可能产生的几种问题&#xff0c;包括了脏写、脏读、不可重复读、幻读&#xff0c;几种问题 那么针对这些多事务并发的问题&#xff0c;实际上SQL标准中就规定了事务的几种隔离级别&#xff0c;用来解决这些问题。 注意一下&#xff…

SSM项目 替换为 SpringBoot

一、运行SSM项目 保证项目改为SpringBoot后运行正常&#xff0c;先保证SSM下运行正常。 项目目录结构 创建数据库&#xff0c;导入sql文件 查看项目中连接数据jar版本&#xff0c;修改对应版本&#xff0c;修改数据库配置信息 配置启动tomcat 运行项目&#xff0c;测试正常…

考虑极端天气线路脆弱性的配电网分布式电源和储能优化配置模型

目录 1 主要内容 1.1 线路脆弱性分析 ​编辑 1.2 配电网线路故障分析 1.3 蒙特卡洛随机抽样的线路脆弱性分析模型伪代码 1.4 配电网储能和光伏优化配置 2 程序效果 3 下载链接 1 主要内容 程序主要参考《考虑极端天气线路脆弱性的配电网分布式电源配置优化模型-马宇帆》…

RL笔记:动态规划(2): 策略迭代

目录 0. 前言 (4.3) 策略迭代 Example 4.2: Jack’s Car Rental Exercise 4.4 Exercise 4.5 Exercise 4.6 Exercise 4.7 0. 前言 Sutton-book第4章&#xff08;动态规划&#xff09;学习笔记。本文是关于其中4.2节&#xff08;策略迭代&#xff09;。 (4.3) 策略迭代 基…

【JavaWeb】复习重点内容

✅✅作者主页&#xff1a;&#x1f517;孙不坚1208的博客 &#x1f525;&#x1f525;精选专栏&#xff1a;&#x1f517;JavaWeb从入门到精通&#xff08;持续更新中&#xff09; &#x1f4cb;&#x1f4cb; 本文摘要&#xff1a;本篇文章主要分享JavaWeb的学习重点内容。 &a…

C++11多线程编程 二:多线程通信,同步,锁

C11多线程编程 一&#xff1a;多线程概述 C11多线程编程 二&#xff1a;多线程通信&#xff0c;同步&#xff0c;锁 C11多线程编程 三&#xff1a;锁资源管理和条件变量 2.1 多线程的状态及其切换流程分析 线程状态说明&#xff1a; 初始化&#xff08;Init&#xff09;&am…

javaEE 初阶 — 网络层中 IP 协议 的报文结构

文章目录IP 协议报文4位版本号4位首部长度8位服务类型16位总长度&#xff08;字节数&#xff09;8位生存时间&#xff08;TTL&#xff09;与 8位协议16位首部校验和32位源 IP 地址与32位目标 IP 地址动态分配的 IP 地址NAT 网络地址转换IPv6IP 协议报文 4位版本号 这里的 IP 协…

图表示学习+对比学习入门必看:DGI

来源&#xff1a;投稿 作者&#xff1a;kon 编辑&#xff1a;学姐 前言 众所周知&#xff0c;火热的对比学习不仅在CV取得了很多成果&#xff0c;也在NLP、推荐等领域大放异彩。自然的&#xff0c;有人将对比学习引入了图表示学习领域&#xff0c;利用图本身的结构与结点自身的…

14.微服务SpringCloud

一、基本概念 Spring Cloud 被称为构建分布式微服务系统的“全家桶”&#xff0c;它并不是某一门技术&#xff0c;而是一系列微服务解决方案或框架的有序集合。它将市面上成熟的、经过验证的微服务框架整合起来&#xff0c;并通过 Spring Boot 的思想进行再封装&#xff0c;屏蔽…

【Servlet篇】Response对象详细解读

文章目录Response 继承体系Response 设置响应数据设置响应行数据设置响应头数据设置响应体数据Response 重定向Response 响应字符数据Response 响应字节数据Response 继承体系 前面说到&#xff0c;我们使用 Request 对象来获取请求数据&#xff0c;使用 Response 对象来设置响…

Pyinstaller 打包EXE(七) 百篇文章学PyQT

本文章是百篇文章学PyQT6的第七篇&#xff0c;本文讲述如何使用Pyinstaller打包UI界面和代码&#xff0c;将程序打包成EXE来更为方便的进行部署&#xff0c;在写博客和学习的过程中会遇到很多问题&#xff0c;例如&#xff1a;PyQT6在网上很多博客都是PyQT5、或者PyQT4大部分都…

Could not extract response: no suitable HttpMessageConverter

版本&#xff1a;spring-cloud-openfeign-core-2.1.1.RELEASE.jar&#xff0c;spring-webmvc-5.1.14.RELEASE.jar&#xff0c;jetty-server-9.4.41.v20210516.jar&#xff0c;tomcat-embed-core-9.0.48.jar 问题背景 生产服务请求下游服务时偶发抛出下面的异常&#xff0c;下…

git入门

目录 1. git简介 1.1 git是什么 1.2 git与svn的区别 2. github 2.1 创建仓库 2.2 删除仓库 2.3 新建文件及文件夹 3. git的基本操作 3.1 配置账户及邮箱 3.2 git文件状态与工作区域 3.3 常用命令 3.4 克隆&#xff08;clone&#xff09; 3.5 查看git仓库的状态 3.…

[音视频] BMP 图片格式分析

BMP 格式是什么 BMP&#xff08;Bitmap&#xff09;是一种常见的无损位图图像文件格式&#xff0c;是Windows操作系统中最早使用的图像格式之一&#xff0c;也是目前很多应用程序所使用的标准图像格式之一。 整体结构图&#xff0c;如下图所示 格式 BMP文件格式有多个版本&a…