You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 10:40:43