Assembly.GetExecutingAssembly() 是获取当前程序集名称和版本最直接安全的方式,它不依赖路径,返回调用代码所在程序集,但需注意与 GetCallingAssembly() 区分,且其 Version 属性仅为四段数字,语义化版本需通过 AssemblyInformationalVersionAttribute 获取。
用 Assembly.GetExecutingAssembly() 获取当前程序集信息最直接
多数时候你只是想知道自己写的这个 dll 或 exe 叫什么、版本多少,assembly.getexecutingassembly() 是最轻量、最不容易出错的选择。它不依赖路径、不查文件系统,直接从运行时上下文拿元数据。
常见错误是误用 Assembly.GetCallingAssembly() —— 它返回的是调用栈上一层的程序集,比如你在 NuGet 包里封装了这个逻辑,那拿到的就不是你的主程序集。
- 在控制台或 WinForms 主程序里,
GetExecutingAssembly()返回的就是 .exe 对应的程序集 - 在类库(.dll)中调用,返回的是该 .dll 的程序集,不是引用它的宿主
- 如果在 ASP.NET Core 中使用,注意中间件或控制器里调用仍有效,但别在静态构造函数里提前触发(可能引发初始化顺序问题)
示例:
var asm = Assembly.GetExecutingAssembly(); string name = asm.GetName().Name; // 如 "MyApp" string version = asm.GetName().Version.ToString(); // 如 "2.1.0.0"
AssemblyName 的 Version 字段不是语义化版本
.NET 程序集版本号是 4 段纯数字(Major.Minor.Build.Revision),和你在 AssemblyInfo.cs 或 csproj 里写的 Version 属性不是一回事。如果你设置了 <version>1.2.3-beta</version>,生成的程序集版本仍是自动计算的 4 段数字(除非显式设了 AssemblyVersion)。
这意味着:asm.GetName().Version 永远不会包含 -beta 这类后缀,也永远不会是 1.2.3 这样的三段格式。
- 要读取语义化版本,得看
Assembly.GetCustomAttribute<assemblyinformationalversionattribute>()</assemblyinformationalversionattribute> -
AssemblyVersion控制强名称签名和绑定策略,改了可能导致FileNotFoundException -
AssemblyFileVersion和AssemblyInformationalVersion只影响文件属性和显示,不影响运行时加载
跨平台读取时注意 Assembly.Location 可能为空
在 .NET Core / .NET 5+ 上,尤其是发布为单文件(publish-self-contained true)或使用 ReadyToRun 时,asm.Location 常常是空字符串。这时候别指望靠它去解析路径再读取 Assembly.LoadFrom() —— 会直接抛 ArgumentException。
正确做法是:只要不需要动态加载别的程序集,就完全绕过 Location。所有元数据(名称、版本、特性)都可通过 GetName() 和 GetCustomAttribute() 直接获取,不依赖磁盘路径。
- 不要写
Assembly.LoadFrom(asm.Location)—— 多余且危险 - 若真需从文件加载,优先用
AssemblyLoadContext.Default.LoadFromAssemblyPath(),并先检查Location是否非空 - 在 Blazor WebAssembly 中,
Location总是空,这是设计使然,不是 bug
读取第三方程序集要用 AssemblyLoadContext 而非 Assembly.LoadFile
想读一个外部 DLL(比如插件)的名称和版本?别用已淘汰的 Assembly.LoadFile() —— 它会把程序集加载进默认上下文,可能引发类型冲突或无法卸载。.NET Core+ 推荐用 AssemblyLoadContext 隔离加载。
容易忽略的一点:即使只读元数据,LoadFromStream() 也会触发 JIT 编译部分类型,如果 DLL 依赖缺失的 native 库或特定运行时,仍可能失败。
- 用
AssemblyLoadContext.CreateDefault(isCollectible: true)创建可卸载上下文 - 配合
File.ReadAllBytes(path)+LoadFromStream(),避免文件锁 - 读完立刻调用
context.Unload(),否则内存泄漏 - 别对同一个 DLL 多次调用
LoadFromStream()—— 即使上下文不同,也可能因内部缓存导致重复加载警告
版本号本身不敏感,但程序集名称里的公钥令牌(PublicKeyToken)在强命名场景下会影响匹配逻辑,这点常被跳过验证。










