samples
samples copied to clipboard
PackageReference in msbuild\custom-task-code-generation\AppSettingStronglyTyped is not working
Issue description
The approaches used in the AppSettingStronglyTyped example no longer work for using NuGet packages in projects with MSBuild Tasks. When creating a package containing MSBuild Tasks, you cannot use NuGet packages as in a regular ClassLibrary project; NuGet packages, or more precisely the dlls supplied with them, must be bundled with the final package.
To achieve these goals, AppSettingStronglyTyped uses CopyProjectReferencesToPackage
Target:
https://github.com/dotnet/samples/blob/d51488ecd50cf8dc774bdb0e0e6e2044bbe5ba5e/msbuild/custom-task-code-generation/AppSettingStronglyTyped/AppSettingStronglyTyped/AppSettingStronglyTyped.csproj#L41-L48
However, Microsoft.Extensions.DependencyInjection.dll
is not included in the final package.
I expect that after running dotnet package
.nupkg will have tasks\netstandard2.0\Microsoft.Extensions.DependencyInjection.dll
, but it doesn't. Which leads to an error loading the library during the build:
System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'.
Steps to reproduce
Sample to reproduce https://github.com/Tripletri/samples/pull/1, integration tests is falling on this commit.
Other thoughts
Since CopyProjectReferencesToPackage
use ReferenceCopyLocalPathsReferenceCopyLocalPaths
and @(ReferenceCopyLocalPaths)
is always empty, this may relate to https://github.com/dotnet/sdk/issues/3662.
As a workaround, I simply commit the external DLLs, reference them with <Reference>
and manually copy them at build time.
First of all, I'm interested in how to achieve this use of PackageReference in projects with MSBuild Tasks, especially with multi-targeting, since manually managing dependencies for all target frameworks is a headache.
Thanks in advice
Target framework
- [x] .NET Standard2.0
dotnet --info output
.NET SDK:
Version: 8.0.101
Commit: 6eceda187b
Workload version: 8.0.100-manifests.0f7d8591
Runtime Environment:
OS Name: Windows
OS Version: 10.0.19045
OS Platform: Windows
RID: win-x64
Base Path: C:\Program Files\dotnet\sdk\8.0.101\
.NET workloads installed:
Workload version: 8.0.100-manifests.0f7d8591
There are no installed workloads to display.
Host:
Version: 8.0.1
Architecture: x64
Commit: bf5e279d92
.NET SDKs installed:
2.1.202 [C:\Program Files\dotnet\sdk]
2.2.402 [C:\Program Files\dotnet\sdk]
3.1.426 [C:\Program Files\dotnet\sdk]
5.0.408 [C:\Program Files\dotnet\sdk]
6.0.321 [C:\Program Files\dotnet\sdk]
6.0.418 [C:\Program Files\dotnet\sdk]
7.0.115 [C:\Program Files\dotnet\sdk]
7.0.203 [C:\Program Files\dotnet\sdk]
8.0.100 [C:\Program Files\dotnet\sdk]
8.0.101 [C:\Program Files\dotnet\sdk]
.NET runtimes installed:
Microsoft.AspNetCore.All 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.26 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 7.0.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 7.0.15 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 8.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 8.0.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.26 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.26 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 7.0.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 7.0.15 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 8.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 8.0.1 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Other architectures found:
x86 [C:\Program Files (x86)\dotnet]
registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]
Environment variables:
Not set
global.json file:
Not found
Learn more:
https://aka.ms/dotnet/info
Download .NET:
https://aka.ms/dotnet/download
You can somewhat work around this issue by adding this line to .csproj of the nuget project
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
You can somewhat work around this issue by adding this line to .csproj of the nuget project
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
Thanks for the tip. With this approach, Microsoft.Build.Framework.dll, Microsoft.Build.Utilities.Core.dll, etc. are also included, judging by the comments in the example project, we want to avoid this
You can somewhat work around this issue by adding this line to .csproj of the nuget project
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
Thanks for the tip. With this approach, Microsoft.Build.Framework.dll, Microsoft.Build.Utilities.Core.dll, etc. are also included, judging by the comments in the example project, we want to avoid this
The README on the project seems a bit outdated. Here's a different version that should address this issue. The trick is to add ExcludeAssets="Runtime"
to the Microsoft.Build.Utilities.Core PackageReference
https://github.com/MicrosoftDocs/visualstudio-docs/blob/main/docs/msbuild/tutorial-custom-task-code-generation.md
Yes, seems like a good solution, thanks @horato
Solution
- Add
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
- Add
ExcludeAssets="Runtime"
toMicrosoft.Build.Utilities.Core
Final .csproj file should look like this:
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<version>1.0.0</version>
<title>AppSettingStronglyTyped</title>
<authors>John</authors>
<description>Generates a strongly typed setting class base on a txt file</description>
<tags>MyTags</tags>
<copyright>Copyright ©Contoso 2022</copyright>
<!-- we need the assemblies bundled, so set this so we don't expose any dependencies to the outside world -->
<GenerateDependencyFile>true</GenerateDependencyFile>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
<!-- This property tells MSBuild where the root folder of the package's build assets should be. Because we are not a library package, we should not pack to 'lib'. Instead, we choose 'tasks' by convention. -->
<BuildOutputTargetFolder>tasks</BuildOutputTargetFolder>
<!-- NuGet does validation that libraries in a package are exposed as dependencies, but we _explicitly_ do not want that behavior for MSBuild tasks. They are isolated by design. Therefore we ignore this specific warning. -->
<NoWarn>NU5100</NoWarn>
<DebugType>embedded</DebugType>
<IsPackable>true</IsPackable>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
<ItemGroup>
<PackageReference
Include="Microsoft.Build.Utilities.Core"
Version="17.0.0"
PrivateAssets="all"
ExcludeAssets="runtime"
/>
<PackageReference
Include="Microsoft.Extensions.DependencyInjection"
Version="6.0.0"
PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<!-- These lines pack the build props/targets files to the `build` folder in the generated package.
By convention, the .NET SDK will look for build\<Package Id>.props and build\<Package Id>.targets
for automatic inclusion in the build. -->
<Content Include="build\AppSettingStronglyTyped.props" PackagePath="build\" />
<Content Include="build\AppSettingStronglyTyped.targets" PackagePath="build\" />
</ItemGroup>
<Target Name="CopyProjectReferencesToPackage" DependsOnTargets="ResolveReferences">
<ItemGroup>
<!-- The dependencies of your MSBuild task must be packaged inside the package, they cannot be expressed as normal PackageReferences -->
<BuildOutputInPackage
Include="@(ReferenceCopyLocalPaths)"
TargetPath="%(ReferenceCopyLocalPaths.DestinationSubPath)" />
</ItemGroup>
</Target>
<!-- This target adds the generated deps.json file to our package output -->
<Target Name="AddBuildDependencyFileToBuiltProjectOutputGroupOutput"
BeforeTargets="BuiltProjectOutputGroup"
Condition=" '$(GenerateDependencyFile)' == 'true'">
<ItemGroup>
<BuiltProjectOutputGroupOutput
Include="$(ProjectDepsFilePath)"
TargetPath="$(ProjectDepsFileName)"
FinalOutputPath="$(ProjectDepsFilePath)" />
</ItemGroup>
</Target>
P.S. I don't want to close the issue until the documentation is updated