兼容PowerShell 5.1与7.1.4的C#模块使用System.Text.Json问题问询
解决方案
1. 简便实现方案
你遇到的报错本质是Windows PowerShell 5.1作为.NET Framework宿主,不会读取你的类库生成的绑定重定向配置,导致System.Text.Json依赖的System.Runtime.CompilerServices.Unsafe程序集加载失败,最简单的修复方案如下:
- 给你的项目添加
Costura.FodyNuGet包引用,仅针对net461目标框架生效,它会自动把所有依赖(包括System.Text.Json、System.Runtime.CompilerServices.Unsafe等)嵌入到你生成的cmdlet程序集中,完全规避程序集加载缺失问题 - 临时测试也可以直接在net461的publish目录下,手动将
System.Runtime.CompilerServices.Unsafe.dll复制进去,同时在模块加载时注册AppDomain.CurrentDomain.AssemblyResolve事件,手动处理程序集版本匹配:
# 放在模块初始化脚本中 Add-Type -TypeDefinition @" using System; using System.Reflection; public static class AssemblyResolver { public static void Register() { AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { if (args.Name.StartsWith("System.Runtime.CompilerServices.Unsafe")) { return Assembly.LoadFrom(System.IO.Path.Combine(System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "System.Runtime.CompilerServices.Unsafe.dll")); } return null; }; } } "@ [AssemblyResolver]::Register()
2. 跨版本单模块适配方案
完全可以打造同时适配两个PowerShell版本的单模块,标准目录结构如下:
sopost/ # 模块根目录,名称和模块名一致 ├── sopost.psd1 # 模块清单文件 ├── lib/ │ ├── net461/ # 存放Windows PowerShell 5.1使用的程序集 │ │ ├── sopost.dll │ │ ├── System.Text.Json.dll │ │ └── System.Runtime.CompilerServices.Unsafe.dll │ └── netcoreapp2.0/ # 存放PowerShell 7+使用的程序集 │ ├── sopost.dll │ └── System.Text.Json.dll └── sopost.psm1 # 根模块脚本,处理不同版本的程序集加载
你需要在sopost.psm1中添加版本判断逻辑:
$runtimeDir = if ($PSVersionTable.PSVersion.Major -ge 6) { Join-Path $PSScriptRoot "lib/netcoreapp2.0" } else { Join-Path $PSScriptRoot "lib/net461" } Import-Module (Join-Path $runtimeDir "sopost.dll")
同时修改psd1清单的RootModule为sopost.psm1即可,两个版本的PowerShell导入时会自动加载对应运行时的程序集。
3. Windows PowerShell 5.1使用System.Text.Json的可行性
完全可以开发,核心要解决两个问题:
- 程序集依赖加载:要么用嵌入依赖的方式(Costura.Fody),要么手动处理程序集解析事件,避免.NET Framework宿主的绑定重定向不生效问题
- 版本兼容:System.Text.Json 5.0.0本身支持.NET Framework 4.6.1+,只要解决依赖加载问题,所有功能都可以正常使用,不需要额外修改业务代码。
内容的提问来源于stack exchange,提问作者PshMike
相关产品推荐
相关产品推荐

