I hava a solution which contains two Project.
/Solution
.sln
.nuget.config
/ProjectA
.csproj
.nuspec
/ProejctB
.csproj
.nuspec
When I add a dependency ProjectA via nuget.
Project structure is become something like this:
/Solution
.sln
nuget.config
/packages
.nupkg
/lib
.dll
/ProjectA
.csproj
.nuspec
packages.config
/ProejctB
.csproj
.nuspec
Basically, Visual Studio create a packages.config file and put dependency there. And, dependency is added to /packages folder. Also, .csproj content changes.(A Reference added which has a relative path to dll inside /packages folder.)
I have two question.
1- Inside nuget.config file I have put following line. So I expect nuget will use default local repository instead of creating a /packages folder in solution. How can I prevent creation of a /packages folder in solution. Instead I would like to use "%userprofile%\.nuget\packages".
<add key="globalPackagesFolder" value="%userprofile%\.nuget\packages" />
2- When I add the dependency as nuget package. Still .csprj file is changed and dll's related path is added there as a reference with relative path. Is it ok? Isn't auto generated packages.config enough. Why also this file is updated.
1- Inside nuget.config file I have put following line. So I expect nuget will use default local repository instead of creating a /packages folder in solution. How can I prevent creation of a /packages folder in solution. Instead I would like to use "%userprofile%.nuget\packages".
You should use below settings in the NuGet.Config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<config>
<add key="repositoryPath" value="%userprofile%\.nuget\packages" />
</config>
</configuration>
You can check the test result from below screenshot, the packages is add to the "%userprofile%\.nuget\packages" folder:
Note: Take care the uppercase and lowercase for the file name and restart the VS after add it.
2- When I add the dependency as nuget package. Still .csprj file is
changed and dll's related path is added there as a reference with
relative path. Is it ok? Isn't auto generated packages.config enough.
Why also this file is updated.
Not, because the Package.config and the HintPath in the .csproj file have different role. The Package.config is used by NuGet to manage the Packages, and the HintPath in the .csproj is used by the Visual Studio reference the path of the Dll file. Both files are need to be updated, otherwise Visual Studio will throw the error "Can not find the reference..."
Related
I am trying to get my head around how Nuget works when creating packages and must admit that I cannot grasp it.
To generalize my task, it is to include a file in the Nuget package, create that Nuget package and when installed as a dependency in other project, the file is shown there in the project structure or somewhere to be manipulated with.
This file is a central .DotSettings file which would then propagate to all the C# repositories and solutions.
Where I am now
I have a .dll project, I have my content folder where the file is and I specify that within the .csproj file as such:
<ItemGroup>
<Content Pack="True"
PackagePath="\"
Include="content\test.DotSettings" />
However, when this is Nuget packed and this dependency is installed in another project, I cannot see this file in the project/dependencies/packages folder, where I would like it to be (and I suppose it should be there, right?)
The workaround I have now is that I reference this file from within the users/nuget/packages folder, however, I do not fancy this solution that much.
So, the main question:
Is there a way to copy the file so that when the dep is installed, the file is shown at the top level project folder structure? if so, what am I missing?
misc questions:
As I understood it, I can write my own .nuspec file and specify it there somehow, but when I did that, at build it always overrides it with its own autogenerated .nuspec file. Is this a wrong way to take at all and should I not create my own .nuspec?
What about the .target and .props file, what is that for and do I need to bother with those in my task or not at all? From what I understood, I should be good with my .csproj file and be able to define it all within it.
TIA!
I'm using VS 2017, and I have a new common project(CommonLib) that needs to be referenced by projects in multiple solutions. For this common project I want to maintain its own packages folder. And after referencing this project into an existing solution (that has a project that refers a different packages folder), nuget restore is not looking at both these package folders.
Not sure if within a single solution nuget restore could search for multiple packages folder to resolve the referencing libraries based on the project file hintPaths.
Also I see that migrating from packages.config to PackageReference would help here, but I don't want to get rid of packages.config in existing projects, and also not in the new CommonLib project to be consistent.
Here is how my src setup paths are:
UX.Sln - paths: C:\Src\UX\UX.Sln; C:\Src\UX\packages;
UXSource.csproj - paths: C:\Src\UX\UXSource; This refers nuget libs from src C:\Src\UX\packages
CommonLib.csproj - paths: C:\Src\Common\CommonLib; I want to refer nuget libs from src C:\Src\Common\packages
Api.Sln - paths: C:\Src\Api\Api.Sln; C:\Src\Api\packages;
ApiSource.csproj - paths: C:\Src\Api\ApiSource; This refers nuget libs from src C:\Src\Api\packages
CommonLib.csproj - paths: C:\Src\Common\CommonLib; I want to refer nuget libs from src C:\Src\Common\packages
If you want to restore nuget packages through multiple nuget packages sources. You just need to put custom nuget.config file.
And as you saw, custom nuget.config file will act on the current projects under the current folder and projects under all subdirectories.
And nuget.config file could not be added into the project folder and it should be under solution folder or above folder to make it work.
Besides, it seems you have added an existing project called CommonLib into UX solution and Api solution.
So you could try this:
1) add a file called nuget.config under C:\Src and then add these node under that file:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="NuGet_Restore_Path1" value="C:\Src\UX\packages" />
<add key="NuGet_Restore_Path2" value="C:\Src\Common\packages" />
<add key="NuGet_Restore_Path3" value="C:\Src\Api\packages" />
</packageSources>
</configuration>
2) Then, the these two solution could use these packages folder to restore missing nuget packages.
Use: nuget restore UX.sln and nuget restore Api.Sln.
In addition, if you do not want the new nuget.config file affects other solutions under src folder, you could add the file into C:\Src\UX and C:\Src\Api instead.
It looks like another project doesn't have configured NuGet source. So you can use
dotnet nuget add <source> command documentation.
or extend it using in NuGet.Config file.
https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file#package-source-sections
Also pls try to package folder location in nuget.config
<configuration>
<config>
<add key="repositoryPath" value="$\..\pacakges" />
</config>
</configuration>
I have two class libraries in a single solution (.NET Core). One of them (cl1) is a main library and it depends on another library (cl2). I have added a .nuspec file with the required metadata only (no dependencies, no files) for the cl1 project in the project folder (same location of .csproj file) and I have set GeneratePackageOnBuild propery to true.
Whenever I am building the class library (cl1), the .nupkg is created automatically in the debug/release folder.
When I check the generated .nupkg file, I am see two strange things:
The generated .nuspec file is different than what I have added in the project folder
cl2 is mentioned as a dependency in the newely generated .nuspec file, but the DLL for cl2 is not included in the lib folder of the .nupkg. So, whenever I consume this package in another solution, I am getting the error No packages exist with this id in source(s) for the cl2.
I have surfed in internet, but was not able to find a proper solution for the above error.
And I have added a .nuspec file [...] in the project folder(same location of .csproj file)
You have to specify the path to your own NuSpec file in the .csproj using the NuspecFile tag, otherwise it will be ignored and the package will be created with the metadata from the .csproj file instead, see reference. You need to use either a relative or an absolute path to the file, for example:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<NuspecFile>cl1.nuspec</NuspecFile>
</PropertyGroup>
</Project>
The generated .nuspec file is different than what I have added in the project folder
As already stated, your NuSpec file is probably not included. However, even if it is, there can be differences, because some information, e.g. source file locations are unnecessary and the target locations are in most cases given by the internal package file structure itself, so it is not there because it is redundant.
cl2 is mentioned as a dependency in the newely generated .nuspec file, but the dll for the cl2 is not included in the lib folder of the .nupkg. So, whenever I consume this nupkg in other solution, I am getting error " No packages exist with this id in source(s)" for the cl2.
Dependencies are meant for packages. So when NuGet restores the package it searches for other packages that this package depends on, here cl2, but there is none, hence the error. When packing a project, referenced projects are not included in the package. That is an open issue and there are workarounds that you can try.
The most reliable, but inconvenient solutions are to avoid the issue at all.
Only use a single project, everything will be included in the package
Pack each project on its own and use the generated package instead of the referenced project
I have a library project used in multiple applications. Let's call this Library1. Library1 has its ownNuGet package dependencies. When I setup a project, ProjectA, using Library1, it specified a HintPath for each .dll that Library1 depended on. Let's say this HintPath was "..\etc.dll".
I now have Library2, which depends on Library1, and ProjectB that depends on Library2 (and Library1). I have a hierarchy like this:
ProjectB
--Library2
----Library1
But the other project uses Library1 directly, like so:
ProjectA
--Library1
When opening either ProjectB, the packages are being resolved in "ProjectB\packages", which is two folders up from the library depending on it, meaning it should be looking in "....\etc.dll" rather than "..\etc.dll" specified in the HintPath.
Is there a way I can specify a HintPath depending on the parent project, or any kind of workaround that will allow this to work without me having to manually change each of my .dll reference paths? Perhaps a file I could add to the parent project?
You can create a NuGet.Config file can specify the repositoryPath which allows you to override the default location where NuGet packages are downloaded to for the project.
<configuration>
<config>
<add key="repositorypath" value="Packages" />
</config>
</configuration>
The repositoryPath is relative to the NuGet.Config file's directory.
NuGet will look for this file based on the solution you open so you would need to place it so that either one or all of your solution's use this file. A simple way is to put it in a directory that is a parent of both solutions but you can add it for each solution or just the one.
If the solution is in c:\a\b\c then NuGet will look for the file in these locations in the order specified, finally falling back to the one in your user profile.
c:\a\b\c.nuget\nuget.config
c:\a\b\c\nuget.config
c:\a\b\nuget.config
c:\a\nuget.config
c:\nuget.config
After setting this up you may need to reinstall the NuGet packages so the correct hintPaths are added to your project.
Intro (how to pack resources into a nuget package)
To pack some resource files into a nuget package, what one would normally do, is the following.
Put all the resource files into the content\ directory of a nuget package. This would be specified by the following line in a .nuspec file:
<files>
<file src="Project\bin\Release\script.js" target="content\js\script.js" />
<files>
Now, when this nuget package gets installed into AnotherProject, the following file structure emerges:
Solution.sln
packages\Project.1.0.0\content\js\script.js // the original resource file
AnotherProject\js\script.js // a physical copy
AnotherProject\AnotherProject.csproj // <Content /> tag (see below)
During package installation, AnotherProject.csproj was injected with tag:
<Content Include="js\script.js" />
and this is for the physical copy of the original resource (which is under packages\ directory).
The actual problem (how to pack resources into a nuget package as link)
My aim is not to have the physical copy of a resource file in the AnotherProject directory but rather a "link" to the original resource under packages\ directory. In the csproj, this should look like this:
<Content Include="packages\Project.1.0.0\content\js\script.js">
<Link>js\script.js</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
Brute force solution that I would rather avoid
Now, one "do it the hard way" workaround I can think of is:
not putting resource files under content\ so they do not get added automatically,
writing Install.ps1 script that would hack the csproj file structure and add the necessary XML piece manually,
This, however, has the following drawbacks:
all my nuget packages need the same script piece in their Install.ps1,
when installing my packages, there would be a nasty "project reload prompt" in Visual Studio.
Since NuGet currently does not support this out of the box your options are either to use PowerShell or to use a custom MSBuild target.
PowerShell
Leave your resources outside of the Content directory in your NuGet package (as you already suggested).
Add the file link using PowerShell in the install.ps1.
You should be able to avoid the project reload prompt if you use the Visual Studio object model (EnvDTE). I would take a look at Project.ProjectItems.AddFromFile(...) to see if that works for you.
MSBuild target
NuGet supports adding an import statement into a project that points to an MSBuild .props and/or .targets file. So you could put your resources into the tools directory of your NuGet package and reference them from a custom MSBuild .props/.targets file.
Typically the custom .props and .targets are used to customise the build process. However they are just MSBuild project files so you could add items for your resources into these project files.
Note that .props are imported at the start of the project file when a NuGet package is installed, whilst .targets are imported at the end of the project.
Customising NuGet
Another option, which would take more work, would be to modify NuGet to support what you want to do.