實現組件存儲 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.pswp.cn/web/44363.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/44363.shtml
英文地址,請注明出處:http://en.pswp.cn/web/44363.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

深入理解Spring Boot中的日志框架選擇

深入理解Spring Boot中的日志框架選擇 大家好&#xff0c;我是微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01; 1. 背景與需求 在開發和運維中&#xff0c;日志是不可或缺的重要組成部分。Spring Boot作為一個流行的Java開…

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;如果每一次去…

破解世紀難題:顛覆性方案解鎖世界十大未解之謎

前言 在科學的浩瀚宇宙中&#xff0c;始終存在一些引人入勝的謎題&#xff0c;它們挑戰著人類智慧的極限。這些謎題不僅涵蓋了數學、物理、天文學和生物學等領域&#xff0c;還觸及到意識和宇宙的本質。破解這些世紀難題&#xff0c;不僅意味著人類知識的巨大飛躍&#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 —— Prompt Templates

文章目錄 一、什么是 Prompt Templates1、String PromptTemplates2、ChatPromptTemplates3、MessagesPlaceholder 留言占位符 二、如何使用 Prompt Templates 一、什么是 Prompt Templates 提示模板有助于將用戶輸入和參數轉換為語言模型的指令。這可用于指導模型的響應&#x…

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;最初設計用于展示網絡結構隨時間的變化。這種圖表特別適用于展示…

sed的替換可用:斜杠/,豎或|,井號# 等符號, 但是查找只能用斜杠/ , sed的查找和替換可以一起用 筆記240711

sed的替換可用:斜杠/,豎或|,井號# 等符號, 但是… … 查找只能用斜杠/ 替換必須用s開頭, 如:s/ , s| , s# 例如: s/正則/替換內容/s/正則/替換內容/gs|正則|替換內容|s|正則|替換內容|gs#正則#替換內容#s#正則#替換內容#g 當內容包含斜杠/時, (例如路徑) , 使用 豎或|,井號…

06_TypeScript 中的函數

TypeScript 中的函數 一、函數的定義es5 定義函數的方法TypeScript 定義函數的方法ts 中定義方法傳參 二、可選參數三、默認參數&#xff08;跟可選參數一樣&#xff09;四、剩余參數&#xff08;三點運算符的應用&#xff09;五、函數重載六、箭頭函數 es6 一、函數的定義 es…

Windows圖形界面(GUI)-SDK-C/C++ - 編輯框(edit)

公開視頻 -> 鏈接點擊跳轉公開課程博客首頁 -> 鏈接點擊跳轉博客主頁 目錄 編輯框(edit) 控件樣式 創建控件 初始控件 消息處理 示例代碼 編輯框(edit) 控件樣式 編輯框&#xff08;Edit Control&#xff09;是Windows中最常用的控件之一&#xff0c;用于接收用戶…

python 知識點累積

.items() tinydict {Google: www.google.com, Runoob: www.runoob.com, taobao: www.taobao.com}print (tinydict.items())運行結果 dict_items([(Google, www.google.com), (Runoob, www.runoob.com), (taobao, www.taobao.com)]) 返回的 dict_items([...]) 是一個字典項的…

【持續集成_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 模型性能的關鍵因素之一是從外部源檢索相…

C++之STL簡介

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 前言一、STL是什么二、STL的發展歷史三、STL的組成部分3.1 容器&#xff08;Containers&#xff09;3.2 迭代器&#xff08;Iterators&#xff09;3.3 算法&#xf…

【啟明智顯分享】ESP32-S3 4.3寸觸摸串口屏HMI應用方案:WIFI/藍牙無線通信助力烘干設備實現遠程遙控

技術不斷進步&#xff0c;人們對烘干設備的美觀度、功能多樣性提出更高要求&#xff0c;傳統的數碼管顯示、按鍵式控制已經無法滿足客戶的需求。用智能屏替代傳統的數碼管可以很好的解決這個問題&#xff0c;為用戶帶來更好的人機交互體驗。 基于此&#xff0c;啟明智顯提出將樂…

solidity實戰練習2--ERC20實現

//SPDX-License-Identifier:MTT pragma solidity ^0.8.24;interface erc20{function name()external view returns (string memory);//查看代幣的名稱function symbol() external view returns(string memory);//查看代幣簡稱function totalSupply()external view returns(uint…

低代碼:架起產教融合的“立交橋”

隨著信息技術的飛速發展&#xff0c;傳統的軟件開發模式正面臨著前所未有的挑戰。為了應對這一挑戰&#xff0c;低代碼平臺應運而生&#xff0c;其通過簡化開發流程、提高開發效率&#xff0c;成為了推動產業與教育深度融合的重要力量。本文將探討低代碼平臺如何架起產教融合的…