从PowerShell 5迁移至7:无法加载System.ServiceModel.Web v4.0.0.0中的类型
PowerShell 7.3.6迁移中System.ServiceModel.Web类型加载失败问题
近期从PowerShell 5.1迁移至7.3.6版本,多数脚本运行正常,但有一个调用.NET类的脚本出现异常:无法加载目标类,报错信息如下:
System.Management.Automation.ExtendedTypeSystemException: The following exception occurred while retrieving member "Parse": "Could not load type 'System.ServiceModel.Web.WebInvokeAttribute' from assembly 'System.ServiceModel.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'." ---> System.TypeLoadException: Could not load type 'System.ServiceModel.Web.WebInvokeAttribute' from assembly 'System.ServiceModel.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. at System.ModuleHandle.ResolveType(QCallModule module, Int32 typeToken, IntPtr* typeInstArgs, Int32 typeInstCount, IntPtr* methodInstArgs, Int32 methodInstCount, ObjectHandleOnStack type) at System.ModuleHandle.ResolveTypeHandle(Int32 typeToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext) at System.Reflection.RuntimeModule.ResolveType(Int32 metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) at System.Reflection.CustomAttribute.FilterCustomAttributeRecord(MetadataToken caCtorToken, MetadataImport& scope, RuntimeModule decoratedModule, MetadataToken decoratedToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, ListBuilder`1& derivedAttributes, RuntimeType& attributeType, IRuntimeMethodInfo& ctorWithParameters, Boolean& isVarArg) at System.Reflection.CustomAttribute.AddCustomAttributes(ListBuilder`1& attributes, RuntimeModule decoratedModule, Int32 decoratedMetadataToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, ListBuilder`1 derivedAttributes) at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, Int32 pcaCount, RuntimeType attributeFilterType) at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeMethodInfo method, RuntimeType caType, Boolean inherit) at System.Management.Automation.DotNetAdapter.MethodCacheEntry.get_IsHidden() at System.Management.Automation.DotNetAdapter.GetDotNetMethodImpl[T](Object obj, String methodName, MemberNamePredicate predicate) at System.Management.Automation.DotNetAdapter.GetDotNetMethod[T](Object obj, String methodName) at System.Management.Automation.Adapter.BaseGetMember[T](Object obj, String memberName) --- End of inner exception stack trace --- at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception) at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame) at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame) at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
使用Add-Type命令也无法解决该问题,且同一脚本在PowerShell 5.1环境中可正常运行。
问题原因
PowerShell 7基于.NET 6+运行时,而System.ServiceModel.Web是.NET Framework专属的程序集,.NET Core/.NET 5+生态中已移除该组件,转而采用ASP.NET Core的现代Web开发组件,这是导致类型加载失败的核心原因。
解决方法
1. 安装.NET Framework兼容包(Windows平台适用)
通过NuGet获取System.ServiceModel.Web的兼容包,手动加载程序集:
# 首次运行安装兼容包,指定CurrentUser范围 Install-Package System.ServiceModel.Web -ProviderName NuGet -Scope CurrentUser # 定位并加载程序集 $packagePath = (Get-Package System.ServiceModel.Web).Source Add-Type -Path (Join-Path $packagePath 'lib/net40/System.ServiceModel.Web.dll')
此方法仅适用于Windows系统,无法在跨平台场景下使用。
2. 重构脚本适配.NET 6+标准
如果需要跨平台支持,建议重构脚本逻辑:
- 替换
WebInvokeAttribute为ASP.NET Core中的[HttpPost]/[HttpGet]等路由特性 - 原WCF REST调用逻辑改用
HttpClient或Microsoft.AspNetCore.Mvc相关组件实现 - 序列化/反序列化操作替换为
System.Text.Json或Newtonsoft.Json
3. 临时切换至.NET Framework运行时(不推荐长期使用)
若暂时无法重构脚本,可通过环境变量强制PowerShell 7使用.NET Framework运行:
$env:DOTNET_ROLL_FORWARD_3=0 pwsh -UseWindowsPowerShell
该方式本质上是调用PowerShell 5.1的运行环境,无法利用PowerShell 7的新特性。
内容的提问来源于stack exchange,提问作者Vadim Berman
相关产品推荐
相关产品推荐

