如何用C++读取MSI文件并获取属性(跨Windows与Linux)
跨平台(Windows/Linux)C++读取MSI文件的解决方案
推荐的跨平台MSI处理库
- msitools:开源MSI工具集,核心是
libmsi库,原生支持Windows和Linux。提供C风格API,可直接在C++代码中调用,能满足MSI数据库读取、表查询、数据提取等常见需求。 - WiX Toolset的libmsi:WiX项目拆分出的独立跨平台MSI解析库,支持双平台编译,API设计和微软Win32 MSI接口接近,降低迁移成本。
实现思路与步骤
1. 库的获取与编译
- msitools:Linux下通过包管理器快速安装开发包,比如Debian/Ubuntu执行
sudo apt-get install libmsi-dev;Windows需从源码编译,可借助MinGW或MSVC环境,编译时指定目标平台。 - WiX libmsi:从WiX官方仓库拉取源码,用CMake配置跨平台编译脚本,生成静态/动态库后集成到C++项目。
2. C++代码集成示例(以libmsi为例)
以下是读取MSI中Product表的基础代码:
#include <msi.h> #include <msiquery.h> #include <iostream> #include <string> int main() { MSIHANDLE dbHandle = nullptr; // 以只读模式打开MSI文件 UINT result = MsiOpenDatabase(L"sample.msi", MSIDBOPEN_READONLY, &dbHandle); if (result != ERROR_SUCCESS) { std::cerr << "Failed to open MSI file" << std::endl; return 1; } MSIHANDLE viewHandle = nullptr; // 执行SQL查询Product表 result = MsiDatabaseOpenView(dbHandle, L"SELECT ProductName, ProductCode FROM Product", &viewHandle); if (result != ERROR_SUCCESS) { MsiCloseHandle(dbHandle); std::cerr << "Failed to create query view" << std::endl; return 1; } result = MsiViewExecute(viewHandle, nullptr); if (result != ERROR_SUCCESS) { MsiCloseHandle(viewHandle); MsiCloseHandle(dbHandle); std::cerr << "Failed to execute query" << std::endl; return 1; } MSIHANDLE recordHandle = nullptr; // 遍历查询结果 while (MsiViewFetch(viewHandle, &recordHandle) == ERROR_SUCCESS) { WCHAR productName[256]; WCHAR productCode[256]; // 提取第2列(ProductName)和第3列(ProductCode)的值 MsiRecordGetString(recordHandle, 2, productName, sizeof(productName)/sizeof(WCHAR)); MsiRecordGetString(recordHandle, 3, productCode, sizeof(productCode)/sizeof(WCHAR)); // 转换为多字节字符串输出(Linux下适配) char mbName[256]; char mbCode[256]; wcstombs(mbName, productName, sizeof(mbName)); wcstombs(mbCode, productCode, sizeof(mbCode)); std::cout << "Product Name: " << mbName << ", Product Code: " << mbCode << std::endl; MsiCloseHandle(recordHandle); } // 释放资源 MsiCloseHandle(viewHandle); MsiCloseHandle(dbHandle); return 0; }
编译时,Linux下执行g++ msi_reader.cpp -lmsi -o msi_reader;Windows下需链接对应的libmsi库文件。
3. 关键注意事项
- 编码处理:MSI内部使用UTF-16编码,Linux下需通过
wcstombs等函数完成宽字符到多字节字符的转换,避免乱码。 - 功能兼容性:跨平台库无法完全复刻Win32 MSI API的所有功能,提前验证你的需求(比如提取内嵌文件、修改数据库)是否被支持。
- 依赖管理:Windows编译时需确保头文件和库文件路径配置正确,可通过CMake统一管理跨平台构建流程。
内容的提问来源于stack exchange,提问作者Abishek Samuel
相关产品推荐
相关产品推荐

