实现组件存储 WinSxS 文件夹解析

目录

背景

目录名的组成

解析目录结构

更新&总结


文章出处链接:[https://blog.csdn.net/qq_59075481/article/details/140385969].

背景

 WinSxS 文件夹位于 Windows 文件夹中,例如 C: \Windows\WinSxS。它是 Windows 组件存储文件的位置。 Windows 组件存储用于支持自定义和更新 Windows 所需的函数。 Windows 组件存储是首先在 Windows XP 中引入的,用于支持并行程序集。从 Windows Vista 开始,组件存储得到了增强,可以跟踪构成操作系统的所有组件并为其提供服务。

这些不同的操作系统组件可以跟踪对象,例如文件、目录、注册表项和服务。然后,系统会将特定版本的组件收集到包中。

 Windows 更新和 DISM 使用包来更新 Windows。 Windows 组件存储将处理 Windows 安装中使用的组件和包。确定 Windows 组件存储大小的过程会很复杂,因为 Windows 通过名为硬链接的技术使用的许多文件都来自 Windows 组件存储外的目录。在这种情况下,某个组件版本中的文件会同时出现在 Windows 组件存储的内部和外部。使用硬链接,Windows 就可以在看起来并不实际占用为多个副本提供的额外空间的情况下,保留同一文件的多个副本。

组件存储文件夹中的文件目录比较复杂,有些时候需要枚举或者检索目录中某个组件的特定版本的副本会很麻烦。在这篇文章中,我将提供一个解析组件存储文件夹的初步程序。包括相关测试示例。

目录名的组成

组件存储的目录名包含多个字段的信息,每个信息之间使用下划线("_")间隔开来,按照顺序包括:程序运行系统架构、组件名称、组件签名、更新时文件系统版本号、语言、文件存储签名。

系统架构有两种:amd64 、 x86,分别代表:适用于 x64 、 x32 的操作系统。

组件名称是该组件的描述名称(当目录名称过长时,采用.. 缩略名称的中间内容,如果是存储的组件的纯资源文件,则后缀 ".resources")

组件签名和文件存储签名都是一段校验码。

版本号包含 4 个部分,结构为:

// 版本信息结构体
struct VersionInfo {int major;int minor;int build;int revision;
};

语言可以是:zh-cn、en-us 等等,混合多个目录文件的,一般语言字段填写 none。

下面是一个标准的样例: 

amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.22621.3672_none_2713b9d173822955

解析目录结构

由于我目前还没有找到相关的 API 来解析目录结构,所以,使用正则表达式编写了一个程序用于解析目录。

提供三个主要函数:

  • listWinSxSAssemblies:解析 WinSxS 整个目录结构,并使用文件流存储解析结果。
  • getAssembliesByComponentName:根据组件名称,检索所有匹配到的存储条目信息。
  • getLatestAssemblyByArchitecture:根据组件名称和适用的系统架构,查找符合条件且版本号最高的存储目录名称。

代码如下:

// EnumWinSxS.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <windows.h>
#include <iostream>
#include <fstream>
#include <string>
#include <regex>
#include <vector>
#include <tuple>
#include <algorithm>
#include <sstream>// 版本信息结构体
struct VersionInfo {int major;int minor;int build;int revision;
};// 解析特征字符串
struct AssemblyInfo {std::wstring architecture;std::wstring componentName;std::wstring componentSign;VersionInfo version;std::wstring language;std::wstring folderSign;bool isResource;
};// 解析版本信息字符串
VersionInfo parseVersionInfo(const std::wstring& versionStr) {VersionInfo version = { 0, 0, 0, 0 };std::wregex versionPattern(LR"((\d+)\.(\d+)\.(\d+)\.(\d+))");std::wsmatch match;if (std::regex_match(versionStr, match, versionPattern)) {version.major = std::stoi(match[1]);version.minor = std::stoi(match[2]);version.build = std::stoi(match[3]);version.revision = std::stoi(match[4]);}return version;
}// 解析 WinSxS 目录名称并返回 AssemblyInfo 结构体
AssemblyInfo parseAssemblyInfo(const std::wstring& dirName) {AssemblyInfo info;//std::wregex regexPattern(LR"((amd64|x86)_([a-zA-Z0-9.-]+)_(\w+)_((\d+\.\d+\.\d+\.\d+))_((?:[a-z]{2}-[a-z]{2}|none))_(\w+))");std::wregex regexPattern(LR"((amd64|x86)_([a-zA-Z0-9.-]+)_(\w+)_(\d+\.\d+\.\d+\.\d+)_((?:[a-z]{2}-[a-z]{2}|none))_(\w+))");std::wsmatch match;if (std::regex_match(dirName, match, regexPattern)) {info.architecture = match[1];info.componentName = match[2];info.componentSign = match[3];info.version = parseVersionInfo(match[4]); // 解析版本信息info.language = match[5];info.folderSign = match[6];info.isResource = (dirName.find(L".resources") != std::wstring::npos);if (info.isResource) {size_t pos = info.componentName.find(L".resources");if (pos != std::wstring::npos) {info.componentName.erase(pos, std::wstring::npos);}}}return info;
}// 比较版本信息的函数
bool compareVersions(const VersionInfo& v1, const VersionInfo& v2) {return std::tie(v1.major, v1.minor, v1.build, v1.revision) < std::tie(v2.major, v2.minor, v2.build, v2.revision);
}// 将版本信息合并为一个完整字符串
std::wstring versionInfoToString(const VersionInfo& version) {std::wostringstream oss;oss << version.major << L"." << version.minor << L"." << version.build << L"." << version.revision;return oss.str();
}//std::vector<std::wstring> listFilesInDirectory(const std::wstring& directory) {
//    std::vector<std::wstring> files;
//    WIN32_FIND_DATAW findFileData;
//    std::wstring searchPath = directory + L"\\*";
//    HANDLE hFind = FindFirstFileW(searchPath.c_str(), &findFileData);
//
//    if (hFind == INVALID_HANDLE_VALUE) {
//        return files;
//    }
//
//    do {
//        const std::wstring fileName = findFileData.cFileName;
//        if (!(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
//            files.push_back(directory + L"\\" + fileName);
//        }
//    } while (FindNextFileW(hFind, &findFileData) != 0);
//
//    FindClose(hFind);
//    return files;
//}void listFilesRecursively(const std::wstring& directory, std::wofstream& outFile, const std::wstring& baseDir) {WIN32_FIND_DATAW findFileData;std::wstring searchPath = directory + L"\\*";HANDLE hFind = FindFirstFileW(searchPath.c_str(), &findFileData);if (hFind == INVALID_HANDLE_VALUE) {return;}do {const std::wstring fileName = findFileData.cFileName;if (fileName == L"." || fileName == L"..") {continue;}std::wstring fullPath = directory + L"\\" + fileName;std::wstring relPath = fullPath.substr(baseDir.length() + 1);if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {listFilesRecursively(fullPath, outFile, baseDir);}else {std::wcout << L"  File: " << relPath << std::endl;outFile << L"  File: " << relPath << std::endl;}} while (FindNextFileW(hFind, &findFileData) != 0);FindClose(hFind);
}void listWinSxSAssemblies(const std::wstring& winSxsPath, std::wofstream& outFile) {WIN32_FIND_DATAW findFileData;std::wstring searchPath = winSxsPath + L"\\*";HANDLE hFind = FindFirstFileW(searchPath.c_str(), &findFileData);if (hFind == INVALID_HANDLE_VALUE) {std::wcerr << L"Error: Unable to open directory " << winSxsPath << std::endl;return;}do {const std::wstring dirName = findFileData.cFileName;if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {// Skip "." and ".." directoriesif (dirName == L"." || dirName == L"..") {continue;}AssemblyInfo info = parseAssemblyInfo(dirName);if (!info.architecture.empty()) {std::wcout << L"Directory: " << dirName << std::endl;outFile << L"Directory: " << dirName << std::endl;std::wcout << L"Architecture: " << info.architecture << std::endl;outFile << L"Architecture: " << info.architecture << std::endl;std::wcout << L"Component Name: " << info.componentName << std::endl;outFile << L"Component Name: " << info.componentName << std::endl;std::wcout << L"Component Signature: " << info.componentSign << std::endl;outFile << L"Component Signature: " << info.componentSign << std::endl;std::wcout << L"Version: " << versionInfoToString(info.version) << std::endl;outFile << L"Version: " << versionInfoToString(info.version) << std::endl;//std::wcout << L"Version: " << info.version.major << L"." << info.version.minor << L"." //    << info.version.build << L"." << info.version.revision << std::endl;//outFile << L"Version: " << info.version.major << L"." << info.version.minor << L"." //    << info.version.build << L"." << info.version.revision << std::endl;std::wcout << L"Language: " << info.language << std::endl;outFile << L"Language: " << info.language << std::endl;std::wcout << L"Folder Signature: " << info.folderSign << std::endl;outFile << L"Folder Signature: " << info.folderSign << std::endl;std::wcout << L"Is Only Resource: " << (info.isResource ? L"Yes" : L"No") << std::endl;outFile << L"Is Only Resource: " << (info.isResource ? L"Yes" : L"No") << std::endl;List files in the directory//std::wstring subDirPath = winSxsPath + L"\\" + dirName;//std::vector<std::wstring> files = listFilesInDirectory(subDirPath);//for (const std::wstring& file : files) {//    std::wcout << L"  File: " << file << std::endl;//    outFile << L"  File: " << file << std::endl;//}// List files and subdirectories in the directorystd::wstring subDirPath = winSxsPath + L"\\" + dirName;listFilesRecursively(subDirPath, outFile, winSxsPath);std::wcout << L"--------------------------------" << std::endl;outFile << L"--------------------------------" << std::endl;}}} while (FindNextFileW(hFind, &findFileData) != 0);FindClose(hFind);
}std::vector<AssemblyInfo> getAssembliesByComponentName(const std::wstring& winSxsPath, const std::wstring& componentName) {std::vector<AssemblyInfo> matchingAssemblies;WIN32_FIND_DATAW findFileData;std::wstring searchPath = winSxsPath + L"\\*";HANDLE hFind = FindFirstFileW(searchPath.c_str(), &findFileData);if (hFind == INVALID_HANDLE_VALUE) {std::wcerr << L"Error: Unable to open directory " << winSxsPath << std::endl;return matchingAssemblies;}do {const std::wstring dirName = findFileData.cFileName;if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {if (dirName == L"." || dirName == L"..") {continue;}AssemblyInfo info = parseAssemblyInfo(dirName);if (!info.architecture.empty() && info.componentName == componentName) {matchingAssemblies.push_back(info);}}} while (FindNextFileW(hFind, &findFileData) != 0);FindClose(hFind);return matchingAssemblies;
}std::wstring getLatestAssemblyByArchitecture(const std::wstring& winSxsPath, const std::wstring& componentName, const std::wstring& architecture) {std::wstring latestDir;VersionInfo latestVersion = { 0, 0, 0, 0 };WIN32_FIND_DATAW findFileData;std::wstring searchPath = winSxsPath + L"\\*";HANDLE hFind = FindFirstFileW(searchPath.c_str(), &findFileData);if (hFind == INVALID_HANDLE_VALUE) {std::wcerr << L"Error: Unable to open directory " << winSxsPath << std::endl;return latestDir;}do {const std::wstring dirName = findFileData.cFileName;if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {if (dirName == L"." || dirName == L"..") {continue;}AssemblyInfo info = parseAssemblyInfo(dirName);if (!info.architecture.empty() && info.architecture == architecture && info.componentName == componentName) {if (compareVersions(latestVersion, info.version)) {latestVersion = info.version;latestDir = dirName;}}}} while (FindNextFileW(hFind, &findFileData) != 0);FindClose(hFind);return latestDir;
}int wmain() {const std::wstring winSxsPath = L"\\\\?\\C:\\Windows\\WinSxS"; // Using the long path prefixconst std::wstring outputPath = L"output.txt";// Testing API 0std::wofstream outFile(outputPath);if (!outFile.is_open()) {std::wcerr << L"Error: Unable to open output file " << outputPath << std::endl;return 1;}listWinSxSAssemblies(winSxsPath, outFile);outFile.close();// Testing API 1const std::wstring componentNameToSearch = L"microsoft.windows.common-controls";std::vector<AssemblyInfo> foundAssemblies = getAssembliesByComponentName(winSxsPath, componentNameToSearch);std::wcout << L"\nAssemblies for component name: " << componentNameToSearch << L"\n";for (const auto& assembly : foundAssemblies) {std::wcout << L"Architecture: " << assembly.architecture << std::endl;std::wcout << L"Component Name: " << assembly.componentName << std::endl;std::wcout << L"Component Signature: " << assembly.componentSign << std::endl;std::wcout << L"Version: " << versionInfoToString(assembly.version) << std::endl;//std::wcout << L"Version: " << assembly.version.major << L"." << assembly.version.minor //    << L"." << assembly.version.build << L"." << assembly.version.revision << std::endl;std::wcout << L"Language: " << assembly.language << std::endl;std::wcout << L"Folder Signature: " << assembly.folderSign << std::endl;std::wcout << L"Is Only Resource: " << (assembly.isResource ? L"Yes" : L"No") << std::endl;std::wcout << L"--------------------------------" << std::endl;}// Testing API 2std::wstring architectureToSearch = L"amd64";std::wstring latestAssemblyDir = getLatestAssemblyByArchitecture(winSxsPath, componentNameToSearch, architectureToSearch);if (!latestAssemblyDir.empty()) {std::wcout << L"Latest Assembly Directory for Architecture " << architectureToSearch << L": "<< latestAssemblyDir << std::endl;}else {std::wcout << L"No assemblies found for architecture " <<architectureToSearch << std::endl;}return 0;
}

测试截图:

WinSxS 解析效果截图

更新&总结

(暂无)


文章出处链接:[https://blog.csdn.net/qq_59075481/article/details/140385969].

本文发布于:2024.07.12,更新于:2024.07.12.

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

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

相关文章

idea启动vue项目一直卡死在51%,问题分析及其如何解决

如果你的项目也一直卡在百分之几十&#xff0c;你可以参考下面的方法&#xff0c;试一试能否解决 问题描述&#xff1a; 通过在idea终端中输入命令 npm run serve 启动vue项目&#xff0c;启动进程一直卡在51% 如何解决&#xff1a; 检查 < template > 标签中的html内容…

深度学习中的超参管理方法:argparse模块

在深度学习方法中我们不可避免地会遇到大量超参数如&#xff08;batch_size、learning_rate等&#xff09;。不同的超参数组合可以得到不同的训练/测试结果。所以在训练和测试过程中我们需要不断调整超参数获得理想的结果&#xff08;炼丹&#xff09;&#xff0c;如果每一次去…

【Windows】硬链接和软链接(OneDrive同步指定目录?)

文章目录 一、场景带入二、Windows下的硬链接和软链接2.1 硬链接&#xff08;Hard Link&#xff09;2.2 软链接&#xff08;符号链接&#xff0c;Symbolic Link&#xff09;2.3 软链接和快捷方式2.4 应用场景 三、OneDrive中的应用3.1 错误姿势3.2 好像可行的尝试3.3 合理的解决…

智能猫砂盆两种类型怎么选?深度剖析热门前三的品牌!

应该也有很多铲屎官像我一样&#xff0c;第一个入手的通常都是封闭式的智能猫砂盆&#xff0c;自动清洁是很好用&#xff0c;但问题也随之而来。有时候滚筒式的智能猫砂盆会在清洁过程中将砂团摔碎&#xff0c;导致粪便暴露出来产生臭味&#xff0c;这样我们回来不得不又再次进…

LangChain框架详解

LangChain框架详解 LangChain是一个基于语言模型开发应用程序的强大框架&#xff0c;旨在帮助开发人员简化与大模型交互、数据检索以及将不同功能模块串联起来以完成复杂任务的过程。它提供了一套丰富的工具、组件和接口&#xff0c;使开发人员能够轻松构建上下文感知和具备逻…

基于stm32+小程序开发智能家居门禁系统-硬件-软件实现

视频演示&#xff1a; 基于stm32智能家居门禁系统小程序开发项目 视频还有添加删除卡号&#xff0c;添加删除指纹&#xff0c;关闭继电器电源等没有演示。 代码Git&#xff1a; https://github.com/Abear6666/stm32lock 总体功能&#xff1a; 本门禁系统主要解锁功能分别为卡…

冲积图(alluvial plot)展示竞争性内源RNA(ceRNA)网络

导读&#xff1a; 用冲积图展示ceRNA网络可以更好地查看竞争和吸附关系&#xff0c;让静态的图&#xff0c;“流动”起来。 冲积图简介 Alluvial plot&#xff08;冲积图&#xff09;是一种流程图&#xff0c;最初设计用于展示网络结构随时间的变化。这种图表特别适用于展示…

06_TypeScript 中的函数

TypeScript 中的函数 一、函数的定义es5 定义函数的方法TypeScript 定义函数的方法ts 中定义方法传参 二、可选参数三、默认参数&#xff08;跟可选参数一样&#xff09;四、剩余参数&#xff08;三点运算符的应用&#xff09;五、函数重载六、箭头函数 es6 一、函数的定义 es…

【持续集成_05课_Linux部署SonarQube及结合开发项目部署】

一、Linux下安装SonarQube 1、安装sonarQube 前置条件&#xff1a;sonarQube不能使用root账号进行启动&#xff0c;所以需要创建普通用户及 其用户组 1&#xff09;创建组 2&#xff09;添加用户、组名、密码 3&#xff09;CMD上传qube文件-不能传到home路径下哦 4&#xff09…

王牌站士Ⅳ--矢量数据库对 RAG 效率的影响

前言 近年来&#xff0c;检索增强生成 (RAG) 模型越来越受欢迎。RAG 模型利用大型神经网络以及外部知识源的检索机制。这使得模型拥有的知识比其内部存储的更多&#xff0c;从而使其能够为广泛的主题和领域生成高质量的输出。 影响 RAG 模型性能的关键因素之一是从外部源检索相…

【启明智显分享】ESP32-S3 4.3寸触摸串口屏HMI应用方案:WIFI/蓝牙无线通信助力烘干设备实现远程遥控

技术不断进步&#xff0c;人们对烘干设备的美观度、功能多样性提出更高要求&#xff0c;传统的数码管显示、按键式控制已经无法满足客户的需求。用智能屏替代传统的数码管可以很好的解决这个问题&#xff0c;为用户带来更好的人机交互体验。 基于此&#xff0c;启明智显提出将乐…

C++基础(十八):继承(重点)

各位看官&#xff0c;大家好&#xff01;今天我们将探讨C中的三大特性之一&#xff1a;继承。继承是一种面向对象编程的重要概念&#xff0c;它允许我们通过创建新的类&#xff0c;从而复用和扩展现有类的功能。通过继承&#xff0c;我们不仅能够提高代码的可重用性和可维护性&…

9.5 栅格图层符号化多波段彩色渲染

文章目录 前言多波段彩色渲染QGis设置为多波段彩色二次开发代码实现多波段彩色 总结 前言 介绍栅格图层数据渲染之多波段彩色渲染说明&#xff1a;文章中的示例代码均来自开源项目qgis_cpp_api_apps 多波段彩色渲染 以“3420C_2010_327_RGB_LATLNG.tif”数据为例&#xff0c…

常见条件控制算法流程图

内容讲解&#xff1a;流程控制[if…else…(if…elif…else…),while,for] 常见条件控制算法流程图高清图

新手教学系列——高效管理MongoDB数据:批量插入与更新的实战技巧

前言 在日常开发中,MongoDB作为一种灵活高效的NoSQL数据库,深受开发者喜爱。然而,如何高效地进行数据的批量插入和更新,却常常让人头疼。今天,我们将一起探讨如何使用MongoDB的bulk_write方法,简化我们的数据管理流程,让代码更加简洁高效。 常规做法:find、insertone…

【Linux】常见指令收官权限理解

tar指令 上一篇博客已经介绍了zip/unzip指令&#xff0c;接下来我们来看一下另一个关于压缩和解压的指令&#xff1a;tar指令tar指令&#xff1a;打包/解包&#xff0c;不打开它&#xff0c;直接看内容 关于tar的指令有太多了&#xff1a; tar [-cxtzjvf] 文件与目录 ...…

C++运行时类型识别

目录 C运行时类型识别A.What&#xff08;什么是运行时类型识别RTTI&#xff09;B.Why&#xff08;为什么需要RTTI&#xff09;C.dynamic_cast运算符Why&#xff08;dynamic_cast运算符的作用&#xff09;How&#xff08;如何使用dynamic_cast运算符&#xff09; D.typeid运算符…

各地户外分散视频监控点位,如何实现远程集中实时监看?

公司业务涉及视频监控项目承包搭建&#xff0c;此前某个项目需求是为某林业公司提供视频监控解决方案&#xff0c;需要实现各地视频摄像头的集中实时监看&#xff0c;以防止国家储备林的盗砍、盗伐行为。 公司原计划采用运营商专线连接各个视频监控点位&#xff0c;实现远程视…

跟着李沐学AI:线性回归

引入 买房出价需要对房价进行预测。 假设1&#xff1a;影响房价的关键因素是卧室个数、卫生间个数和居住面积&#xff0c;记为x1、x2、x3。 假设2&#xff1a;成交价是关键因素的加权和 。权重和偏差的实际值在后面决定。 拓展至一般线性模型&#xff1a; 给定n维输入&…

MySQL 9.0 正式发行Innovation创新版已支持向量

从 MySQL 8.1 开始&#xff0c;官方启用了新的版本模型&#xff1a;MySQL 创新版 (Innovation) 和长期支持版 (LTS)。 根据介绍&#xff0c;两者的质量都已达到可用于生产环境级别。区别在于&#xff1a; 如果希望尝试最新的功能和改进&#xff0c;并喜欢与最新技术保持同步&am…