NuGet package shows no dependencies?
Asked Answered
O

2

16

I try to make a NuGet package from a .NET 4.7.2 class library (VS2017), but the resulting NuGet package surprisingly shows no dependencies (which is an error).

My setup is like this:

  • My class library is .NET Framework 4.7.2
  • My class library uses another NuGet package (that has dependencies).
  • My class library uses packageReferences in .csproj
  • My class library contains a proper .nuspec file
  • I use nuget.exe pack for creating the package

The nuget.exe pack command should automatically fill in the needed dependencies - this also used to be the case earlier (in another project). However, at that time I used packages.config instead of packageReferences with my class library. Does that change anything?

What is going on?

How can I force the system to again include the needed dependencies in my package?

Notes:

  • The package is built by a MSBuild script on our TeamCity build server (without VS2017). It's the build script that calls both "nuget.exe restore" and later "nuget.exe pack" as part of its build logic.

  • MSBuild is version 15.7

  • nuget.exe is version 4.6.2

Oaf answered 13/8, 2018 at 12:50 Comment(0)
T
20

How can I force the system to again include the needed dependencies in my package?

This is a known issue about nuget pack is ignoring dependencies when using PackageReference instead of packages.config.

To resolve this issue, you can use the workaround from that link of referencing NuGet.Build.Tasks.Pack and using msbuild -t:pack to pack it. NuGet team are still actively working on improving this scenario.

I have tested this workaround, and it works fine. However, the msbuild command requires a little more detail.

  • Add the nuget package NuGet.Build.Tasks.Pack to the project, as stated in the GitHub issue.

  • Use the command msbuild.exe /t:pack. NuGet will error out if there's no Authors property, and you will probably want to set the output directory to something other than the default:

    msbuild.exe /t:pack "MyTestLibrary.csproj" /p:PackageOutputPath="D:\TestFolder" -p:Authors=tester
    

However, if you want to use a .nuspec file to create the nuget package, you should use the following .nuspec file:

<?xml version="1.0"?>
<package >
  <metadata>
    <id>MyTestLibrary</id>
    <version>1.0.0</version>
    <authors>Tester</authors>
    <owners>Tester</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Package description</description>
    <releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
    <copyright>Copyright 2018</copyright>
    <tags>Tag1 Tag2</tags>
    <dependencies>
      <group targetFramework=".NETFramework4.7.2">
        <dependency id="Microsoft.Owin" version="4.0.0" exclude="Build,Analyzers" />
      </group>
    </dependencies>
  </metadata>

    <files>
        <file src="bin\Debug\MyTestLibrary.dll" target="lib\net472\MyTestLibrary.dll" />
    </files>
</package>

Then we could use nuget.exe pack to create the nuget package. But, using this method, we have to manually fill in the needed dependencies in the .nuspec file.

Tribade answered 14/8, 2018 at 6:14 Comment(0)
D
2

I got the same issue and use 2nd way leo Liu mention with Pattrick'script and some small modification to overcome this issue. Below are steps:

  1. Copy or download powershell script below, name it NuGetPackDependencies.ps1 and add it to your solution (Because I want to reuse the same script for many projects in this solution) enter image description here
function Format-XML {Param ([string]$xmlfile) 
  
  $Doc=New-Object system.xml.xmlDataDocument 
  $doc.Load((Resolve-Path $xmlfile)) 
  $sw=New-Object system.io.stringwriter 
  $writer=New-Object system.xml.xmltextwriter($sw) 
  $writer.Formatting = [System.xml.formatting]::Indented 
  $doc.WriteContentTo($writer) 
  $sw.ToString() 
}

'*****'
'***** PowerShell script NugetPackDependencies 1.0.'
'***** Insert project package references as dependencies into package manifest (nuspec file)'
'*****'
'***** Start script'
'*****'

Set-Location -Path $args[0]

# Get VB.NET or C# project file.
$projFile = (ls -Path "*.vbproj", "*.csproj" | Select-Object -First 1).Name

# If project file cannot be found exit script.
if ($projFile -eq $null) {'***** Project file not found. Exit script'
                            exit}
else {"***** Get package references from project file: '" + $projFile + "'"} 


                  
# Get content from project file.
$projFileContent = ls -Filter $projFile | Get-Content

# Convert content from project file to XML.
$projFileXml  = [xml]$projFileContent


# Namespace 
$nm = New-Object -TypeName System.Xml.XmlNamespaceManager -ArgumentList $projFileXml.NameTable
$nm.AddNamespace('x', 'http://schemas.microsoft.com/developer/msbuild/2003')


# Get package references from project file xml and put them in an list of new objects containg id and version.
$packRefs=$projFileXml.SelectNodes('/x:Project/x:ItemGroup/x:PackageReference', $nm) | 
ForEach-Object {New-Object -TypeName PSObject -Property @{
                    id = New-Object -TypeName Reflection.AssemblyName -ArgumentList $_.Include
                    version = New-Object -TypeName Reflection.AssemblyName -ArgumentList $_.Version}               
                } 

Write-Output $packRefs

# Create new XML tags for the nuspec file containing the id and version.
$packRefsXml= $packRefs | Select-Object @{L='deps'; E ={ "<dependency id=""" + $_.id + """ version=""" + $_.version + """ />"}}


# concatenate the tags.
$packRefsXmlConcat = ""
$packRefsXml | ForEach-Object { 
$packRefsXmlConcat = $packRefsXmlConcat +  $_.deps
}

# Get the nuspec file.
$nuspec = (ls -Path "*.nuspec" | Select-Object -First 1)
$nuspecFile = $nuspec.FullName

# If nuspec file cannot be found exit script.
"*****"
if (!$nuspecFile) {Write-Output '***** Nuspec file not found. Exit script'
                    exit}
else{"***** Insert dependencies into nuspec file: '" + $nuspec.NAme + "'"} 

# Put the nuspec XML in a var using .NET XmlDocument
$xmlNuspec = New-Object System.Xml.XmlDocument
$xmlNuspec.PreserveWhitespace = $true
$xmlNuspec.Load($nuspecFile)

# Remove all dependencies elements if present.
$tags =$xmlNuspec.package.metadata.SelectNodes("dependencies")

ForEach($tag in $tags) {
$xmlNuspec.package.metadata.RemoveChild($tag) | Out-Null # Suppress unwanted Output
}

# Namespace.
$nm = New-Object -TypeName System.Xml.XmlNamespaceManager -ArgumentList $xmlNuspec.NameTable
$nm.AddNamespace('x', '')

# Get the metadata tag from the xml
$metaDataElement = $xmlNuspec.SelectNodes('/x:package/x:metadata', $nm)  

# Create new dependecies element
$newDependenciesChild = $xmlNuspec.CreateElement("dependencies") 

# Add dependency elements to dependencies element
$newDependenciesChild.set_innerXML($packRefsXmlConcat) | Out-Null # Suppress unwanted Output

# Append dependencies child to metdata child
$metaDataElement.AppendChild($newDependenciesChild) | Out-Null # Suppress unwanted Output

# Write output to temporary nuspec file
$xmlNuspec.OuterXml | Out-File -filepath temp.nuspec 

# Pretty the nuspec file and overwrite original nupec file using the format-XML function.
Format-XML -xmlfile temp.nuspec | Out-File -filepath $nuspecFile

# delete temp nuspec.
del temp.nuspec

"*****"
"***** Finished script"
"*****"
  1. Config Post-Build Event

[Post-Build Event]

cd $(SolutionDir)
powershell.exe -ExecutionPolicy Bypass -NoProfile -NonInteractive -File NuGetPackDependencies.ps1 $(ProjectDir)
  1. Build and publish your project as you did before.
Disciplinary answered 9/1, 2020 at 11:18 Comment(3)
I understand the idea. But I get an exception on the default file and the file is erased (82 byte): 1> ***** Insert dependencies into nuspec file: 'Prog.nuspec' 1> Exception when calling "Load" with" 1 " arguments: "".", hexadecimal value 0x00, is an invalid sign., line 2, position 1."D:\Prog\NuGetPackDependencies.ps1:4 знак:3 1> + $doc.Load((Resolve-Path $xmlfile)) 1> + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1> + CategoryInfo : NotSpecified: (:) [], MethodInvocationException 1> + FullyQualifiedErrorId : DotNetMethodException 1> ***** Finished scriptWeanling
I guess there are some Unicode characters in the generated temp.nuspec file. Try to remove the last line of deleting temp.nuspec and see what is the output, try to change it may help.Disciplinary
Method invocation failed because [System.Xml.XPathNodeList] does not contain a method named 'AppendChild'. Changed line 87 from $metaDataElement = $xmlNuspec.SelectNodes('/x:package/x:metadata', $nm) to $metaDataElement = $xmlNuspec.package.metadata and it worked fine.Ladyfinger

© 2022 - 2024 — McMap. All rights reserved.