Nuget package does not restore all DLLs and Dependencies - c#

I have created a Nuget package using Nuget Package Explorer. The package has some third party dlls that I use in my code. I dlls are included in the Nuget package and not referenced directly in the project references. The Nuget Package has the following.
- thirdPartyAAA.dll
- thirdPartyAAA.xml (Needed by thirdPartyAAA.dll)
- thirdPartyBBB.dll (needed by thirdPartyAAA.dll
- thirdPartyBBB.dll.config (used by thirdPartyBBB.dll)
- Dependency on HtmlAgilityPack nuget (Needed by thirdPartyAAA.dll)
- Dependency om RestSharp nuget (Needed by thirdPartyAAA.dll)
The problem is: when I reference this Nuget package in the code and compile the code I only get aaa.dll in the bin output folder. the following files are missing from the bin folder:
- thirdPartyAAA.xml
- thirdPartyBBB.dll
- thirdPartyBBB.dll.config
- All dlls from HtmlAgilityPack nuget
- All dll from RestSharp nuget
In my code I directly reference thirdPartyAAA.dll.
Is there a way - either during creating the Nuget Package or when referencing the package - to force the Nuget Package to restore all its contents and its dependencies? I need all the files that's included in the Nuget Package to be restored regardless if they are directly references in the code or not.
thank you all for your help.
Here is the manifest of the package if it helps.
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>MyPackage</id>
<version>1.0.0</version>
<title></title>
<authors>Dev</authors>
<owners>Dev</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>My package description.</description>
<dependencies>
<dependency id="HtmlAgilityPack" version="1.4.9" />
<dependency id="RestSharp" version="105.0.1" />
</dependencies>
</metadata>
<files>
<file src="content\thirdPartyAAA.chm" target="content\thirdPartyAAA.chm" />
<file src="content\thirdPartyAAA.XML" target="content\thirdPartyAAA.XML" />
<file src="content\thirdPartyBBB.dll.config" target="content\thirdPartyBBB.dll.config" />
<file src="lib\thirdPartyAAA.dll" target="lib\thirdPartyAAA.dll" />
<file src="lib\thirdPartyBBB.dll" target="lib\thirdPartyBBB.dll" />
</files>
</package>

The problem is: when I reference this Nuget package in the code and compile the code I only get aaa.dll in the bin output folder. the following files are missing from the bin folder:
- thirdPartyAAA.xml
- thirdPartyBBB.dll
- thirdPartyBBB.dll.config
- All dlls from HtmlAgilityPack nuget
- All dll from RestSharp nuget
First, for the thirdPartyBBB.dll, you should make sure the target framework version of project is higher than your dll's target framework. For example, If the target framework version of your project is .net 4.6.2, the target framework version of your thirdPartyBBB.dll should be lower than .net 4.6.2. Otherwise, you are referring a dll file with higher version target framework to the project with lower version target framework. This is incompatible.
Besides, for the dependencies of this package, you can check if those dependencies added to the project, and the properties Copy Local of those dlls are set to True. It works fine on my side.
Second, for the content file, you should add a .targets file in the build folder in your package with following code to copy those content files to the bin folder:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<None Include="$(ProjectDir)thirdPartyAAA.chm">
<Link>thirdPartyAAA.chm</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CustomToolNamespace></CustomToolNamespace>
</None>
<None Include="$(ProjectDir)thirdPartyAAA.XML">
<Link>thirdPartyAAA.XML</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CustomToolNamespace></CustomToolNamespace>
</None>
<None Include="$(ProjectDir)thirdPartyBBB.dll.config">
<Link>thirdPartyBBB.dll.config</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CustomToolNamespace></CustomToolNamespace>
</None>
</ItemGroup>
</Project>
For some details info, please check this thread.
Alternatively, you can use Install.ps1 file to change the property, the script looks like:
param($installPath, $toolsPath, $package, $project)
function MarkDirectoryAsCopyToOutputRecursive($item)
{
$item.ProjectItems | ForEach-Object { MarkFileASCopyToOutputDirectory($_) }
}
function MarkFileASCopyToOutputDirectory($item)
{
Try
{
Write-Host Try set $item.Name
$item.Properties.Item("CopyToOutputDirectory").Value = 2
}
Catch
{
Write-Host RecurseOn $item.Name
MarkDirectoryAsCopyToOutputRecursive($item)
}
}
#Now mark everything in the a directory as "Copy to newer"
MarkDirectoryAsCopyToOutputRecursive($project.ProjectItems.Item("TheFolderOfYourContentFiles"))
You can check similar issue for details.
In addition, I have created a test nuget package, you can check if it works for you, test it with .net framework project with target framework 4.6 and above.
https://1drv.ms/u/s!Ai1sp_yvodHf1QJriMiGQWdYveRm
Hope this helps.

Go to your solution explorer ,
on Ur project references,
right click on the DLL which is missing from the bin folder. Select properties, then make "copy local " to true. This will copy the DLL to the build path after compiling.

Go to your solution explorer ,
on Ur project references,
right click on the DLL which is missing from the bin folder. Select properties, then make "copy local " to true. This will copy the DLL to the build path after compiling.
For nuget restoring please refer the below link
https://learn.microsoft.com/en-us/nuget/consume-packages/package-restore-troubleshooting

I recently ran into almost exactly the same problem.
After 2 days, I discovered several posts that clarified that the contents folder are ONLY deployed during the +initial+ installation of the nuget.
What this means is that any files deployed as CONTENT are intended to be checked into your version control system, just like any other code in your project.
They are specifically NOT deployed when VS runs a "package restore" as it does when you build a project and some packages are missing.

Related

DLL in NuGet package not appearing in build output folder

We have a NuGet package that was created by ourselves and is hosted on an in-house repo. We've been using it for several years in a .Net Framework 4.x solution. The package contains a .Net4.x assembly (a class library, referenced by code in the solution), two "native" DLLs, and a handful of .c files. When the solution builds, every file in the package gets copied to the build output folder, which is what we expect.
I've now migrated this solution to .Net6 and referencing the same package, but the build behaviour is different. Here, the solution builds successfully but none of the files in the package get copied to the build output folder. Instead, the two native DLLs and .c files get copied to the root folder of the referencing project (also showing up in the VS solution explorer window). The .Net assembly (TspAdqAcquisition.dll) does not appear in the project root folder, or anywhere else for that matter.
What's going on?
This is the nuspec file (from the "library" solution where the Tsp...dll and other files reside):
<?xml version="1.0" encoding="utf-8"?>
<package >
<metadata minClientVersion="2.5">
....
</metadata>
<files>
<file src="x64\Release\*.c" target="build" />
<file src="x64\Release\glew64.dll" target="build\glew64.dll" />
<file src="x64\Release\glut64.dll" target="build\glut64.dll" />
<file src="x64\Release\TspAdqAcquisition.dll" target="lib\net451\TspAdqAcquisition.dll" />
<file src="x64\Release\TspAdqAcquisition.dll" target="lib\net\TspAdqAcquisition.dll" />
<file src="x64\Release\TspAdqAcquisition.dll" target="lib\net6.0\TspAdqAcquisition.dll" />
<file src="x64\Release\TspAdqAcquisition.dll" target="lib\net6.0-windows10\TspAdqAcquisition.dll" />
<file src="x64\Release\TspAdqAcquisition.dll" target="lib\net6.0-windows11\TspAdqAcquisition.dll" />
</files>
</package>
Edit
I've figured out why the two native DLLs and .c files weren't being copied to the build output folder. The NuGet package in question is referenced by a class library project (net6.0 TFM rather than net6.0-windows), so these particular files were ending up in a separate \net6.0\ build output folder, rather than the \net6.0-windows\ build output folder that the rest of the solution ends up in. Once I'd referenced that class library project by one of the WPF projects, these files appeared in the correct build output folder.
However the TspAdqAcquisition.dll assembly still isn't being copied to (either) build output folder.
Edit 2
I'm now able to get the TspAdqAcquisition.dll assembly to copy to the build output folder by including this line in the project file:
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
I had to put this in the WPF project file to ensure that the DLL is copied to the correct (\net6.0-windows) build output folder. If I add the above line to the class library project file referencing the NuGet package then the DLL ends up in the wrong (\net6.0) build output folder.
It's all starting to feel a bit hacky for my liking...
My last remaining question then is whether it's possible to prevent those native DLLs and .c files from being "unpackaged" into the project folder and cluttering up the solution explorer window? Why doesn't this happen in VS2019?
It seems you don't have a .targets file in the nuget package. I'm not sure whether that's the "normal" way of how this should be done, but that's how I copy native binaries to the output.
So one possible way to get this to work correctly, is to create a <packagename>.targets file in the build folder of the nuget with content such as:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="CopyFilesToTargetDirectory_MyPackageName" BeforeTargets="Build">
<ItemGroup>
<FilesForTargetDirectory_MyPackageName Include="$(MSBuildThisFileDirectory)\..\tools\**\*.*" />
</ItemGroup>
<PropertyGroup>
<TargetDirectory_MyPackageName Condition="'$(TargetDirectory_MyPackageName)' == ''">$(TargetDir)</TargetDirectory_MyPackageName>
</PropertyGroup>
<Copy SourceFiles="#(FilesForTargetDirectory_MyPackageName)"
DestinationFolder="$(TargetDirectory_MyPackageName)\%(RecursiveDir)"
SkipUnchangedFiles="true" />
</Target>
</Project>
and then, move the native libraries from the build folder to either the tools folder (as in the example code above) or the lib\native folder.

How to control output of a nuget package dependencies during build

I would like to support backward compatibility in my application.
Simply saying - one app needs to work using different versions of a dll depending on a flag which the app get's during runtime.
I've simplified everything and created a test solution with 2 projects in it.
Each project has it's own version of the same nuget package.
I picked System.Drawing.Common cause it has no dependencies.
ClassLibrary1 contains System.Drawing.Common of version 4.5.0.
ClassLibrary2 contains System.Drawing.Common of version 6.0.0.
Both projects have same output path:
<OutputPath>..\DEBUG\</OutputPath>
When I build my solution I get just one System.Drawing.Common.dll in my output folder:
Cause both dlls have one name and only version is different.
The desired behavior on the pictures below:
Distribute the nuget package dependencies into different folders according to versions.
Add suffix to the nuget package dependencies according to versions.
The idea is in controlling output of the nuget package dependencies.
Do you have any idea how I can achieve that ?
P.S. all other logic - resolving dependencies according versions etc is out of scope of this question.
It's possible.
First you need to add GeneratePathProperty to PackageReference element in csproj file
<ItemGroup>
<PackageReference Include="System.Drawing.Common">
<Version>4.5.0</Version>
<GeneratePathProperty>true</GeneratePathProperty>
</PackageReference>
</ItemGroup>
It allows us using $(PkgSystem_Drawing_Common) variable which contains a path to the nuget package.
Then we need to create a msbuild targets file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="CopyNugetDll" BeforeTargets="BeforeCompile" Outputs="System.Drawing.Common.dll">
<XmlPeek XmlInputPath="$(ProjectPath)" Query="Project/ItemGroup/PackageReference[#Include='System.Drawing.Common']/Version/text()">
<Output TaskParameter="Result" PropertyName="NugetPackageVersion" />
</XmlPeek>
<ItemGroup>
<NugetrDll Include="$(PkgSystem_Drawing_Common)\lib\net461\System.Drawing.Common.dll" />
</ItemGroup>
<Message Text="Copying #(NugetrDll) to $(OutDir)" Importance="high" />
<Exec Command="copy $(PkgSystem_Drawing_Common)\lib\net461\System.Drawing.Common.dll $(OutDir)\System.Drawing.Common.$(NugetPackageVersion).dll" />
</Target>
</Project>
Here using xpath we select version from project.assets.json file and save it in NugetPackageVersion variable. Exec copy is used to copy the dll to a specific location with a specific prefix which contains a value from NugetPackageVersion variable.
Lastly you need to include msbuild targets file to a project
<Import Project="CopyDll.targets" />
This just isn't how package resolution works in .NET, you get one version of each package which is decided at restore time.
There may be some funky options if you have a very niche problem, but it sounds like maybe you're trying to solve a common problem in an uncommon way which is generally a bad idea.
Typically for the problem of backwards compatibility the onus is on the publisher of the library rather than the consumer of the library to make sure it all works by not making breaking API changes.

Include ONLY .xml file of SPECIFIC nuget package in a different folder

We have a project (ProjectAbc) in a solution which is referencing a nuget package (which is our different project [ProjectXyz] from other solution). We use .net core framework and package reference to include nuget package (ProjectXyz) in .csproj file.
<PackageReference Include="ProjectXyz" Version="1.1.2.3" />
When the solution is build locally or in Prod, ProjectXyz.dll and ProjectXyz.xml gets generated in
ProjectAbc/bin/debug(locally) or release(inProd)/netcoreapp3.1
We want Only ProjectXyz.xml of Only ProjectXyz nuget package to get generated in following folder directly
ProjectAbc
I found various articles which directed me to do different things like copying file to output directory after building or using relative path. Though, tried different ways, I keep getting various errors. It may be because I am not aware of the syntax in .csproj file or also may be because I am not sure what I am doing.
What would be best way to copy file in above case or to generate file directly in the required folder?
for my comment response:
Since I am unable to paste the screenshot in my comment for #Perry Qian-MSFT. So pasting it here.
8/20/2020-----package screenshot---------------------------
You could use <package_name>.props file in nuget project ProjectXyz to copy such file into the project folder of ProjectAbc. You should use <package_id>.props.
1) First, in your ProjectXyz project, create a folder called build and then add a file called <package_id>.props, in your side, it is called ProjectXyz.props.
2) Add these in ProjectXyz.props file:
<Project>
<Target Name="CopyFilesToProject" BeforeTargets="Build">
<Message Text="Copying ProjectXyz.xml to project" />
<ItemGroup>
<SourceScripts Include="$(MSBuildThisFileDirectory)..\..\content\any\any\**\*.*"/> //file from the ProjectXyz nuget package
</ItemGroup>
<Copy
SourceFiles="#(SourceScripts)"
DestinationFiles="#(SourceScripts -> '$(MSBuildProjectDirectory)\%(RecursiveDir)%(Filename)%(Extension)')" //copy into the main ProjectAbc project folder
/>
</Target>
</Project>
3) Unload your ProjectXyz project and add these in ProjectXyz.csproj file:
<ItemGroup>
<Content Include="bin\Debug\xxx\ProjectXyz.xml(the path of the ProjectXyz.xml)" Pack="true"
PackagePath="content\any\any;contentFiles\any\any\;;">
<PackageCopyToOutput>true</PackageCopyToOutput>
</Content>
<None Include="build\ProjectXyz.props" Pack="true" PackagePath="build\$(TargetFramework)"/>
</ItemGroup>
4) Then you should pack your new ProjectXyz project.
5) Then you finish packing, you should first clean all nuget caches first.
Then in your ProjectAbc project, you should uninstall the old one and then install the new ProjectXyz nuget package.
After that, you should build ProjectAbc project first and then you will see that xml document from the nuget package is under the project folder of ProjectAbc.
====================================================================
Update 1
ProjectXyz project is net core or net standard while ProjectAbc is net core.
First, to help you understand the issue, instead, I try to pack ProjectXyz.xml file into other folder in the ProjectXyz.nupkg.
1) First, change to use these xml content in ProjectXyz.csproj file:
<ItemGroup>
<Content Include="bin\Debug\netcoreapp3.1\ProjectXyz.xml" Pack="true" PackagePath="XmlFolder">
<PackageCopyToOutput>true</PackageCopyToOutput>
</Content>
<None Include="build\ProjectXyz.props" Pack="true" PackagePath="build\$(TargetFramework)"/>
</ItemGroup>
The goal of it is to pack ProjectXyz.xml file into the folder called XmlFolder of XmlFolder.nupkg. And save ProjectXyz.xml file in the Nuget package.
Make sure that the file exists in the nuget package.
If the file does not exist, I think it is controlled by your git. Or you could put this ProjectXyz.xml in your project folder.
Try to right-click on your project-->Properties-->Build-->check this:
Just use <Content Include="ProjectXyz.xml" Pack="true" PackagePath="XmlFolder">
In our side, the file can be copied into nupkg nuget package so you should make sure that other tools like git will not interface it.
2) Then change to use these in ProjectXyz.props file:
<Project>
<Target Name="CopyFilesToProject" BeforeTargets="Build">
<Message Text="Copying ProjectXyz.xml to project" />
<ItemGroup>
//ProjectXyz.xml file from the ProjectXyz nuget package
<SourceScripts Include="$(MSBuildThisFileDirectory)..\..\XmlFolder\**\*.*"/>
</ItemGroup>
//copy ProjectXyz.xml file into the main ProjectAbc project folder
<Copy
SourceFiles="#(SourceScripts)"
DestinationFiles="#(SourceScripts -> '$(MSBuildProjectDirectory)\%(RecursiveDir)%(Filename)%(Extension)')"
/>
</Target>
</Project>
The goal of it is that when you install this nuget package, it will first run this target to copy the ProjectXyz.xml file from the nuget package into the main project ProjectAbc.
Note:
When you finishing installing nuget package, first build ProjectAbc project and the file will exists in ProjectAbc project folder.
3) Then right-click ProjectXyz-->Properties-->Pack to pack your project.
When you install the new ProjectXyz, you should first delete all files under
C:\Users\xxx(current user)\.nuget\packages.
Also, one more question I had is, the ProjectXyz is being referenced
in multiple projects like ProjectAbc, Project123. We dont want
ProjectXyz.xml file to show up in Project123 but only in ProjectAbc. I
guess with above solution, it might show in both of referencing
projects.
For this, you only need to add a condition in CopyFilesToProject target like this: $(ProjectXyz_Flag)==true and then create a property ProjectXyz_Flag and set its value to true in ProjectAbc.csproj file.
When you build ProjectAbc project, it will determine whether to copy the file based on the switch variable you are currently setting.
a) Add a condition called $(ProjectXyz_Flag) in ProjectXyz.props file:
Then repack your ProjectXyz project and do several clean steps as I said before.
When you install that package in ProjectAbc project, you should add such such property in ProjectAbc.csproj file:
<PropertyGroup>
<ProjectXyz_Flag>true</ProjectXyz_Flag>
</PropertyGroup>
Then when you build ProjectAbc project, it will execute the copy target and if you do not define that property, it will not copy that file in ProjectAbc.
And if those projects do not need ProjectXyz.xml file, you just do not define that switch property in those projects.
====================================================
Update 2
try to use nuget.exe cli to pack your project, you just need a custom nuspec file:
First, download nuget.exe cli and then configure its local path into PATH System Environment Variable. Then, you can call nuget in CMD.
Second, open CMD and cd xxx(project folder path), run nuget spec to generate the nuspec file and then modify the generated nuspec file:
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<!-- ... -->
</metadata>
<files>
<file src="xxx\ProjectXyz.xml" target="XmlFolder" />
<file src="build\ProjectXyz.props" target="build\netcoreapp3.1" />
</files>
</package>
Third, run nuget pack to pack this project.
==============================================================
Update 3
Please first clean your nuget caches or just delete all nuget caches under C:\Users\xxx(current user)\.nuget\packages. Then reinstall your nuget package.
Also, make sure that the xxx.props name is the same as your nuget package_id.
If your nuget package calls ProjectXyz(package_id). Then the props file should be named as ProjectXyz.props.
Besides, you should set msbuild project build output verbosity to detailed under Tools-->Options-->Projects and Solutions-->Build and Run.
Then, rebuild your ProjectAbc to check whether the target executes.
======================================================
Update 4
You should make sure that when you pack your package project.mnop, make sure that the project.mnop.props file has no syntax errors.
For an example, I have incorrectly wrote something like asdczxcx in the props file, however, since the build action of the props file is Content or None, Vs will not automatically analyze its errors and will not show the errors.
And the error shows the same as yours.
So you should delete that Illegal characters. Make sure that project.mnop.props has no syntax errors. Then repack your project.
After that, first uninstall the old nuget package project.mnop on the ProjectAbc.
Then, delete the cache project.mnop folder under C:\Users\xxx(current user)\.nuget\packages.
Finally, delete bin and obj folder of ProjectAbc, install the new version project.mnop, then rebuild your project ProjectAbc.
=============================================
Update 5
Actually, this should be an easier way. And your inspiration can be done with a more concise Nuget package structure.
You should only change this:
1) change to use ProjectXyz.xml from the lib folder in your ProjectXyz.props:
<SourceScripts Include="$(MSBuildThisFileDirectory)..\..\lib\netcoreapp3.1\ProjectXyz.xml"/>
</ItemGroup>
<Copy
SourceFiles="#(SourceScripts)"
DestinationFiles="#(SourceScripts -> '$(MSBuildProjectDirectory)\%(RecursiveDir)%(Filename)%(Extension)')"
/>
2) change your xxx.nuspec file to:
<?xml version="1.0"?>
<package >
<metadata>
........
<copyright>Copyright 2020</copyright>
<tags>Tag1 Tag2</tags>
</metadata>
<files>
<file src="build\ProjectXyz.props" target="build\netcoreapp3.1" />
</files>
</package>
3) then pack your project and then you can get what you want.
Note: SourceScripts uses the path $(MSBuildThisFileDirectory).
$(MSBuildThisFileDirectory) means the full path where the ProjectXyz.props file of the nuget package exists.
In your side, the $(MSBuildThisFileDirectory) means
C:\Users\xxxxx\.nuget\packages\project.mnop\45.0.0\build\netcoreapp3.1
And then use this path to find the file address of ProjectXyz.xml in the lib folder of the nuget package.

In VS2019 nuget doesn't consider referenced projects as lib, but as nuget packages

I'm using VS2019 community edition.
I have two .net core projects X, Y, X is referencing Y, and I want to package X as a Nuget package, I'm using the package feature in VS2019.
when I try to add X's Nuget package in another project it searches for Y as a Nuget package and not as DLL should be in X.
How can I change this so Y will be added as DLL in X's package?
I tried to add the following to X's project (.csproj):
<PropertyGroup>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
</PropertyGroup>
<Target Name="CopyProjectReferencesToPackage" DependsOnTargets="ResolveReferences">
<ItemGroup>
<BuildOutputInPackage Include="#(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference'))" />
</ItemGroup>
</Target>
But I still get the same result, nuget.exe tries to restore Y as Nuget package not as DLL comes with X's package.
UPDATE:
Also if Y has another Nuget dependency, it should be considered in X without referencing it directly in X.
I tried the following:
In X's project:
Go to Dependencies->Projects.
Right click on Y's project then Properties.
Set Private Assets to All
Now this will add Y's dll file in the lib folder in the X's nuspec file.
This will work fine if Y doesn't depend on any other Nuget packages that X doesn't know about, because those packages will not be mentioned as dependencies in X's nuspec file.
Finally I settled down on this:
Just reference Y, generate package for it too and live with it :'(
In VS2019 nuget doesn't consider referenced projects as lib, but as
nuget packages
Actually, the new nuget feature which you used and also PackagePath="lib" function will treat the dll as a nuget dependency rather than an assembly dll.
If you simply want Y to be an Assembly DLL rather than a nuget package, these methods won't work. I have tried these methods, and it really made me struggling.
After a deep research, I found that the problem is that dotnet pack will add the referenced project as a nuget pacakge into the main nuget package automatically. Because dotnet pack will automatically generates an Nuspec file to package the project according to its rules, which treat the referenced project as a Nuget package by default. You can open the X.nupkg file and will see like this under X.nuspec file:
However, in this pack mechanism, we do not have the right to change the rule.
Suggestion
1) when you create the X.nupkg file using Pack Button in VS2019, please do some changes to X.nupkg manually.
Use zip to open nuget compressed package, then open X.nuspec file and delete these node:
<dependencies>
<group targetFramework=".NETStandard2.0">
<dependency id="Y" version="1.0.0" exclude="Build,Analyzers" />
</group>
</dependencies>
Save the changes and then use the modified X.nupkg.
2) Or you should create a custom nuspec file based on our needs and rules manually to guidance the nuget pack process.
Try to use this nuspec file:
<?xml version="1.0"?>
<package >
<metadata>
<id>xxx</id>
<version>1.0.0</version>
<title>xx</title>
..................
</metadata>
<files>
<file src="bin\xxx\xxx\Y.dll" target="lib\xxx(targetframework)"/>
</files>
</package>
Also if Y has another Nuget dependency, it should be considered in X
without referencing it directly in X.
So far, Nuget does not have the feature to ask the main project whether to use the dependency package dll of the referenced project.
And the dependencies from the referenced projects always exist in the main project.
Besides, if you still want these, you could report these problems on our Team Forum and I hope the Team will check them carefully and give you a satisfactory reply.

Code analysis rule set is not updated from nuget package

I'm trying to use custom ruleset file from nuget package. I added given .props to the build folder of the package:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CodeAnalysisRuleSet>MyProject.CodeAnalysis.ruleset</CodeAnalysisRuleSet>
<RunCodeAnalysis>true</RunCodeAnalysis>
</PropertyGroup>
</Project>
After installing nuget package to project I see that rule set file is in the package root folder, the paths are correct:
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\MyProject.CodeAnalysis.3.0.0\build\MyProject.CodeAnalysis.props" Condition="Exists('..\packages\MyProject.CodeAnalysis.3.0.0\build\MyProject.CodeAnalysis.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
But Visual Studio is not seeing correct rule set. When I open active rule set from References -> Analyzers, it's pointing to different file: MinimumRecommendedRules.ruleset. So it's using rules from this file not from my one.
My .nuspec file incldes this code:
<files>
<file src="MyProject.CodeAnalysis.ruleset" target="content/StyleCop" />
<file src="build\**\*.*" target="build" />
</files>
Structure of nuget package in Nuget Package Explorer looks like this:
build
MyProject.CodeAnalysis.props
content
StyleCop
MyProject.CodeAnalysis.ruleset
My configuration is:
Visual Studio 2019, ver. 16.6.0
Project Target: .NET Framework v4.7.2
What I do wrong?
P.S. I see this posts, but they didn't help me:
Code Analysis is not working with ruleset from nuget package (from .props)
Add code analysis ruleset through nuget package
Code analysis rule set is not updated from nuget package
I think the main issue is that you should use MyProject.CodeAnalysis.targets file in the build folder rather than MyProject.CodeAnalysis.props file.
As this document said,
.props is added at the top of the project file; .targets is added at the bottom.
So when you use .props file, it will read the custom rulset file before you imported the file into your project, so you will miss that file.
To solve it, you should use .targets file.
Solution
Update 1
1) change to use MyProject.CodeAnalysis.targets file in the build folder rather than MyProject.CodeAnalysis.props .
2) add your code in this file
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CodeAnalysisRuleSet>MyProject.CodeAnalysis.ruleset</CodeAnalysisRuleSet>
<RunCodeAnalysis>true</RunCodeAnalysis>
</PropertyGroup>
</Project>
3) Instead, use this in your .nuspec file.
<files>
<file src="MyProject.CodeAnalysis.ruleset" target="content" />
<file src="build\**\*.*" target="build" />
</files>
4) Then you pack your nuget project and when you install it in other main project, you should build the project first, and then you can find that the new ruleset file is enabled automatically under References --> Analyzers.
This shows correctly in Analyzers:
In addition, when you try to create a new version by suggestions, you should first, clean your global nuget cache first. Usually, delete all files under C:\Users\xxx(current user)\.nuget\packages.
Besides, use a new version called 1.1.1 in .nuspec file.
<version>1.1.1</version>
Then create a new net framework project to install the new version of the package to test again.
Any concern and feedback will be expected. We are looking forward to hearing from you.

Categories

Resources