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

PowerShell 5.1与7的证书操作差异及脚本兼容问题咨询

PowerShell 5.1与7的差异及脚本运行失败原因分析

我编写了一段脚本,可在PowerShell 7中正常运行,但需要适配PowerShell 5.1。我已安装System.IdentityModel.Tokens.Jwt 7.0.3包,并将脚本依赖的DLL复制到了脚本目录。在PowerShell 7中执行new-object Microsoft.IdentityModel.Tokens.X509SigningCredentials($x509cert)能正常输出,但在PowerShell 5.1中会抛出以下错误:

System.Management.Automation.MethodInvocationException: Exception calling ".ctor" with "1" argument(s): "The type initializer for 'PerTypeValues`1' threw an exception." ---> System.TypeInitializationException: The type initializer for 'PerTypeValues`1' threw an exception. ---> System.IO.FileNotFoundException: Could not load file or assembly 'System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
   at System.SpanHelpers.PerTypeValues`1.MeasureArrayAdjustment()
   at System.SpanHelpers.PerTypeValues`1..cctor()
   --- End of inner exception stack trace ---
   at Microsoft.IdentityModel.Tokens.Base64UrlEncoder.Encode(Byte[] inArray, Int32 offset, Int32 length)
   at Microsoft.IdentityModel.Tokens.X509SecurityKey..ctor(X509Certificate2 certificate)
   at Microsoft.IdentityModel.Tokens.SigningCredentials..ctor(X509Certificate2 certificate)
   at Microsoft.IdentityModel.Tokens.X509SigningCredentials..ctor(X509Certificate2 certificate)
   --- End of inner exception stack trace ---
   at System.Management.Automation.DotNetAdapter.AuxiliaryConstructorInvoke(MethodInformation methodInformation, Object[] arguments, Object[] originalArguments)
   at System.Management.Automation.DotNetAdapter.ConstructorInvokeDotNet(Type type, ConstructorInfo[] constructors, Object[] arguments)
   at Microsoft.PowerShell.Commands.NewObjectCommand.CallConstructor(Type type, ConstructorInfo[] constructors, Object[] args)

想请教两个问题:

  1. 除底层依赖的.NET版本不同外,PowerShell 5.1和7还有哪些关键差异?
  2. 这段脚本无法在PowerShell 5.1运行的具体原因是什么?

脚本示例

$CertPassWord       = "password" # 证书密码
$CertificatePath_Pfx = "C:\Temp\Certs\test.pfx" # 证书保存路径

[System.Reflection.Assembly]::LoadFrom("C:\Temp\Certs\Microsoft.IdentityModel.Tokens.dll")

$x509cert = new-object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath_Pfx, $CertPassWord)
new-object Microsoft.IdentityModel.Tokens.X509SigningCredentials($x509cert)

一、PowerShell 5.1与7的核心差异(除.NET版本外)

  • 程序集加载机制:PowerShell 5.1基于.NET Framework,依赖全局程序集缓存(GAC)或本地目录,对.NET Core/.NET 5+程序集兼容性极差;PowerShell 7基于.NET(Core),采用现代化依赖解析,支持NuGet包依赖链自动加载。
  • API兼容性边界:PowerShell 7支持大量.NET Core专属新API,而5.1仅能调用.NET Framework兼容的API,部分.NET Core类型/方法在5.1中无法直接使用。
  • 程序集隔离性:PowerShell 7的程序集加载更独立,能避免版本冲突;5.1的加载逻辑易受GAC中旧版本程序集干扰。
  • 语法与功能扩展:PowerShell 7新增foreach-object -parallel、三元运算符?:等语法,但这不是当前问题的诱因。

二、脚本无法在PowerShell 5.1运行的原因

从错误信息看,核心问题是缺少依赖程序集System.Runtime.CompilerServices.Unsafe(版本4.0.4.1),具体诱因如下:

  1. 包版本兼容性不匹配:你使用的System.IdentityModel.Tokens.Jwt 7.0.3是针对.NET 6+编译的,它依赖的System.Runtime.CompilerServices.Unsafe是.NET Core专属程序集,而PowerShell 5.1底层的.NET Framework默认不包含该程序集,也无法直接加载。
  2. 依赖集复制不完整:你仅复制了Microsoft.IdentityModel.Tokens.dll,但该DLL依赖的其他.NET Core程序集(如System.Memory、System.Security.Cryptography.Xml等)未一并复制到脚本目录,PowerShell 5.1无法自动解析这些依赖链。
  3. API实现差异导致初始化失败:X509SigningCredentials的构造函数在.NET Core实现中使用了.NET Framework不支持的Span<T>相关API,而Span<T>必须依赖System.Runtime.CompilerServices.Unsafe,最终引发类型初始化异常。

解决建议

  • 降级NuGet包版本:改用针对.NET Framework编译的旧版本System.IdentityModel.Tokens.Jwt(如5.x系列,同时支持.NET Framework 4.6.1+和.NET Core),其依赖的程序集均与.NET Framework兼容。
  • 完整复制依赖程序集(不推荐):若坚持使用7.0.3版本,需将所有依赖的.NET Core程序集全部复制到脚本目录,还需通过app.config配置程序集绑定重定向,但这种方法稳定性极差,容易出现其他兼容问题。
  • 改用.NET Framework原生API:直接使用.NET Framework自带的JWT相关API,避免依赖.NET Core专属程序集。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 02:05:35