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

PowerShell 5.1导入同程序集多版本无报错仅首个生效原因求解

核心前提

所有现象的核心根源是你使用的是未强签名的弱命名程序集,PowerShell 5.1基于.NET Framework运行,所有行为都遵循.NET Framework的程序集加载规则。

Q1 为什么第二次导入不报错?第二个版本是否被加载?

  • .NET Framework的AppDomain加载逻辑中,弱命名程序集仅通过简单名称做唯一性判定:只要当前AppDomain中已经加载过同名的弱命名程序集,后续不管你尝试加载什么版本、什么路径的同名弱命名程序集,CLR都会直接忽略加载请求,返回已加载的程序集实例,不会抛出任何错误。
  • Import-Module导入二进制dll时,默认会将程序集加载到默认加载上下文(Default Load Context),你第二次调用导入命令时,CLR已经判定同名弱命名程序集存在,因此第二个版本的dll根本没有被加载,只是Import-Module本身没有针对无清单二进制模块做版本冲突校验,所以没有返回错误。
  • 如果你使用强签名程序集测试,就会符合你原本的认知:同AppDomain无法加载两个不同版本的同名强签名程序集,第二次加载会直接抛出冲突异常。

Q2 为什么Get-Module会显示两个同版本的重复条目?

  • Import-Module的模块记录逻辑和CLR的程序集加载逻辑是完全独立的两套机制:每次调用Import-Module时,只要没有指定-Force参数、也没有检测到同名称同版本的模块已存在,就会新增一条模块记录。
  • 由于你的程序集没有声明[assembly: AssemblyFileVersion]属性,PowerShell读取模块版本时会直接复用当前AppDomain中已加载的同名程序集的版本号,因此两条模块记录的版本都是最早导入的版本号,看起来就是完全重复的两条条目。
  • 实际调用类型、方法时走的是CLR的类型解析逻辑,永远只会命中最早加载的程序集,因此只有第一个版本的逻辑生效。

Q3 为什么没有出现依赖冲突?

  • 主程序集的依赖加载同样遵循.NET Framework的弱命名程序集加载规则:第一个版本的MyAssembly.dll加载时,它依赖的次级弱命名程序集已经被加载到AppDomain中,后续第二个版本的主程序集尝试加载对应版本的依赖时,CLR发现同名弱命名程序集已存在,会直接复用已加载的版本,根本不会去读取第二个版本的依赖dll,自然不会触发依赖冲突。
  • 你测试Microsoft.CodeAnalysis.CSharp.dll得到相同结果,也是因为同样的加载逻辑:已加载的程序集优先级最高,弱命名程序集仅匹配简单名称,不会校验版本。

遗漏的核心知识点

  • 弱命名程序集和强命名程序集的加载规则差异:弱命名仅校验名称,强命名需要校验名称、版本、公钥Token、文化四个维度的完整标识
  • PowerShell的模块记录(Get-Module返回的内容)仅代表Import-Module的调用记录,不代表CLR实际加载了对应版本的程序集
  • .NET Framework的AppDomain程序集加载特性:程序集一旦加载到AppDomain中,除非卸载整个AppDomain,否则无法移除,同AppDomain内的程序集去重规则完全由CLR控制,和PowerShell的模块逻辑无关
  • 无模块清单(.psd1)的二进制dll作为PowerShell模块导入时,PowerShell的版本校验逻辑非常宽松,不会主动做版本冲突检测。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 17:30:01