用 FileVersionInfo.GetVersionInfo
读取文件版本信息
最直接可靠的方式是调用
FileVersionInfo.GetVersionInfo,它能解析 Windows PE 文件(.exe、.dll)中嵌入的版本资源,不依赖文件名或扩展名,也不要求程序正在运行。
注意:该方法读取的是文件的 文件版本(File Version),不是程序集版本(Assembly Version),二者可能不同。
传入完整路径,如"C:\MyApp\app.exe";相对路径需确保当前工作目录正确 若文件无版本资源(如未在项目属性中设置“程序集信息”或未嵌入版本块),会返回默认值(如 0.0.0.0)且不抛异常 支持 .NET Framework 和 .NET Core / .NET 5+,但 .NET Core 3.1+ 中需引用
System.Diagnostics.FileVersionInfo命名空间(已内置,无需额外 NuGet)
FileVersionInfo.FileVersion
和 ProductVersion
的区别
同一个文件里常有两个关键字符串版本字段:
FileVersion(文件版本)和
ProductVersion(产品版本),它们在 Visual Studio 的“程序集信息”对话框中分别对应“文件版本”和“产品版本”输入框。
常见误区是只读
FileVersion,但有些发布流程(如 MSBuild 自动递增)实际更新的是
ProductVersion,而
FileVersion被固定为 1.0.0.0。
fileVersionInfo.FileVersion→ 对应
VS_VERSIONINFO.dwFileVersionMS/dwFileVersionLS
fileVersionInfo.ProductVersion→ 对应
VS_VERSIONINFO.dwProductVersionMS/dwProductVersionLS两者都是字符串形式(如
"2.1.3.0"),不是
Version类型,需手动
Version.Parse()才能比较
读取程序集版本(AssemblyVersion
)要换方式
如果你真正想获取的是 C# 编译时写死的
[assembly: AssemblyVersion("1.2.3.4")],那 FileVersionInfo不管用——它读不到 IL 元数据,只能读资源段。
此时必须加载程序集(注意:会触发 JIT 加载,有副作用),再查
AssemblyName.Version:
try
{
var asm = Assembly.LoadFrom(@"C:MyApplib.dll");
var version = asm.GetName().Version; // 这才是 AssemblyVersion
}
catch (BadImageFormatException)
{
// 非托管 DLL、架构不匹配(x86/x64)、.NET 版本不兼容时抛此异常
}
Assembly.LoadFrom会执行静态构造函数、触发类型初始化,慎用于生产环境读取第三方 DLL 若只需元数据不执行代码,可用
AssemblyLoadContext.Default.LoadFromAssemblyPath(.NET 5+)或
Assembly.ReflectionOnlyLoadFrom(旧版,仅限检查,不能调用) 对于当前正在运行的程序集,直接用
typeof(Program).Assembly.GetName().Version更安全
常见错误:路径不存在、权限不足、UAC 虚拟化干扰
调用
FileVersionInfo.GetVersionInfo时突然报
FileNotFoundException或返回空版本,大概率不是代码问题,而是路径或权限卡点。 检查路径是否含中文、空格、特殊符号;用
Path.GetFullPath规范化后再传入 Windows 应用商店应用(UWP)或受限制沙盒中无法访问任意磁盘路径,会静默失败 32 位进程尝试读取
C:Program Files下的 64 位程序时,可能被文件系统重定向到
Program Files (x86),或因 UAC 虚拟化把路径映射到用户配置目录 某些杀毒软件或 EDR 会 hook 文件读取 API,导致
GetVersionInfo返回空或异常——可先用
File.Exists确认文件可访问
版本信息本身不加密也不校验,读出来就是资源节里存的字符串。真要防篡改,得靠签名验证(
Assembly.GetName().GetPublicKeyToken()或 Authenticode)。
