Restore nuget package in different folder - visual-studio

We have some projects (Plugins) which use in several projects, the output of these projects will copy to the specific folder in the target projects (Plugins folder).
We pack project with Visual studio 2019 Pack option and after that, we push npkg files to our local NuGet server for further use.
The problem is when we want to get these packages, Package Manager should put lib files in the Plugins folder, but unfortunately, the package manager extracts these in the root folder (bin).
My question is: How can I config nuspec file to force package manager to extract to the right folder, and can I do it with visual studio or I have to create nuspec file manually.

You should use a <packages_id>.props file to realize it.
create a file called <packages_id>.props under the build folder of your lib project.
You should note that if your nupkg file is called Plugins.1.0.0.nupkg, you should name this file as Plugins.props so that it will work.
add these on Plugins.props file:
<Project>
<Target Name="CopyFiles" BeforeTargets="Build">
<ItemGroup>
<File Include="$(MSBuildThisFileDirectory)..\Plugins\*.*"></File>
</ItemGroup>
<!--It will copy the plugins output files into the Plugins folder of the goal project-->
<Copy SourceFiles="#(File)" DestinationFolder="$(ProjectDir)Plugins"></Copy>
</Target>
</Project>
add these on Plugins.csproj file:
<ItemGroup>
<None Include="bin\Debug\netstandard2.0\Plugins.dll" Pack="true" PackagePath="Plugins"></None>
//add any output files from Plugins project which you want them to be packed
<None Include="build\Plugins.props" Pack="true" PackagePath="build"></None>
</ItemGroup>
use Pack Button to create the new release version of your nuget pakckage.
Also, when you install this new version of nuget package, please clean your nuget caches or delete all files under C:\Users\xxx(current user)\.nuget\packages.
When you finish the installing process, please click Build button and the files will generated under Plugins folder.
There is also a similar issue about this.

Related

Include File in NuGet package on Build, only if it does not exist

A while ago I asked this question:
Including a Folder in NuGet Package and have it install into project as file .netcore/Razor
The answer to which has got me most of the way where I want to go, but the trouble is rebuilding or updating the NuGet package in my projects is now overwriting files that are user-editable.
I feel the answer is somewhere in the .props file but I am not sure how to achieve it:
<Project>
<Target Name="CopyFiles" BeforeTargets="Build" >
<ItemGroup>
<File Include="$(MSBuildThisFileDirectory)..\Pagesettings\*.*"></File>
</ItemGroup>
<Copy SourceFiles="#(File)" DestinationFolder="$(ProjectDir)Pagesettings"></Copy>
</Target>
</Project>
The Target tag has an optional attribute Condition. I am guessing that somehow this can be used...?
So, to clarify my question:
From my original question linked above I have a NuGet package which when downloaded creates a folder called PageSettings, into which is copied a bunch of default JSON files containing PageSettings from my NuGet package. NOTE; these files initially appear in Visual Studio as linked files. They are not actually copied to the directory until the project is built.
However, the purpose of these PageSettings files is to be a default , or if you like an example, of PageSettings for users of my NuGet package. Once installed, the user can and should change these .JSON files, so now when their project is rebuilt, or if there is an update to the NuGet package available which they install, these JSON files should NOT update/install.
Sure. My answer quite has some flaws. To prevent overwriting existing files and files that have changed, I suggest you use xcopy with /d. It will not overwrite the existing files.
Instead, use this in test.props file:
<Project>
<Target Name="CopyFiles" BeforeTargets="Build">
<ItemGroup>
<File Include="$(MSBuildThisFileDirectory)..\Pagesettings\*.*"></File>
</ItemGroup>
<Exec Command="xcopy /s/d/y #(File) $(ProjectDir)Pagesettings\"></Exec>
<!--<Copy SourceFiles="#(File)" DestinationFolder="$(PorojectDir)Pagesettings" Condition="!Exists('$(PorojectDir)Pagesettings\*.*')"></Copy>-->
</Target>
</Project>
Then, repack your nuget project. Before using this new one, please clean nuget caches first.

include the XML documentation from a NuGet package

I have a NuGet package with an xml documentation file (doc.xml).
I have installed the NuGet package in my project.
I know want to add the NuGet documentation file doc.xml to my solution.
I am running .net core 3.1 but I have no idea how this can be achieved.
Thank you!
If your nuget project is net standard or net core, please check these steps:
1) create a file called <package_id>.props file under a folder called build on your project.
Note that, you should make sure that the your package_id of your nuget project is the same as the .props file, otherwise, it will not work. See this link's description.
In my side, my nuget package called test.1.0.0.nupkg, so I should rename the file as test.props file.
2) please add these content in test.props file.
<Project>
<Target Name="CopyFilesToProject" BeforeTargets="Build">
<ItemGroup>
<SourceScripts Include="$(MSBuildThisFileDirectory)..\File\*.*"/>
</ItemGroup>
<Copy
SourceFiles="#(SourceScripts)"
DestinationFolder="$(ProjectDir)"
/>
</Target>
</Project>
The propose of this target is to copy the xml file from the File folder of the nupkg into the target project's folder when you install this nuget into the main project.
3) add these under xxx.csproj file:
<ItemGroup>
<None Include="bin\Debug\netcoreapp3.1\test.xml(the path of the xml file in your nuget project)" Pack="true" PackagePath="File"></None>
<None Include="build\test.props(the path of the test.props file in your nuget project)" Pack="true" PackagePath="build"></None>
</ItemGroup>
4) Then, when you pack your project, the structure should be this:
Before you install this new version of nuget package, you should clean nuget caches first or just delete all cache files under C:\Users\xxx(current user)\.nuget\packages to remove the old ones in case you still install the old one.
After that, rebuild your main project to execute the target and you will see the xml document file exist under the main project folder.
In addition, there is a similar issue you can refer to and if you use the net framework project, the link also provide the method.
===========================
Update 1
If you want to copy the file into bin\Release or bin\Debug, you should modify step 2, change to use this in the .props file:
<Copy
SourceFiles="#(SourceScripts)"
DestinationFolder="$(ProjectDir)$(OutputPath)"
/>
or just
<Copy
SourceFiles="#(SourceScripts)"
DestinationFolder="$(OutDir)"
/>
as you want.
Before you install this new version, you should first delete nuget caches under C:\Users\xxx(current user)\.nuget\packages.

Create a Nuget package without its dependencies to be added as references

I need to create a Nuget package out of my library .net framework project.
The problem is that my project depends on many other dlls which I do not want my Nuget users to see. So I want people to install my package and see only my project dll in the references list, while all its dependencies will be added to bin folder only.
Actually, this is what happens when I reference this dll in any project- I can see it in my references list, and all its dependencies are simply copied to bin folder right after building. Can this behaviour be achieved with this project as Nuget ?
Create a Nuget package without its dependencies to be added as references
Since you do not want your Nuget users to see the other dlls, so you can not set those dlls file as dependencies, which will be added to the references list by default.
To resolve this issue, we need add those dlls file in the other folder in the .nuspec file and add a function to copy this dlls file to the bin folder when we add this nuget package to the project. You can follow below steps:
Add a xx.targets file in your project folder(The one you used to create nuget package ), make sure the name of the target file is the same name as the package id(TestDemo is my package ID, so the name of .targets is TestDemo.targets).
Add below code in the targets file:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)*.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
Note: The path of "$(MSBuildThisFileDirectory)" should be relative path, if you are not familiar with it, you can use the absolute path.
In the nuspec file, add required file to the Build directory along with the targets file.
<files>
<file src="<ThoseDllsPath>\*.dll" target="Build\" />
<file src="TestDemo.targets" target="Build\" />
<file src="bin\Debug\TestDemo.dll" target="lib\462" />
</files>
Pack this package, then add it on other project to test, it work fine.
Hope this helps.
I tried the solution of Leo Liu-MSFT. It worked in a .NET Framework Project, but not in a .NET Core 3.0
If you're using packages.config to manage your library's NuGet dependencies and building the nupkg with nuget.exe pack, then I believe you'll need to generate your own nuspec file and simply not add your build-time dependencies as a dependency to your package.
If you're using PackageReference, then you can use PrivateAssets
<ItemGroup>
<!-- ... -->
<PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.0">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<!-- ... -->
</ItemGroup>

NuGet only imports my .targets file into the top project

I have multiple projects in my solution, they all have the same NuGet package installed. I installed this NuGet package via the 'Manage Nuget Packages for Solution' option in my menu.
Now this particular NuGet Package has a .targets file in my build folder that imports some files into the build.
When I rebuild my solution these files are only copied for the top-level project. The other projects don't get the files copied into their build folder. This is causing me headaches because all the projects need these files in their build folder.
When I look into my .csproject files I see the following difference:
Project 1
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\NuGetTester.1.0.1\build\NuGetTester.targets" Condition="Exists('..\packages\NuGetTester.1.0.1\build\NuGetTester.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\NuGetTester.1.0.1\build\NuGetTester.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NuGetTester.1.0.1\build\NuGetTester.targets'))" />
</Target>
</Project>
Project 2
The 2nd project does not have these lines.
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
When I include these lines in the 2nd project everything seem to work.
Can someone explain why this only happens for the first project? Can I somehow force that every project in the solution that installs this NuGet will also include these lines? I can't force my users to include this manually.
Edit, this is the .targets file.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Content Include="$(MSBuildThisFileDirectory)\Versions\*.sql">
<Link>App_Data\Versions\%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
Thanks
Can someone explain why this only happens for the first project? Can I somehow force that every project in the solution that installs this NuGet will also include these lines?
Without install nuget package log, I could not give the reason that why this only happens for the first project. But you should make sure you have installed the nuget package to all projects when you installed the NuGet package via the 'Manage Nuget Packages for Solution' option:
If all check boxes are checked, you still have this issue, you should install individually that package to the problematic project, then check the install log.
Just in case, there is a workaround for this issue. You can create a MSBuild project file named "Directory.Build.props" in the same folder as your solution with you content in it.
It will be primitive imported into all projects in the directory hierarchy.
Check this document for more details.
Hope this helps.
It appears, to my knowledge, that the order of the projects was not the problem.
The problem only appears when I have no files in my target (net46) folder in the build folder.
Once I placed a random file into the .NET targetted folder the .targets file was imported into the project. Or if I removed all the .NET target folders from the build it works as usual.
So just to make a summary.
Build folder with no .NET framework target folders -> It works
Build folder with an empty .NET framework target folder -> Does not work
Build folder with a .NET framework target folder filled with one or many files -> It works

Build NuGet Package automatically including referenced dependencies

I want to run a local/internal NuGet repository. I think I've figured out how to "reuse" existing NuGet packages by including them in a dummy project using NuGet and scanning the package file to grab my locally-cached .nupkg files, but...
How do you create a nuget package (.nupkg) from a project, automatically including all dll dependencies and not just those grabbed via NuGet?
Specifically:
Create a solution
Add a new Project
Add references to various .dll files/other projects <-- this is the missing part
Add NuGet packages via package manager / cmdline / whatever
something automatically creates the .nupkg
From what I've found, you're supposed to do things like
manually edit your .csproj file to add <BuildPackage>true</BuildPackage> to include dependencies
manually create a .nuspec file and manually list your dependencies (similar ?)
manually run nuget pack on your .nuspec file
But everything is manual, which is stupid. Even the semi-automatic solutions are still awkward or half-manual:
Create .nuspec templates - doesn't seem to include dependencies, just metadata
nuget pack via build-event (step #5), which you need to add manually to every project, and it has its own quirks:
"$(SolutionDir).nuget\NuGet.exe" pack "$(ProjectPath)" -Properties Configuration=Release
move /Y *.nupkg "$(TargetDir)"
I'll settle for something that automatically creates a .nuspec manifest from project references. Then theoretically that + the nuget build-event can be rolled up into a build-project/nuget package, which is what I really want to see.
Your point #3 (Add references to various .dll files/other projects <-- this is the missing part) really contains two different issues: (1) add references to various dll files, and (2) add references to other projects in the same solution.
Number (2) here has gotten some added support as of NuGet 2.5. You can add an option to include references to other projects in the same solution when creating a NuGet package for a project:
nuget pack projectfile.csproj -IncludeReferencedProjects
If projectfile.csproj references any other projects in your solution that also is exposed as NuGet packages, these projects' NuGet packages will be added as dependencies.
If it references projects in your solution that doesn't expose themselves as NuGet packages, their dlls will be included in this NuGet package.
As for (1), if you find yourself often adding dlls to your projects that aren't available as NuGet packages, you could just create your own (internal) NuGet packages with these files. If you then add these dlls as a NuGet package instead of the files directly, this NuGet package will be a dependency in your project's NuGet package.
I found a well-written article on this topic. I have the same issue with certain packages that have a hierarchy of dependencies and up until now I've been uploading each as a separate NuGet package (what. a. waste. of. time)
I've just tested the solution found here: https://dev.to/wabbbit/include-both-nuget-package-references-and-project-reference-dll-using-dotnet-pack-2d8p
And after examining the NuGet package using NuGet Package Explorer, the DLLs produced by referenced projects are indeed present. I'm going to test by actually submitting this package to NuGet and testing it.
Here's my source in case it is helpful to you: https://github.com/jchristn/NuGetPackTest
And the test NuGet package: https://www.nuget.org/packages/NuGetPackTest/1.0.0
The solution appears to work well. I don't know what it's going to look like when there are layers of references, I'm sure it could get really hairy and really fast.
.csproj from NuGetPackTest library which references project TestLibrary (portions removed for brevity)
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netcoreapp3.0;netcoreapp3.1;net461</TargetFrameworks>
...
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<!-- added this line -->
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
</PropertyGroup>
<ItemGroup>
<!-- modified this ProjectReference to include the children ReferenceOutputAssembly and IncludeAssets -->
<ProjectReference Include="..\TestLibrary\TestLibrary.csproj">
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<IncludeAssets>TestLibrary.dll</IncludeAssets>
</ProjectReference>
</ItemGroup>
<!-- added this section -->
<Target DependsOnTargets="ResolveReferences" Name="CopyProjectReferencesToPackage">
<ItemGroup>
<BuildOutputInPackage Include="#(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference'))"/>
</ItemGroup>
</Target>
</Project>
For other Googlers, you can use this if you are using the NuGet.targets file to run NuGet Pack:
<Target Name="PrePackage" BeforeTargets="BuildPackage">
<PropertyGroup>
<BuildCommand>$(BuildCommand) -IncludeReferencedProjects</BuildCommand>
</PropertyGroup>
</Target>
Check this out!
The solution which I found is an extension for Visual Studio:
https://visualstudiogallery.msdn.microsoft.com/fbe9b9b8-34ae-47b5-a751-cb71a16f7e96/view/Reviews
You simply add new project called NuGet Package:
Then you are adding interesting you projects to references and BOOOM !!
All dependencies and file directories are automatically added.
If you want to modify NuSpec data you click right at project and go to Properties,
then modify what you want.
Generated NuSpec and nupkg will be in folder obj of your new project.
I hope it helps ;).
I solved this for my case by adding the whole TargetDir to the nuget package.
Just add this to the .csproj :
<Target Name="IncludeAllFilesInTargetDir" AfterTargets="Build">
<ItemGroup>
<None Include="$(TargetDir)\**">
<Pack>true</Pack>
<PackagePath>tools</PackagePath>
</None>
</ItemGroup>
</Target>

Resources