使用反射获取程序集版本与DotPeek显示版本不一致问题求助
解决反射获取程序集版本与DotPeek显示不一致的问题
我之前在大型解决方案里也碰到过完全一样的坑!当时折腾了好半天,终于搞懂了问题所在,也找到了和DotPeek一样能拿到真实版本的方法。
问题根源:反射 vs DotPeek的本质区别
你用反射拿到的Assembly.GetName().Version或者ImageRuntimeVersion,都是运行时已加载到AppDomain中的程序集版本——而在大型解决方案里,配置文件里的绑定重定向、程序集影子复制这些机制,会让运行时加载的版本和磁盘上原始程序集的版本不一样。
但DotPeek不一样,它是静态解析磁盘上的程序集文件,直接读取PE文件里的CLR元数据(程序集清单部分),完全不受运行时绑定规则的影响,所以能拿到你需要的“真实版本”。
正确的解决方案:直接读取磁盘文件的版本
不用通过反射加载程序集,直接读取磁盘上的程序集文件元数据,就能得到和DotPeek一致的版本号。这里有两种常用方法:
方法1:获取程序集版本(和DotPeek显示的Assembly Version一致)
这个方法不会把程序集加载到当前AppDomain,完全是静态读取文件:
string assemblyFilePath = @"路径\到\你的程序集.dll"; // 直接从文件读取程序集名称和版本 AssemblyName assemblyName = AssemblyName.GetAssemblyName(assemblyFilePath); Version realAssemblyVersion = assemblyName.Version; Console.WriteLine($"真实程序集版本:{realAssemblyVersion}");
方法2:获取文件版本(如果需要的是File Version)
有些程序集的文件版本和程序集版本不一致,如果你要的是文件版本,可以用这个:
string assemblyFilePath = @"路径\到\你的程序集.dll"; FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(assemblyFilePath); string realFileVersion = fileVersionInfo.FileVersion; Console.WriteLine($"真实文件版本:{realFileVersion}");
为什么之前的反射方法不行?
你试过的那些反射方法,都是基于已加载到内存的程序集:
- 如果解决方案里配置了绑定重定向,运行时会自动把旧版本的程序集重定向到新版本,反射拿到的就是重定向后的版本;
- 有些Web项目或者使用影子复制的场景,程序集会被复制到临时目录再加载,反射拿到的是复制后的文件版本;
- 还有些程序集是延迟加载的,运行时还没加载,反射根本拿不到对应的实例。
而直接读取磁盘文件的方式,完全避开了这些运行时机制,和DotPeek的原理一致,自然能拿到正确的版本号。
内容的提问来源于stack exchange,提问作者Fals
相关产品推荐
相关产品推荐

