MSBuild - one Package Reference interferes with loading a separate Task - c#

Using MSBuild, the following builds and works fine:
<PackageReference Include="Publicise.MSBuild.Task" Version="1.3.0"/>
<Target Name="Publicise" BeforeTargets="BeforeBuild">
<Publicise
AssemblyPath="..."
OutputPath="../"/>
</Target>
However, when I add another Package Reference (changing nothing else), it encounters errors on build:
<PackageReference Include="Publicise.MSBuild.Task" Version="1.3.0"/>
<PackageReference Include="ILRepack.MSBuild.Task" Version="2.0.13"/>
This results in error MSB4062:
The "Publicise" task could not be loaded from the assembly ...\ILRepack.MSBuild.Task.dll. Confirm that the declaration is correct, that the assembly and all its dependencies are available, and that the task contains a public class that implements Microsoft.Build.Framework.ITask.
Why is something completely separate preventing the task from being properly found, and how can I fix this?

The issue is caused by these two msbuild task nuget packages accidentally.
And since you have installed the ILRepack.MSBuild.Task nuget package at the end. And the PackageReference node of ILRepack.MSBuild.Task is akways at the end. So $(TaskAssembly) is always loads from ILRepack.MSBuild.Task nuget package and the value from publicise.msbuild.task is being covered. And the issue The "Publicise" task could not be loaded from the assembly ILRepack.MSBuild.Task.dll makes sense.
C:\Users\xxx\.nuget\packages\publicise.msbuild.task\1.3.0\build\Publicise.MSBuild.Task.props
C:\Users\xxx\.nuget\packages\ilrepack.msbuild.task\2.0.13\build\ILRepack.MSBuild.Task.props
Also, when you project loads the nuget package, you can check under C:\xxx\source\repos\xxx(project_name)\xxx(project_name)\obj\xxx.csproj.nuget.g.props:
Loading the ILRepack.MSBuild.Task.props is always at the end and $(TaskAssembly) is always from ilrepack.msbuild.task due to being overwritten by the later installed package.
The error Publicise task(should be from publicise.msbuild.task) from ilrepack.msbuild.task could be understood.
Solution
So you should make publicise.msbuild.task at the end.
Solution 1)
open C:\xxx\source\repos\xxx(project_name)\xxx(project_name)\obj\xxx.csproj.nuget.g.props file,
modify like this:
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)ilrepack.msbuild.task\2.0.13\build\ILRepack.MSBuild.Task.props" Condition="Exists('$(NuGetPackageRoot)ilrepack.msbuild.task\2.0.13\build\ILRepack.MSBuild.Task.props')" />
<Import Project="$(NuGetPackageRoot)publicise.msbuild.task\1.3.0\build\Publicise.MSBuild.Task.props" Condition="Exists('$(NuGetPackageRoot)publicise.msbuild.task\1.3.0\build\Publicise.MSBuild.Task.props')" />
</ImportGroup>
make Publicise.MSBuild.Task.props at the buttom.
Then, save the changes and then click Build button rather than Rebuild button to test again.
Solution 2)
downgrade ILRepack.MSBuild.Task nuget package to version 2.0.0.
===============================
Update 1
Thanks for sharing your opinion about the workaround. Since these two nuget packages have to be used in your project, so these two solutions might not be very useful.
The error, conflict is caused by the author of the nuget packages and incidentally, you're using the same TaskAssembly property from these two nuget packages at the same time.
TreatAsLocalProperty="TaskAssembly" will not solve the issue. <packages_id>.props files from the nuget packages are still embedded in the project's CSPROj file. Whether the fields are the same as TaskAssembly or will conflict.
The better solution is that you should rename one of the TaskAssembly of the nuget packages to another, which would not cause conflict.
1) Open C:\Users\xxx\.nuget\packages\ilrepack.msbuild.task\2.0.13\build\ILRepack.MSBuild.Task.props file:
change TaskAssembly property to another like TaskAssembly_copy:

Related

Require .csproj nuget packages to exist when building solution

I'm creating an app to automatically update nuget packages in a solution and build it to be sure they are still compatible.
Scenario:
<PackageReference Include="Dapper" Version="1.50.5" />
Clean/Build package with correct package version. It Succeeds.
Then I edit the version in the .csproj with garbage text.
<PackageReference Include="Dapper" Version="dasdasdasdqw3" />
It still succeeds. However it does log the error:
Error occurred while restoring NuGet packages: Invalid restore input. Missing required property 'Name'.
My understanding is that it is using the previous successful version from the \.nuget\packages folder.
Is there a way to have the build fail if the package could not be restored that does not involve deleting it from \.nuget\packages?
Assume that you used a net core project.
First, make sure that you have enabled these two options under Tools-->Options-->Nuget Package Manager-->General:
Actually, when you change the version, vs will detect the change and use the current version and will not used the latest valid package under \.nuget\packages. In my side, it failed.
Right-click on your project Properties-->Unload project-->Edit Project File and then change from 1.50.5 to adadd. And then reload your project, you will find that the project has an invalid nuget version called asda.
It fails build process successfully. You should click Rebuild rather than Build button.
========
If you did not see the nuget package version displayed UI under solution explorer, you could unload the project and then reload your project. And wait for a moment to get the change.
Besides, you could add dotnet restore command under Project Properties-->Build Events-->Pre-Build event command line to make it more accurately.
To use the latest updated version automatically, you could use Floating Versions.
Try this:
<PackageReference Include="Dapper" Version="*" />
It will update the nuget package to use the latest version under nuget package source feed rather than the latest version from cache \.nuget\packages. When you reload your project, wait for a moment, and you will see the change to use the latest nuget version automatically.

.NET Core - Nuget Pack of UniTest Project shows warning "The assembly is not inside the 'lib' folder"

I'm trying to pack a UnitTest project as a Nuget package and I always get the following warning(s) if I build my project:
The assembly
'content\SpecFlow.MSDependencyInjection.SpecFlowPlugin.dll' is not
inside the 'lib' folder and hence it won't be added as a reference
when the package is installed into a project. Move it into the 'lib'
folder if it needs to be referenced.
My csproj file looks like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>0.1.0</Version>
<IsPackable>true</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Http" Version="2.2.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" />
<PackageReference Include="SpecFlow" Version="3.0.188" />
<PackageReference Include="SpecFlow.MSDependencyInjection.SpecFlowPlugin" Version="1.0.2" />
<PackageReference Include="SpecFlow.MsTest" Version="3.0.188" />
<PackageReference Include="SpecFlow.Tools.MsBuild.Generation" Version="3.0.188" />
</ItemGroup>
</Project>
The error still appears if I copy the files into the lib folder of the Nuget package. I'm at a loss what I need to change for this warning to disappear. To be frank I'm not even sure why it appears in the first place because I have a different project that works fine without this error.
Update 1:
After the detailed answer from #zivkan I changed my project structure so it is not a UnitTest project anymore.
Sadly the errors still appear if my project is a class library...
Screenshot with all Nuget-Packages that I need for my project to work
If I only add my own Nuget-Package that consists of two dependencies (Microsoft.Extensions.DependencyInjection and SpecFlow) it still produces this error but the two dependencies in this Nuget-Package don't. To me this seems to be a problem with the Nuget-Packages...
I'm not 100% sure, but my guess is that since with SDK style csproj files, when you build, only your assembly's dll is normally written to the output directory. When you run a non-test netcoreapp, the dotnet cli looks at what project references and nuget references you have, and configures the assembly loader to load from their "original" locations, rather than having all the assemblies copied to your app's bin folder. Perhaps the unit test framework doesn't support loading assemblies in this way and creates Content items out of each dll, which tells the build step to copy the content (in this case dlls) into the output directory (bin\$(Configuration)\$(TargetFramework)). Therefore, when you run unit tests, the unit test framework has all the required assemblies in the single directory, whereas that's normally not true for non-test projects.
Next you need to understand that when NuGet packs a project, it looks for MSBuild items of the type Content, and puts copies of them in the nupkg's content and contentFiles directories. Due to how NuGet works, only dlls in the lib\ or ref\ directories within the nupkg are given to the compiler, therefore any dlls you have a content directory will not be passed to the compiler, so your project that references this nupkg cannot use classes in those dlls. This is not how people usually intend to use NuGet packages and therefore NuGet generates a warning.
So, I believe the reason you're getting this warning is because you're packing a project type that is not intended to be packable. The project type does some uncommon things in order to work, which triggers NuGet warnings because typically when this uncommon thing is done, it's a mistake.
I believe this to be a case of a XY problem. I assume you're packing a unit test project because you want to share some utility code useful for tests, maybe some mocks or object initialisation code. In this case, I recommend you create a new classlib project, put your shared code in there, leaving all your test cases in your netcoreapp test project, even if it's nothing more than a single method call into the classlib. This way you can pack and share the classlib without warnings. Packing a unit test seems unusual and it would be interesting to discuss why you want to do this, what problem do you intend to solve and if packing a test is really the best way to achieve it. Unfortunately Stack Overflow isn't a good place to have discussions and is often actively discouraged.
perhaps you have missed a file, please follow this link for full details : https://learn.microsoft.com/en-us/nuget/create-packages/creating-a-package#Package_Conventions

How to prevent Visual Studio's Nuget Consolidate from operating on a particular project? [duplicate]

Is there a way to disable updates of specific nuget packages installed in a project?
I have made some local modifications to a couple of javascript library packages and do not want to run the risk of someone updating over the top of my changes in the future.
I've never created my own nuget package, I'm guessing one option might be to fork the existing packages?
You could try constraining the package so it your project will only allow a particular version to be used. Then all updates to any newer version will be prevented.
You can do this by editing your project's package.config file. For example, the line below should only allow version 2.1.0 to be used.
<package id="SomePackage" version="2.1.0" allowedVersions="[2.1.0]" />
I don't have a package.config. (VS 2019, .NET Core 3.1) What I did instead was changing the .csproj of the project which had the package which I needed to stop showing up for updates.
In my case it was EPPlus, and I wrapped the version number within square brackets.
<ItemGroup>
<PackageReference Include="EPPlus" Version="[4.5.3.3]" />
</ItemGroup>
After that, it stopped showing up on the Updates tab in Nuget Package Manager.
And it doesn't give any option to update from anywhere else too. (Installed tab, Nuget for the solution, etc)
You'll need to restart VS to get rid of the yellow triangles next to the packages.
EDIT:
WARNING: Please note that this work only for "Manage nuget packages for [project]" (which is rarelly used), not "Manage nuget packages for Solution" (which is the one you use every other day). See comments.
So this is no solution at all. I will keep it here for some random googlers who will try this, but it is almost useless.
For PackageReference you can block update on single version like this:
<PackageReference Include="IdentityServer4.AspNetIdentity">`
<Version>[3.1.1]</Version>
</PackageReference>
For some reason it have to be in own element and not in attribute, so you are stuck with editing your .csproj by hand.
VS2019 will look funny (some yellow triangles) but just restart it and it will take effect.
It is not the same as allowedVersions= becouse AFAIK you can lock to exactly one version only (for example, [3.1.0, 3.1.1] or (3.0.0, 3.1.1] or whatever else does NOT work!)
(i know i am necromanting this question - accepted answer is about older <Package />, my answer is about newer <PackageReference />)

Xunit Namespace Could not be Found in Visual Studio Code

I'm using Visual Studio Code for a .NET Core Project.
I have an ASP.NET Core Project for which i want to create a separate unit tests project, i created a sub folder and ran
dotnet new xunit
dotnet restore
When i tried to run it from the cli "dotnet build" "dotnet run" it ran successfully, however in visual studio, it says that it can't find the namespace Xunit
This is very strange because Visual Studio code has worked fine for me so far, it never had problem with dependencies, it only has this problem with Xunit.
Anyone familiar with this issue?
I had the same issue. It was solved by typing "Restart Omnisharp" in the Command Palette.
Adding the xunit reference to the root csproj is likely undesirable.
The Issue
The idea of having tests in a separate csproj is that they and their dependencies won't be included in the main project. Adding xunit to the root csproj will however cause the main project to reference xunit. Depending on how the product is bundled, this will cause the xunit dlls and all the dlls it depends on to be included unnecessarily.
Unfortunately, Omnisharp has an issue with nested csproj. It appears the root csproj will claim all source files in all subdirectories, even if there are nested csproj. This causes the missing reference error.
The Solution
Do not nest csproj. Note how Microsoft's xunit setup guide puts the main csproj and its tests csproj into different subdirectories of the sln.
I first ran into this error as well and after restructuring the project to not nest csproj, the error was resolved; with only the tests csproj referencing xunit.
I tried opening the test project directly with vscode (instead of opening the root project that contains the test project in a sub folder) and now vscode recognizes Xunit.
I then opened the root project with vscode again, added Xunit to the root project's csproj file, ran "dotnet restore" in the root project and now Xunit is recognized in the test project.
The thing is that vscode (or is it Omnisharp? i'm not sure) probably looks only at the root csproj file and ignores any csproj file that happens to be in a sub folder.
Prelude
None of the above worked for me.
Turns out I should have checked my notes from before, as this has been a recurring issue here with a project that uses Xunit:
Make sure all installed Xunit.xxxxxxxxx packages have the EXACT SAME version.
The problem occurs while/after having updated my NuGet packages automatically, which will, at the time of writing, install Xunit 2.4.1 (and several other xunit packages at version 2.4.1) plus xunit.runner.visualstudio at version 2.4.3 (!)
While nothing untoward is reported during this NuGet update, the result is a permanently failing build, where Fact and Assert are suddenly unknown, e.g.
Error CS0246: The type or namespace name 'Fact' could not be found (are you missing a using directive or an assembly reference?) Imazen.Test.Webp
The fix
What did work out for me was to go and revert that xunit.runner.visualstudio update, re-installing 2.4.1.
BTW, in Visual Studio, this would then look something like this (after the revert/re-install):
Note that the package manager there is hinting that an update is available and as soon as you apply that 2.4.3 update again, in any way, you're back to square one: a curiously failing build.
The key to the solution is to have all installed xunit packages with the same version. -- if only a few have updates available on NuGet, wait until all xunit packages are available for that same version.
Postscript
Don't know why this is so finicky, as I've only observed this brittle behaviour with xunit.*, but this is what has worked earlier this year (I had forgotten) and now had happen to me again, with the same outcome: the mandatory revert of a NuGet xunit package update.
#areller's solution solved my issue. I just want to expand on his answer to provide some sample code, in case there are other people who doesn't know exactly what to do (especially if you just started on C# like I did).
The Issue
First, I followed instructions here to start writing unit tests for a .NET Core application:
https://learn.microsoft.com/en-gb/dotnet/core/testing/unit-testing-with-dotnet-test
Then I encountered the same issue mentioned by OP.
Solution
First, I tried Claus' solution by restarting OmniSharp, but it doesn't fix the issue.
Then, following #areller's suggestion, I found these lines in Tests.csproj:
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
</ItemGroup>
I copied that, and pasted in my root directory's .csproj file, so the root .csproj looks like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
</ItemGroup>
</Project>
After that, VS Code asks me to restore. The VS Code dialog came with a "Restore" button; I clicked on that; several seconds later the issue is gone.
Good luck!
I had the same issue. I installed xunit.extensibility.core (2.4.1) for my .Net 5 solution and it solved the issue. xunit.runner.visualstudio (2.4.3) was already present.

Override a nuget package reference with a local project reference

I'd like iterate on a nuget package without continuously pushing the package to a nuget feed.
I'm wondering if it's possible to conditionally add a project reference instead of a nuget package reference via a target or props file in csproj files that would allow me to locally debug my nuget package.
In my csproj I would have:
<Reference Include="A">
if(Exists(localOverrides.props) {
<HintPath>localOverrides.A.HintPath</HintPath>
} else {
<HintPath>..\packages\A.dll</HintPath>
}
</Reference>
and localOverrides.props would be a file listed in my .gitignore that developers could add lines to like:
A -> C:\Repos\A\bin\A.dll
Am I on the wrong path? Surely there must be a more sustainable way to quickly iterate and debug a nuget package then creating pre-release packages on every change
The way I have always debugged Nuget package is once you have that package added to your solution through Nuget, you then make changes to the Nuget DLLs and just copy them into the correct folder in the packages folder for the project consuming the Nuget package.
All you have to do is compile the solution that Nuget project solution in debug mode and just copy/paste them into the consuming project's packages folder. You could make this even simpler by writing a batch script and adding it as a post build event to the Nuget project that just copied the DLLs into the correct folder for you.
There is a much easier way, in which you could use both: project references during development (faster), and package references during production.
In your .csproj project file:
<ItemGroup Condition="'$(Configuration)'=='Debug'">
<ProjectReference Include="../../../Library1/Library1.csproj" />
<ProjectReference Include="../../../Library2/Library2.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)'!='Debug'">
<PackageReference Include="Library1" Version="1.0.0" />
<PackageReference Include="Library2" Version="1.0.0" />
</ItemGroup>
In development: project compiled in debug mode, so the project reference will be used.
In production (CI server, docker container): project compiled in release mode, so the package reference will be used.
If all you want to acomplish is to debug the NuGet package I suggest you use "dotpeek debug server" option. This way you don't need to do anything with the reference and simply debug the package or whatever you want.
https://confluence.jetbrains.com/plugins/servlet/mobile#content/view/53336814
Sounds like you want a test project (unit or integration) in the same solution as your NuGet packaged assembly project. Then you can prove it's correctness independently of any consumers of the NuGet package. Good tests will also help ensure you don't break anything unintentionally when updating the package in the future.

Categories