.NET 5发布后System.Security.Principal.Windows.dll缺失问题求助
我有一个包含多个项目的.NET 5解决方案,为实现Windows模拟功能,给其中一个项目添加了NuGet包System.Security.Principal.Windows。解决方案编译正常,调试时一切运行良好,但发布到文件系统后,System.Security.Principal.Windows.dll未被复制到发布目录。所有项目的目标框架均设置为net5.0-windows。
待发布项目的.csproj
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net5.0-windows</TargetFramework> <RollForward>Major</RollForward> <StartupObject>My.Special.Service.Program</StartupObject> <AssemblyVersion>7.0.0.0</AssemblyVersion> <FileVersion>7.0.0.42</FileVersion> <Version>7.0.0.42</Version> </PropertyGroup> ... <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PlatformTarget>x64</PlatformTarget> </PropertyGroup> <ItemGroup> <SupportedPlatform Include="windows" /> </ItemGroup> <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.Authentication.Negotiate" Version="5.0.17" /> <PackageReference Include="Microsoft.AspNetCore.Buffering" Version="0.2.2" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.17" /> <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="5.0.17" /> <PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" /> <PackageReference Include="Serilog.AspNetCore" Version="5.0.0" /> <PackageReference Include="Serilog.Extensions.Logging.File" Version="2.0.0" /> <PackageReference Include="Serilog.Sinks.Seq" Version="5.1.1" /> </ItemGroup> ... </Project>
依赖System.Security.Principal.Windows的项目的.csproj
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net5.0-windows</TargetFramework> <RollForward>Major</RollForward> <RootNamespace>My.Special.Service.ComAccess</RootNamespace> <AssemblyName>My.Special.Service.ComAccess</AssemblyName> </PropertyGroup> <ItemGroup> <SupportedPlatform Include="windows" /> </ItemGroup> <ItemGroup> <PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="6.0.0" /> <PackageReference Include="System.Security.Principal.Windows" Version="5.0.0" /> </ItemGroup> ... </Project>
发布配置文件
<?xml version="1.0" encoding="utf-8"?> <!-- https://go.microsoft.com/fwlink/?LinkID=208121. --> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <DeleteExistingFiles>True</DeleteExistingFiles> <ExcludeApp_Data>False</ExcludeApp_Data> <LaunchSiteAfterPublish>True</LaunchSiteAfterPublish> <LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration> <LastUsedPlatform>Any CPU</LastUsedPlatform> <PublishProvider>FileSystem</PublishProvider> <PublishUrl>bin\publish\Release</PublishUrl> <WebPublishMethod>FileSystem</WebPublishMethod> <SiteUrlToLaunchAfterPublish /> <TargetFramework>net5.0-windows</TargetFramework> <RuntimeIdentifier>win-x64</RuntimeIdentifier> <ProjectGuid>...</ProjectGuid> <SelfContained>false</SelfContained> </PropertyGroup> </Project>
核心原因
当目标框架为net5.0-windows时,System.Security.Principal.Windows属于.NET 5 Windows平台的框架内置组件,你安装的NuGet包会被框架本身的版本替代。在非独立发布(SelfContained=false)模式下,框架相关DLL不会被复制到发布目录——.NET运行时会直接调用系统全局安装的框架文件。而调试时能正常运行,是因为VS开发环境会自动处理依赖加载逻辑。
解决方式1:强制复制依赖项
在依赖System.Security.Principal.Windows的项目(即My.Special.Service.ComAccess)的.csproj中,添加配置强制MSBuild将该DLL复制到输出目录:
<ItemGroup> <PackageReference Include="System.Security.Principal.Windows" Version="5.0.0"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> </ItemGroup>
或者更直接添加复制指令:
<ItemGroup> <Reference Include="System.Security.Principal.Windows"> <Private>True</Private> </Reference> </ItemGroup>
解决方式2:切换为独立发布模式
修改发布配置文件中的SelfContained属性为true,这样.NET运行时和所有依赖框架DLL都会被打包到发布目录:
<SelfContained>true</SelfContained>
注意:独立发布会增大包体积,但无需目标机器预先安装.NET 5运行时。
解决方式3:移除冗余NuGet包
对于net5.0-windows,Windows身份模拟相关API(如WindowsIdentity、WindowsImpersonationContext)已经内置在框架中,无需额外安装NuGet包。直接移除该包引用,改用框架内置类型即可解决问题。
内容的提问来源于stack exchange,提问作者sawie

