当前位置: 首页 > news >正文

Win32 获取EXE/DLL文件版本信息

CFileVersion.h

#pragma once#include <windows.h>
#include <string>
#include <tchar.h>#ifdef _UNICODE
using _tstring = std::wstring;
#else
using _tstring = std::string;
#endif// 版本号辅助类
class CVersionNumber
{
public:// 无参构造CVersionNumber();// 从版本字符串构造CVersionNumber(LPCTSTR lpStrVer);// 从指定版本号构造CVersionNumber(WORD v1, WORD v2, WORD v3, WORD v4);// 从版本字符串构造CVersionNumber& operator = (LPCTSTR lpStrVer);// 比较版本号大小int CompareVersion(const CVersionNumber& ref) const;//获取版本号字符串_tstring GetVersionStr() const;// 比较运算重载bool operator == (const CVersionNumber& ref);bool operator != (const CVersionNumber& ref);bool operator < (const CVersionNumber& ref);bool operator <= (const CVersionNumber& ref);bool operator > (const CVersionNumber& ref);bool operator >= (const CVersionNumber& ref);private:WORD m_nVer[4];         //版本号
};typedef struct _FILE_VERSION_INFO
{_tstring strComments;                       //文件注释_tstring strInternalName;                   //内部名称_tstring strProductName;                    //产品名称_tstring strCompanyName;                    //公司名称_tstring strLegalCopyright;                 //法律版权_tstring strProductVersion;                 //产品版本_tstring strFileDescription;                //文件描述_tstring strLegalTrademarks;                //合法商标_tstring strPrivateBuild;                   //私有构建_tstring strFileVersion;                    //文件版本_tstring strOriginalFilename;               //原始文件名_tstring strSpecialBuild;                   //特殊构建_tstring strFileVersionEx;                  //文件版本(从 VS_FIXEDFILEINFO中 获取)_tstring strProductVersionEx;               //产品版本(从 VS_FIXEDFILEINFO中 获取)CVersionNumber FileVerNumber;               //文件版本号CVersionNumber ProductVerNumber;            //产品版本号
}FILE_VERSION_INFO;class CFileVersion
{struct LANGANDCODEPAGE {WORD wLanguage;WORD wCodePage;LANGANDCODEPAGE():wLanguage(0),wCodePage(0){}};public:CFileVersion();~CFileVersion();CFileVersion operator = (const CFileVersion& r) = delete;static FILE_VERSION_INFO GetVersionInfo(const _tstring& strFile);static FILE_VERSION_INFO GetCurrentModuleVersionInfo();public:bool LoadFile(const _tstring& strFile);             //加载文件信息void Close();FILE_VERSION_INFO GetVersionInfo() const;           //整个版本信息_tstring GetComments() const;                       //文件注释_tstring GetInternalName() const;                   //内部名称_tstring GetProductName() const;                    //产品名称_tstring GetCompanyName() const;                    //公司名称_tstring GetLegalCopyright() const;                 //法律版权_tstring GetProductVersion() const;                 //产品版本_tstring GetFileDescription() const;                //文件描述_tstring GetLegalTrademarks() const;                //合法商标_tstring GetPrivateBuild() const;                   //私有版本_tstring GetFileVersion() const;                    //文件版本_tstring GetOriginalFilename() const;               //原始文件名_tstring GetSpecialBuild() const;                   //特别版本_tstring GetFileVersionEx() const;                  //文件版本(从 VS_FIXEDFILEINFO中 获取)_tstring GetProductVersionEx() const;               //产品版本(从 VS_FIXEDFILEINFO中 获取)VS_FIXEDFILEINFO GetFixedFileInfo() const;          //文件的版本信息private:_tstring _QueryInfo(const _tstring& strName) const;void _LoadAllInfo();LPVOID m_lpVerData;                                 //文件信息数据指针LANGANDCODEPAGE m_Translate;                        //语言代码页VS_FIXEDFILEINFO m_VsFixedFileInfo;                 //文件的版本信息FILE_VERSION_INFO m_VersionInfo;                    //版本信息
};

CFileVersion.cpp

#include "CFileVersion.h"
#include <tchar.h>
#include <strsafe.h>#pragma comment(lib, "Version.lib")#pragma pack(push)
#pragma pack(1)
// 包含文件的版本信息。 此信息与语言和代码页无关
// https://learn.microsoft.com/zh-cn/windows/win32/menurc/vs-versioninfo
typedef struct {WORD             wLength;       // VS_VERSIONINFO 结构的长度(以字节为单位),此长度不包括在 32 位边界上对齐任何后续版本资源数据的填充WORD             wValueLength;  // Value 成员的长度(以字节为单位)WORD             wType;         // 版本资源中的数据类型, 1: 资源包含文本数据 0: 版本资源包含二进制数据WCHAR            szKey[15];     // Unicode 字符串 L“VS_VERSION_INFO”WORD             Padding1;      // 在 32 位边界上对齐 Children 成员所需的任意或零个 WORD//VS_FIXEDFILEINFO Value//WORD             Padding2//WORD             Children
} VS_VERSIONINFO, * PVS_VERSIONINFO;#pragma pack(pop)CVersionNumber::CVersionNumber():m_nVer{ 0 }
{
};CVersionNumber::CVersionNumber(LPCTSTR lpStrVer):m_nVer{ 0 }
{_stscanf_s(lpStrVer, _T("%hd.%hd.%hd.%hd"), &m_nVer[0], &m_nVer[1], &m_nVer[2], &m_nVer[3]);
}CVersionNumber::CVersionNumber(WORD v1, WORD v2, WORD v3, WORD v4):m_nVer{ v1, v2, v3, v4 }
{
}CVersionNumber& CVersionNumber::operator = (LPCTSTR lpStrVer)
{_stscanf_s(lpStrVer, _T("%hd.%hd.%hd.%hd"), &m_nVer[0], &m_nVer[1], &m_nVer[2], &m_nVer[3]);return *this;
}int CVersionNumber::CompareVersion(const CVersionNumber& ref) const
{for (int i = 0; i < _countof(m_nVer); i++){if (m_nVer[i] != ref.m_nVer[i]){return (m_nVer[i] > ref.m_nVer[i] ? 1 : -1);}}return 0;
}_tstring CVersionNumber::GetVersionStr() const
{TCHAR szBuf[MAX_PATH] = { 0 };(void)::StringCchPrintf(szBuf, _countof(szBuf), _T("%hd.%hd.%hd.%hd"),m_nVer[0],m_nVer[1],m_nVer[2],m_nVer[3]);return szBuf;
}bool CVersionNumber::operator == (const CVersionNumber& ref)
{return CompareVersion(ref) == 0;
}bool CVersionNumber::operator != (const CVersionNumber& ref)
{return CompareVersion(ref) != 0;
}bool CVersionNumber::operator < (const CVersionNumber& ref)
{return CompareVersion(ref) < 0;
}bool CVersionNumber::operator <= (const CVersionNumber& ref)
{return CompareVersion(ref) <= 0;
}bool CVersionNumber::operator > (const CVersionNumber& ref)
{return CompareVersion(ref) > 0;
}bool CVersionNumber::operator >= (const CVersionNumber& ref)
{return CompareVersion(ref) >= 0;
}CFileVersion::CFileVersion():m_lpVerData(NULL)
{memset(&m_VsFixedFileInfo, 0, sizeof(m_VsFixedFileInfo));
}CFileVersion::~CFileVersion()
{this->Close();
}FILE_VERSION_INFO CFileVersion::GetVersionInfo(const _tstring& strFile)
{CFileVersion verInfo;verInfo.LoadFile(strFile);return verInfo.GetVersionInfo();
}FILE_VERSION_INFO CFileVersion::GetCurrentModuleVersionInfo()
{TCHAR szBuf[MAX_PATH] = { 0 };::GetModuleFileName(NULL, szBuf, _countof(szBuf));return GetVersionInfo(szBuf);
}bool CFileVersion::LoadFile(const _tstring& strFile)
{PVOID pFsRedirectionOldValue = NULL;bool isDisableWow64Fs = false;bool isSuccess = false;UINT cbTranslate = 0;DWORD dwVerSize;if (strFile.empty()){return false;}this->Close();m_VersionInfo = FILE_VERSION_INFO();// 禁用文件重定向isDisableWow64Fs = ::Wow64DisableWow64FsRedirection(&pFsRedirectionOldValue);do{// 获取版本信息数据大小dwVerSize = ::GetFileVersionInfoSize(strFile.c_str(), 0);if (0 == dwVerSize){break;}// 分配版本信息缓冲m_lpVerData = ::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, dwVerSize);if (!m_lpVerData){break;}// 获取版本信息if (!::GetFileVersionInfo(strFile.c_str(), 0, dwVerSize, m_lpVerData)){break;}// 获取语言代码LANGANDCODEPAGE* lpTranslate = NULL;if (!::VerQueryValue(m_lpVerData, _T("\\VarFileInfo\\Translation"), (LPVOID*)&lpTranslate, &cbTranslate)){break;}m_Translate = *lpTranslate;// 获取 VS_FIXEDFILEINFO 信息PVS_VERSIONINFO lpVersion = (PVS_VERSIONINFO)m_lpVerData;if (0 != lpVersion->wValueLength){VS_FIXEDFILEINFO* pFixedFileInfo = (VS_FIXEDFILEINFO*)((LPBYTE)lpVersion + sizeof(VS_VERSIONINFO));DWORD dwAlign = 4;DWORD_PTR dwPadding = ((DWORD_PTR)pFixedFileInfo % dwAlign);if (0 != dwPadding){pFixedFileInfo = (VS_FIXEDFILEINFO*)((LPBYTE)pFixedFileInfo + (dwAlign - dwPadding));}m_VsFixedFileInfo = *pFixedFileInfo;}// 加载所有信息_LoadAllInfo();isSuccess = true;} while (false);// 不成功则关闭if (!isSuccess){this->Close();}// 恢复文件重定向if (isDisableWow64Fs){::Wow64RevertWow64FsRedirection(pFsRedirectionOldValue);}return isSuccess;
}void CFileVersion::Close()
{if (m_lpVerData){HeapFree(::GetProcessHeap(), 0, m_lpVerData);m_lpVerData = NULL;}
}void CFileVersion::_LoadAllInfo()
{m_VersionInfo.strComments = _QueryInfo(_T("Comments"));m_VersionInfo.strInternalName = _QueryInfo(_T("InternalName"));m_VersionInfo.strProductName = _QueryInfo(_T("ProductName"));m_VersionInfo.strCompanyName = _QueryInfo(_T("CompanyName"));m_VersionInfo.strLegalCopyright = _QueryInfo(_T("LegalCopyright"));m_VersionInfo.strProductVersion = _QueryInfo(_T("ProductVersion"));m_VersionInfo.strFileDescription = _QueryInfo(_T("FileDescription"));m_VersionInfo.strLegalTrademarks = _QueryInfo(_T("LegalTrademarks"));m_VersionInfo.strPrivateBuild = _QueryInfo(_T("PrivateBuild"));m_VersionInfo.strFileVersion = _QueryInfo(_T("FileVersion"));m_VersionInfo.strOriginalFilename = _QueryInfo(_T("OriginalFilename"));m_VersionInfo.strSpecialBuild = _QueryInfo(_T("SpecialBuild"));m_VersionInfo.strFileVersionEx = GetFileVersionEx();m_VersionInfo.strProductVersionEx = GetProductVersionEx();m_VersionInfo.FileVerNumber = m_VersionInfo.strFileVersionEx.c_str();m_VersionInfo.ProductVerNumber = m_VersionInfo.strProductVersionEx.c_str();}_tstring CFileVersion::_QueryInfo(const _tstring& strName) const
{_tstring strRes;TCHAR strQuery[MAX_PATH] = { 0 };LPCTSTR lpQueryRes = NULL;UINT uQueryCchSize;do{if (!m_lpVerData){break;}(void)::StringCchPrintf(strQuery, _countof(strQuery),_T("\\StringFileInfo\\%04x%04x\\%s"),m_Translate.wLanguage,m_Translate.wCodePage,strName.c_str());if (!::VerQueryValue(m_lpVerData, strQuery, (LPVOID*)&lpQueryRes, &uQueryCchSize)){break;}strRes = lpQueryRes;} while (false);return strRes;
}_tstring CFileVersion::GetComments() const
{return m_VersionInfo.strComments;
}_tstring CFileVersion::GetInternalName() const
{return m_VersionInfo.strInternalName;
}_tstring CFileVersion::GetProductName() const
{return m_VersionInfo.strProductName;
}_tstring CFileVersion::GetCompanyName() const
{return m_VersionInfo.strCompanyName;
}_tstring CFileVersion::GetLegalCopyright() const
{return m_VersionInfo.strLegalCopyright;
}_tstring CFileVersion::GetProductVersion() const
{return m_VersionInfo.strProductVersion;
}_tstring CFileVersion::GetFileDescription() const
{return m_VersionInfo.strFileDescription;
}_tstring CFileVersion::GetLegalTrademarks() const
{return m_VersionInfo.strLegalTrademarks;
}_tstring CFileVersion::GetPrivateBuild() const
{return m_VersionInfo.strPrivateBuild;
}_tstring CFileVersion::GetFileVersion() const
{return m_VersionInfo.strFileVersion;
}_tstring CFileVersion::GetOriginalFilename() const
{return m_VersionInfo.strOriginalFilename;
}_tstring CFileVersion::GetSpecialBuild() const
{return m_VersionInfo.strSpecialBuild;
}_tstring CFileVersion::GetFileVersionEx() const
{TCHAR szBuf[MAX_PATH] = { 0 };(void)::StringCchPrintf(szBuf, _countof(szBuf), _T("%hd.%hd.%hd.%hd"),HIWORD(m_VsFixedFileInfo.dwFileVersionMS),LOWORD(m_VsFixedFileInfo.dwFileVersionMS),HIWORD(m_VsFixedFileInfo.dwFileVersionLS),LOWORD(m_VsFixedFileInfo.dwFileVersionLS));return szBuf;
}_tstring CFileVersion::GetProductVersionEx() const
{TCHAR szBuf[MAX_PATH] = { 0 };(void)::StringCchPrintf(szBuf, _countof(szBuf), _T("%hd.%hd.%hd.%hd"),HIWORD(m_VsFixedFileInfo.dwProductVersionMS),LOWORD(m_VsFixedFileInfo.dwProductVersionMS),HIWORD(m_VsFixedFileInfo.dwProductVersionLS),LOWORD(m_VsFixedFileInfo.dwProductVersionLS));return szBuf;
}VS_FIXEDFILEINFO CFileVersion::GetFixedFileInfo() const
{return m_VsFixedFileInfo;
}FILE_VERSION_INFO CFileVersion::GetVersionInfo() const
{return m_VersionInfo;
}

main.cpp

#include <locale.h>
#include "Win32Utils/CFileVersion.h"int _tmain(int argc, LPCTSTR argv[])
{setlocale(LC_ALL, "");FILE_VERSION_INFO info = CFileVersion::GetCurrentModuleVersionInfo();return 0;
}

相关文章:

Win32 获取EXE/DLL文件版本信息

CFileVersion.h #pragma once#include <windows.h> #include <string> #include <tchar.h>#ifdef _UNICODE using _tstring std::wstring; #else using _tstring std::string; #endif// 版本号辅助类 class CVersionNumber { public:// 无参构造CVersionN…...

回显服务器的制作方法

文章目录 客户端和服务器TCP和UDP的特点UDP socket api的使用DatagramSocketDatagramPacketInetSocketAddress API 做一个简单的回显服务器UDP版本的回显服务器TCP版本的回显服务器 客户端和服务器 在网络中&#xff0c;主动发起通信的一方是客户端&#xff0c;被动接受的这一方…...

w28DVWA-csrf实例

DVWA-csrf实例 low级别 修改密码&#xff1a;修改的密码通过get请求&#xff0c;暴露在url上。 写一个简单的html文件&#xff0c;里面伪装修改密码的文字&#xff0c;代码如下&#xff1a; <html><body><a href"http://dvwa:7001/vulnerabilities/csr…...

子网络划分与互通,上网行为审计

网络环境需求:在办公网络环境中,由于公司部门的划分,以及服务器、电脑、手机等设备类型,一般都需要划分多个网段,便于进行网络管理,并提升网络通信效率。各个子网段管理员控制设备的接入,子网段之间需要进行局域网通信,发送消息和文件,通常使用飞秋。服务器网段,禁止…...

如何快速删除node_module依赖包

利用npm&#xff1a;输入 npm install rimraf -g rimraf node_modules...

async/await 的用法

一、async和await定义 async 是异步的意思&#xff0c;而 await 是等待的意思&#xff0c;await 用于等待一个异步任务执行完成的结果。 1.async/await 是一种编写异步代码的新方法&#xff08;以前是采用回调和 promise&#xff09;。 2. async/await 是建立在 promise 的基础…...

JAVA面试汇总总结更新中ing

本人面试积累面试题 基础RocketMQSpring登录技能操作线程事务微服务JVMKAFKAMYSQLRedislinux 基础 1.面向对象的三个特征 封装&#xff0c;继承&#xff0c;多态&#xff0c;有时候也会加上抽象。 2.多态的好处 允许不同类对象对同一消息做出响应&#xff0c;即同一消息可以根…...

vue-利用属性(v-if)控制表单(el-form-item)显示/隐藏

表单控制属性 v-if 示例&#xff1a; 通过switch组件作为开关&#xff0c;控制表单的显示与隐藏 <el-form-item label"创建数据集"><el-switch v-model"selectFormVisible"></el-switch></el-form-item><el-form-item label&…...

数据结构-邻接矩阵

介绍 邻接矩阵&#xff0c;是表示图的一种常见方式&#xff0c;具体表现为一个记录了各顶点连接情况的呈正方形的矩阵。 假设一共有以下顶点&#xff0c;其连接关系如图所示 那么&#xff0c;怎么表示它们之间的连接关系呢&#xff1f; 我们发现&#xff0c;各条边所连接的都…...

基于CNN-GRU-Attention的时间序列回归预测matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 CNN&#xff08;卷积神经网络&#xff09;部分 4.2 GRU&#xff08;门控循环单元&#xff09;部分 4.3 Attention机制部分 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版…...

Docker部署Halo容器并结合内网穿透实现公网访问本地个人博客

文章目录 1. Docker部署Halo1.1 检查Docker版本如果未安装Docker可参考已安装Docker步骤&#xff1a;1.2 在Docker中部署Halo 2. Linux安装Cpolar2.1 打开服务器防火墙2.2 安装cpolar内网穿透 3. 配置Halo个人博客公网地址4. 固定Halo公网地址 本文主要介绍如何在CentOS 7系统使…...

纯css实现文字左右循环滚动播放效果

思路&#xff1a;由两个span模块组成&#xff0c;第一个为空的span内容&#xff0c;为的是实现第二个span内容缓慢出现的效果。 代码如下&#xff1a; <div class"scrollingStyle"><span class"first-marquee"></span><span class&q…...

【Java EE初阶二十二】https的简单理解

1. 初识https 当前网络上,主要都是 HTTPS 了,很少能见到 HTTP.实际上 HTTPS 也是基于 HTTP.只不过 HTTPS 在 HTTP 的基础之上, 引入了"加密"机制&#xff1b;引入 HTTPS 防止你的数据被黑客篡改 &#xff1b; HTTPS 就是一个重要的保护措施.之所以能够安全, 最关键的…...

系统学习Python——装饰器:类装饰器-[跟踪对象接口:基础知识]

分类目录&#xff1a;《系统学习Python》总目录 文章《系统学习Python——装饰器&#xff1a;类装饰器-[单例类&#xff1a;基础知识]》的单例示例阐明了如何使用类装饰器来管理一个类的所有实例。类装饰器的另一个常用场景是为每个生成的实例扩展接口。类装饰器基本上可以在实…...

go-redis 使用 redis 6.0.14 版本错误: consider implementing encoding.BinaryMarshaler

使用方法 err : bp.data.redis.Get(ctx, policyKey).Scan(&result)起初在 redis 5.x.x 版本并没有遇到错误&#xff0c;但是在切换 redis 实例之后就出现了错误&#xff08;他们之间只是版本不同&#xff09;。 修复方法 看错误日志的描述&#xff0c;大概含义就是需要我们…...

计网 - 域名解析的工作流程

文章目录 Pre引言1. DNS是什么2. 域名结构3. 域名解析的工作流程4. 常见的DNS记录类型5. DNS安全6. 未来的发展趋势 Pre 计网 - DNS 域名解析系统 引言 在我们日常使用互联网时&#xff0c;经常会输入各种域名来访问网站、发送电子邮件或连接其他网络服务。然而&#xff0c;我…...

普中51单片机学习(EEPROM)

EEPROM IIC串行总线的组成及工作原理 I2C总线的数据传送 数据位的有效性规定 I2C总线进行数据传送时&#xff0c;时钟信号为高电平期间&#xff0c;数据线上的数据必须保持稳定&#xff0c;只有在时钟线上的信号为低电平期间&#xff0c;数据线上的高电平或低电平状态才允许…...

智能风控体系之供应链业务模式

供应链金融是一种针对中小企业的新型融资模式&#xff0c;将资金流有效整合到供应链管理的过程中&#xff0c;既为供应链各环节企业提供贸易资金服务&#xff0c;又为供应链弱势企业提供新型贷款融资服务&#xff0c;以核心客户为依托&#xff0c;以真实贸易背景为前提&#xf…...

最少停车数(C 语言)

题目描述 特定大小的停车场&#xff0c;数组cars[]表示&#xff0c;其中1表示有车&#xff0c;0表示没车。车辆大小不一&#xff0c;小车占一个车位&#xff08;长度1&#xff09;&#xff0c;货车占两个车位&#xff08;长度2&#xff09;&#xff0c;卡车占三个车位&#xf…...

MAC M1安装vmware和centos7虚拟机并配置静态ip

一、下载vmware和centos7镜像 1、VMWare Fusion 官网的下载地址是&#xff1a;下载地址 下载好之后注册需要秘钥&#xff0c;在官网注册后使用免费的个人秘钥 2、centos7 下载地址&#xff1a; https://biosyxh.cn:5001/sharing/pAlcCGNJf 二、虚拟机安装 直接将下…...

基于8ms平台的嵌入式GUI开发实践:智能家居86盒UI设计与实现

1. 项目概述&#xff1a;当智能家居遇上8ms&#xff0c;一个86盒的UI革命 最近在折腾一个智能家居的改造项目&#xff0c;核心是想把家里那些老旧的开关面板&#xff0c;换成能联网、能自定义、还能显示点信息的“智能大脑”。市面上现成的智能开关要么功能固化&#xff0c;要么…...

企业级应用如何利用Taotoken的容灾与路由能力保障AI服务高可用

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 企业级应用如何利用Taotoken的容灾与路由能力保障AI服务高可用 对于将大模型能力深度集成到关键业务流程的企业应用而言&#xff0…...

从高斯-克吕格到UTM:在QGIS里搞定国内卫星影像与地形图的坐标匹配

从高斯-克吕格到UTM&#xff1a;在QGIS里搞定国内卫星影像与地形图的坐标匹配 当你在QGIS中加载了从不同来源获取的卫星影像和地形图时&#xff0c;是否遇到过这样的困扰&#xff1a;明明应该是同一区域的数据&#xff0c;却在软件中显示得南辕北辙&#xff1f;这种"影像对…...

深入解析阿里云盘命令行客户端架构设计与技术实现

深入解析阿里云盘命令行客户端架构设计与技术实现 【免费下载链接】aliyunpan 阿里云盘命令行客户端&#xff0c;支持JavaScript插件&#xff0c;支持同步备份功能。 项目地址: https://gitcode.com/GitHub_Trending/ali/aliyunpan 阿里云盘命令行客户端是一个基于Go语言…...

避开FPGA除法器设计的那些‘坑’:恢复余数 vs. 不恢复余数 vs. SRT 实战选型指南

FPGA除法器设计实战&#xff1a;恢复余数、不恢复余数与SRT算法选型指南 在数字信号处理、图形渲染或科学计算等FPGA应用中&#xff0c;除法运算往往是性能瓶颈所在。不同于乘法器可通过流水线大幅提速&#xff0c;除法器的设计需要工程师在算法选择阶段就做出关键决策——恢复…...

手把手改造libmad:将一次性加载改为流式解码,拯救你的内存不足嵌入式系统

嵌入式音频革命&#xff1a;libmad流式解码改造实战指南 在资源受限的嵌入式环境中处理MP3音频&#xff0c;就像试图用吸管喝光整个游泳池的水——传统的一次性加载方式会让你的系统瞬间窒息。当树莓派Pico这类微控制器只有264KB的RAM时&#xff0c;一个5MB的MP3文件就能让内存…...

C#上位机如何连接西门子S7-1500的Modbus服务器?从PLC配置到.NET代码实战

C#上位机连接西门子S7-1500 Modbus服务器全流程解析 在工业自动化领域&#xff0c;上位机与PLC的通信是实现数据采集和设备控制的关键环节。西门子S7-1500系列PLC作为当前主流控制器&#xff0c;其Modbus TCP服务器功能为C#开发者提供了标准化的通信接口。本文将深入探讨如何从…...

深入理解 ASP.NET Core 中的 IActionResult

一、从一个问题开始 你写了一个 Web API&#xff0c;有时候要返回数据&#xff0c;有时候要返回 404&#xff0c;有时候要返回 400——这三种情况的返回值类型完全不同&#xff0c;一个 C# 方法怎么能同时返回多种东西&#xff1f; 这就是 IActionResult 存在的根本原因。它的本…...

drf-nested-routers测试指南:确保嵌套路由稳定性的完整方案

drf-nested-routers测试指南&#xff1a;确保嵌套路由稳定性的完整方案 【免费下载链接】drf-nested-routers Nested Routers for Django Rest Framework 项目地址: https://gitcode.com/gh_mirrors/dr/drf-nested-routers drf-nested-routers是Django Rest Framework的…...

技术解密:如何从零构建开源贴片机的完整指南

技术解密&#xff1a;如何从零构建开源贴片机的完整指南 【免费下载链接】lumenpnp The LumenPnP is an open source pick and place machine. 项目地址: https://gitcode.com/gh_mirrors/lu/lumenpnp 在电子制造领域&#xff0c;贴片机一直是小型创客和硬件开发者难以企…...