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.
Related
I have a problem with the WinSCP.exe file in my created NuGet package.
I reference WinSCP in my project as follows:
<PackageReference Include="WinSCP" version="5.17.10" />
After packing my NuGet package, the winscp.exe is copied to the package in contentFiles. When I reference my package in other projects/NuGet packages, the winscp.exe is also copied into the package. I don't like that, because I want to use the references and download it while package restore (obviously).
But I don't know how I can exclude the .exe from my package.
I tried this:
<PackageReference Include="WinSCP" version="5.17.10" >
<PrivateAssets>none</PrivateAssets>
<IncludeAssets>all</IncludeAssets>
<ExcludeAssets>contentFiles;build;runtime;native;analyzers</ExcludeAssets>
</PackageReference>
This works for the first/lowest package, the .exe isn't copied and the reference is set in nuspec.
But for higher packages, which reference MY package (with reference WinSCP in nuspec), the .exe file isn't restored.
One workaround is as far as I can see, that I add for each package which is using my first/lowest package, the same reference again:
<PackageReference Include="WinSCP" version="5.17.10" >
<PrivateAssets>none</PrivateAssets>
<IncludeAssets>all</IncludeAssets>
<ExcludeAssets>contentFiles;build;runtime;native;analyzers</ExcludeAssets>
</PackageReference>
But I don't think, that is the intended way..
I'm wondering if the nuget-package structure of the .nupkg is the source of the problem/behavior. The Winscp.dll is stored in lib/net40, but the Winscp.exe is in tools/ folder. Official Microsoft Documentation doesn't describe well, where .exe files should be stored and for what "tools" is for...
Thanks for any help.
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:
I am trying to get rid of nuget packages and have only local dll files in the project.
These packages I have excluded
<PackageReference Include="Microsoft.AspNetCore" Version="2.1.7" />
<PackageReference Include="Microsoft.AspNetCore.CookiePolicy" Version="2.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.WindowsServices" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.HttpsPolicy" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.1.3" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.1.1" />
So, I've built my solution and imported all the dlls in the project. I can compile it, but the server says:
An unhandled exception occurred while processing the request. InvalidOperationException: The view 'Index' was not found. The following locations were searched: ...
But having the same with nuget makes the work fine. What is an alternative to add dlls to the project?
I've seen this, but in my case I have too many files with the same name when I put all the dlls in one folder (conflicts)
You can always add NUget source which is local folder from you drive and make it as default or the only source of dependencies.
Here are more details Local feeds
Replace asp.net core NuGet packages with local dll files. What is an
alternative to add dlls to the project?
I am trying to get rid of nuget packages and have only local dll files
in the project.
Nuget is a recommended way to manage the assemblies for your project. When you have access to Internet, using nuget is very convenient for your situation.
But according to your another post here, you're trying to develop/build the project in environment with no Internet. If so, we can still use nuget for this situation:
Step1: Clear all Nuget cache in VS=>Tools=>Options=>Nuget Package Manager=>General. (All packages you once used in VS are cached in %userprofile%\.nuget\packages, we can easy to restore the packages using nuget store, so feel free to clear the cache)
Step2: Delete the bin and obj folders of your current web project, and then restore packages for only your current project.(nuget restore, dotnet restore or simply rebuild the project in VS,VS will restore the packages for you)
Step3: Now let's navigate to the %userprofile%\.nuget\packages folder, now every packages in packages folder is that your current project depends on. Let's rename the folder name from packages to mypackages. Now all the packages(assemblies) your project need are in mypackages folder.
Step4: We can then copy/move this folder into your project folder. We can add this folder into source control or what depending on your actual needs. You can feel free to deploy your project to another server(no-internet) and continue on your work.
As to how to reference them, you can fetch the assemblies you need from mypackages folder and manually reference them.(Add=>Reference=>...). Or use this better way with nuget, add the path where your mypackages folder exist to Package Source, you can restore the packages for your project easily even in no-Internet environment.
Hope it helps and feel free to let me know if you need any further info or support :)
Probably missing a reference to Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation. You can add a dll for this package and then compile the Project or solution.
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
Consider a large existing codebase with approx. 150+ solutions and 800+ C# projects. Many are unit tests written using NUnit. All those projects references "nunit.framework.dll" from a "lib" folder that is checked in. There is also a number of 3rd party assemblies in the "lib" folder which has corresponding NuGet packages.
I could manually open 150+ solutions and migrate each reference to to NuGet. However this is proving to be tedious and error prone. I wrote a C# console application to parse csproj files and identify which packages needs to be installed for the respective project. So I know that 300+ projects requires the NUnit package to be installed.
How to I programmatically automate the installation of a package in a solution, matching the exact same behavior as doing so manually within Visual Studio 2013? I looked everywhere, and only found an extension however, it doesn't perform a full install with dependencies etc.
Create a packages.config file with just an entry for the NUnit packages
package.config should look something like this check for correct package name, version and target info
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="nunit.framework" version="2.6.3" targetFramework="net45" requireReinstallation="true" />
</packages>
extend the utility you wrote to parse .csproj files to edit the csproj file as well and add the below tags
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
packages.config should be copied to all project folders; else if your projects are going to have the same reference you can choose to Add the packages.config as a link
<ItemGroup>
<None Include="$(SolutionDir)packages.config">
<Link>$(SolutionDir)packages.config</Link>
</None>
</ItemGroup>
Once this is done open the solution in visual studio and go to the NuGet console and enter the below
command; NuGet will resolve missing dependencies and add them.
update-package
You can use the following snippet:
Get-Project -All | foreach-object {IF (Get-Content $_.FullName | Select-String 'Reference Include="XXX"') {Install-Package XXX -ProjectName $_.FullName}}
Replace XXX with your desired package name and run the snippet in Tools->NuGet Package Manager->Package Manager Console from within Visual Studio.