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

如何通过代码获取MSI/EXE安装项目文件的版本信息

解决MSI/EXE安装文件版本读取返回Null的问题

一、EXE文件的处理

调用FileVersionInfo.GetVersionInfo返回null,大概率是目标EXE未嵌入标准文件版本资源(比如部分自解压包、精简版安装引导程序),可尝试以下两种方案:

1. 直接解析PE文件头提取版本

通过读取PE文件的资源段获取版本信息,示例代码:

using System;
using System.IO;
using System.Runtime.InteropServices;

public static string GetPeFileVersion(string filePath)
{
    if (!File.Exists(filePath)) return null;

    using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
    using var binaryReader = new BinaryReader(fileStream);

    // 跳过DOS头,定位PE头
    fileStream.Position = 0x3C;
    int peHeaderPtr = binaryReader.ReadInt32();
    fileStream.Position = peHeaderPtr;

    // 验证PE标识
    uint peSignature = binaryReader.ReadUInt32();
    if (peSignature != 0x00004550) // "PE\0\0"
        return null;

    // 跳转至版本信息字段
    fileStream.Position += 0x12;
    int fileVersionPtr = peHeaderPtr + 0x40;
    fileStream.Position = fileVersionPtr;

    ushort major = binaryReader.ReadUInt16();
    ushort minor = binaryReader.ReadUInt16();
    ushort build = binaryReader.ReadUInt16();
    ushort revision = binaryReader.ReadUInt16();

    return $"{major}.{minor}.{build}.{revision}";
}

2. 确认是否为MSI引导程序

很多setup.exe只是MSI的启动器,实际版本信息存储在关联的MSI文件中(可能与exe同目录,或内嵌在exe内部),可尝试提取内嵌MSI后再读取版本。

二、MSI文件的处理

MSI的版本信息存储在数据库的Property表(ProductVersion属性)中,FileVersionInfo无法读取这类信息,需用Windows Installer相关方法:

方法1:使用WiX的Microsoft.Deployment.WindowsInstaller库

  1. 通过NuGet安装Microsoft.Deployment.WindowsInstaller包
  2. 示例代码:
using Microsoft.Deployment.WindowsInstaller;

public static string GetMsiVersion(string msiPath)
{
    if (!File.Exists(msiPath)) return null;

    using var database = new Database(msiPath, DatabaseOpenMode.ReadOnly);
    return database.ExecuteScalar("SELECT `Value` FROM `Property` WHERE `Property` = 'ProductVersion'") as string;
}

方法2:无第三方库的原生API调用

无需引入外部库,直接调用Windows Installer API:

using System;
using System.Text;
using System.Runtime.InteropServices;

public static string GetMsiVersionWithoutLibrary(string msiPath)
{
    uint bufferSize = 256;
    StringBuilder versionBuffer = new StringBuilder((int)bufferSize);
    uint result = MsiGetFileVersion(msiPath, versionBuffer, ref bufferSize);
    return result == 0 ? versionBuffer.ToString() : null;
}

[DllImport("msi.dll", CharSet = CharSet.Unicode)]
private static extern uint MsiGetFileVersion(string szFilePath, StringBuilder szVersion, ref uint pcchVersion);

三、常见排查点

  • 确认文件路径正确,且当前程序有读取该文件的权限(比如系统目录下的文件需管理员权限)
  • 若EXE经过压缩或加壳,需先脱壳才能读取版本信息

内容的提问来源于stack exchange,提问作者Dan D

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 02:35:19