为何Visual Studio 2022创建的WPF项目中System.ServiceModel无法工作
场景与问题
我在Visual Studio 2022创建的.NET 6 WPF应用中,执行以下WCF命名管道通信代码时出现异常:
var pipeFactory = new ChannelFactory<IWCFStarter>(new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/someadress")); IWCFStarter pipeChannel = pipeFactory.CreateChannel(); bool result = false; result = pipeChannel.UpdateArcGISProAddOn("ARCBAR", "{294628d0-3e47-4c2a-8b0c-a14fb5496711}");
这段代码在旧版Visual Studio创建的.NET Framework WPF应用中可正常运行,但在新项目中抛出如下异常:
System.BadImageFormatException HResult=0x80131058 Message=Could not load file or assembly 'System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. Reference assemblies should not be loaded for execution. They can only be loaded in the Reflection-only loader context. (0x80131058) Source=ARCBARUnittests Inner Exception 1: BadImageFormatException: Cannot load a reference assembly for execution.
项目的.csproj内容如下:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>WinExe</OutputType> <TargetFramework>net6.0-windows</TargetFramework> <Nullable>enable</Nullable> <UseWPF>true</UseWPF> <NeutralLanguage>de-AT</NeutralLanguage> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <TreatWarningsAsErrors>True</TreatWarningsAsErrors> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <TreatWarningsAsErrors>True</TreatWarningsAsErrors> </PropertyGroup> <ItemGroup> <ProjectReference Include="..\..\Landesversionsdienst\WCFContracts\WCFContracts.csproj" /> <ProjectReference Include="..\Framework\AdresssucheUT\AdresssucheUT.csproj" /> <ProjectReference Include="..\Framework\Adresssuche\Adresssuche.csproj" /> <ProjectReference Include="..\Framework\ExceptionHandlingUT\ExceptionHandlingUT.csproj" /> <ProjectReference Include="..\Framework\LoggingUT\LoggingUT.csproj" /> <ProjectReference Include="..\Framework\MyStringToolsUT\MyStringToolsUT.csproj" /> <ProjectReference Include="..\Framework\OSToolsUT\OSToolsUT.csproj" /> <ProjectReference Include="..\Framework\RadBaseGUIElementsUT\RadBaseGUIElementsUT.csproj" /> <ProjectReference Include="..\Framework\RadWeb\RadWeb.csproj" /> </ItemGroup> <ItemGroup> <Reference Include="System.ServiceModel"> <HintPath>..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.ServiceModel.dll</HintPath> </Reference> </ItemGroup> </Project>
我尝试移除上述System.ServiceModel引用并安装NuGet包System.ServiceModel.NetNamedPipe,代码可编译但运行时抛出新异常:
Could not load file or assembly 'System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. The system cannot find the file specified.
安装System.ServiceModel.Primitives等相关NuGet包后,问题仍未解决。
原因分析
引用程序集无法在.NET 6运行时加载
直接引用的是.NET Framework 4.8的System.ServiceModel.dll,这是一个引用程序集,仅用于编译时校验,不能在.NET 6的运行时环境中执行,因此触发BadImageFormatException。依赖项目的.NET Framework版本冲突
项目引用的WCFContracts.csproj等类库可能仍基于.NET Framework开发,依赖的是.NET Framework版本的System.ServiceModel 4.0.0.0,而主项目安装的是.NET 6兼容的NuGet包,导致运行时无法找到匹配的程序集版本。
解决方案
1. 彻底移除.NET Framework版System.ServiceModel引用
删除.csproj文件中以下节点:
<ItemGroup> <Reference Include="System.ServiceModel"> <HintPath>..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.ServiceModel.dll</HintPath> </Reference> </ItemGroup>
2. 迁移依赖类库到.NET 6或配置兼容的WCF包
检查所有引用的项目(尤其是WCFContracts.csproj):
- 若这些项目仍基于.NET Framework,将其目标框架修改为
net6.0-windows,并在这些项目中安装System.ServiceModel.Primitives和System.ServiceModel.NetNamedPipeNuGet包。 - 若无法迁移,确保这些项目的程序集绑定重定向配置正确,将
System.ServiceModel重定向到.NET 6兼容的版本。
3. 正确安装WCF NuGet包
在主WPF项目和所有依赖的类库中,安装以下官方NuGet包:
System.ServiceModel.PrimitivesSystem.ServiceModel.NetNamedPipe
这些包是.NET Core/.NET 5+平台下官方提供的WCF客户端实现,完全兼容.NET 6。
4. 添加程序集绑定重定向(可选)
如果仍存在版本冲突,在项目的app.config文件中添加绑定重定向,将旧版本的System.ServiceModel重定向到NuGet包提供的版本:
<configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="System.ServiceModel" publicKeyToken="b77a5c561934e089" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="6.0.0.0" /> </dependentAssembly> </assemblyBinding> </runtime> </configuration>
内容的提问来源于stack exchange,提问作者Gener4tor

