Creating and Publishing a Package

Getting Started

  1. Download NuGet.exe
  2. Make sure NuGet.exe is in your path

If you’re more GUI inclined, use the Package Explorer GUI to create packages.

Share your Package

Upgrade to the latest version of NuGet.exe (or download it here)

NuGet Update

Store your API Key

NuGet SetApiKey Your-API-Key

Build your NuGet Package

NuGet Pack YourPackage.nuspec

Publish your package

NuGet Push YourPackage.nupkg

Installing NuGet.exe

  1. Download NuGet.exe
  2. Place NuGet in a well known location such as c:\utils on your machine
  3. Make sure that NuGet.exe is in your path

To learn about the nuget commands, run nuget help or refer to the NuGet.exe Command Line Reference.

Creating a Package

There are a few approaches to creating a package. Most packages are very simple and contain a single assembly. In those cases, there are some very easy ways to create packages. We’ll cover more interesting cases later.

From an assembly

If you have an assembly, you can easily generate a nuspec file from metadata within the assembly and create a package.

nuget spec MyAssembly.dll

This creates a Nuspec file. Edit the NuSpec file as needed and then

nuget pack MyAssembly.nuspec

From a project

For simple packages, creating a package from a csproj or vbproj file is a convenient way to create packages. For example, other packages that have been installed into your project will be referenced as dependencies when you create a package this way.

In the folder where the csproj file is, run:

nuget spec

This creates a special nuspec file with tokens meant to be replaced at pack time based on the project metadata. For example, $version$ gets replaced by the version specified in the AssemblyVersionAttribute applied to your assembly (typically within the AssemblyInfo.cs file).

The following is a list of the supported replacement tokens.

TokenSource
$id$ The Assembly name
$version$ The assembly version as specified in the assembly’s AssemblyVersionAttribute.
$author$ The company as specified in the AssemblyCompanyAttribute.
$description$ The description as specified in the AssemblyDescriptionAttribute.

You can then edit this nuspec file if you need to customize it. e.g. if you don't want token replacement for some fields, you hard code then in the nuspec instead.

Also, if you want to pull additional files into the package, you can use a node in the nuspec. e.g. suppose you want to add all the files from some arbitrary other folder into the package, you'd have:

<files>
    <file src="/img/spacer.gif"> 

Once your nuspec is ready, you can run:

nuget pack MyProject.csproj

Note that you need to run 'nuget pack' on the project file, not the nuspec itself. But the nuspec will in fact get picked up.

By default, NuGet will use the default build configuration set in the project file (typically Debug). To pack files from a different build configuration (e.g., Release), you can run:

nuget pack MyProject.csproj -Prop Configuration=Release

To change the project default for future packaging calls, modify the project file directly; Visual Studio does not offer a convenient method of altering this setting in the project properties GUI. To edit this file in Visual Studio, first unload it by right-clicking the project and choosing "Unload Project".

spacer

To edit the project file, right-click the unloaded project and choose "Edit {your-project-name}.{cs|vb|etc.}proj".

spacer

In typical project files, the first <Project><PropertyGroup> will contain a <Configuration> element that can be modified to choose your preferred build configuration (typically Release).

<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>

You can also use the -Symbols flag to include a symbols package as well. A symbols package allows others to step into your package’s code in the debugger.

For a detailed walkthrough showing how to create and publish NuGet packages from a project, see The easy way to publish NuGet packages with sources on David Ebbo’s blog.

From a convention based working directory

Some packages contain more than just assemblies. They may contain

  1. Content and source code that should be injected into the target project.
  2. PowerShell scripts and executables.
  3. Configuration file and source code transformations.

To create a package in this way, you can layout a directory structure that follows the NuGet conventions.

  • tools - The tools folder of a package is for powershell scripts and programs accessible from the Package Manager Console. After the folder is copied to the target project, it is added to the `$env:Path (PATH) environment variable.
  • lib - Assemblies (.dll files) in the lib folder are added as assembly references when the package is installed.
  • content - Files in the content folder are copied to the root of your application when the package is installed.

Think of the Content folder as the root of your target application. For example, if I want to a package to add an image in the /images directory of the target application, make sure to place the image in the Content/images folder of the package.

Create the manifest

To create a spec file from scratch, run the following command.

nuget spec

This will create an XML file with the .nuspec extension.

<?xml version="1.0"?>
<package xmlns="schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
  <metadata>
    <id>MyPackageId</id>
    <version>1.0</version>
    <authors>philha</authors>
    <owners>philha</owners>
    <licenseUrl>LICENSE_URL_HERE_OR_DELETE_THIS_LINE</licenseUrl>
    <projectUrl>PROJECT_URL_HERE_OR_DELETE_THIS_LINE</projectUrl>
    <iconUrl>ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Package description</description>
    <tags>Tag1 Tag2</tags>
    <dependencies>
      <dependency id="SampleDependency" version="1.0" />
    </dependencies>
  </metadata>
</package>

Edit this file to fill in the values appropriate for your package. Then create the folders needed by your package and copy the correct content in each folder.

mkdir lib
mkdir tools
mkdir content
mkdir content\controllers

copy ..\src\SomeController.cs content
copy ..\src\MyLibrary lib
copy ..\src\SomePowershellScript.ps1 tools

With the working directory in place with content, run the following command:

nuget pack YourPackage.nuspec

To create your package.

Publishing

Create an account at NuGet.org

Head over to nuget.org/ and register for an account. Once you do that, click on "My Account" to see an API Key that was generated for you.

In a command console, run the command:

nuget setApiKey Your-API-Key

This will store your API key so that you never need to do this step again on this machine.

Package Conventions

There are two types of conventions that apply when creating packages. The conventions listed in this page are enforced conventions which have to follow when building packages. There are also community (or optional) conventions, which have been formed by the community in order to make it easier for others to understand what your package is all about and make use of it immediately. For information about community conventions, see the Package Conventions page. This page will continue to be updated as new conventions are defined.

Supporting Multiple .NET Framework Versions and Profiles

Many libraries target a specific version of the .NET Framework. For example, you might have one version of your library that's specific to Silverlight, and another version of the same library that takes advantage of .NET Framework 4 features. You do not need to create separate packages for each of these versions. NuGet supports putting multiple versions of the same library in a single package keeping them in separate folders within the package.

Framework Version Folder Structure

When NuGet installs an assembly from a package, it checks the target .NET Framework version of the project you are adding the package to. NuGet then selects the correct version of the assembly in the package by selecting the correct subfolder within the lib folder.

To enable NuGet to do this, you use the following naming convention to indicate which assemblies go with which framework versions:

lib\{framework name}{version}

The following example shows a folder structure that supports four versions of a library:

\lib
    \net11
        \MyAssembly.dll
    \net20
        \MyAssembly.dll
    \net40
        \MyAssembly.dll
    \sl40
        \MyAssembly.dll

Framework Names

NuGet attempts to parse the folder name into a FrameworkName object. Names are case insensitive, and you can use abbreviations for both framework name and version number.

If you omit the framework name, the .NET Framework is assumed. For example, the following folder structure is equivalent to the previous one:

\lib
    \11
        \MyAssembly.dll
    \20
        \MyAssembly.dll
    \40
        \MyAssembly.dll
    \sl4
        \MyAssembly.dll

The following is a list of valid framework names and abbreviation:

Framework NameAbbreviations
.NET Frameworknet
Silverlightsl
.NETMicroFrameworknetmf

Assemblies that are not Specific to a Framework Version

Assemblies that have no associated framework name or version are stored directly in the lib folder.

Matching Assembly Version to the Target Framework of a Project

When NuGet installs a package that has multiple assembly versions, it tries to match the framework name of the assembly with the target framework of the project. If a match is not found, NuGet copies the assembly that's for the highest version that is less than or equal to the project's target framework. For example, if you install a package that has the lib folder structure shown in the previous example in a project that targets the .NET Framework 3.5, the assembly in the 2 folder (for .NET Framework 2.0) is selected.

Grouping Assemblies by Framework Version

NuGet copies assemblies from only a single library folder. For example, suppose a package has the following folder structure:

\lib
    \Net20
        \MyAssembly.dll (v1.0)
        \MyAssembly.Core.dll (v1.0)
    \Net40
        \MyAssembly.dll (v2.0)

When the package is installed in a project that targets the .NET Framework 4, MyAssembly.dll (v2.0) is the only assembly installed. MyAssembly.Core.dll (v1.0) is not installed. (One reason why NuGet behaves this way is that MyAssembly.Core might have been merged into version 2.0 of MyAssembly.)

In this example, if you want MyAssembly.Core.dll to be installed in a project that targets the .NET Framework 4, you must include it in the Net40 folder as well as in the Net20 folder.

The rule about copying assemblies from only one folder also applies to the root lib folder. Suppose a package has the following folder structure:

\lib
    \MyAssembly.dll (v1.0)
    \MyAssembly.Core.dll (v1.0)
    \Net40
        \MyAssembly.dll (v2.0)

In projects that target the .NET Framework 2.0 and the .NET Framework 3.5, NuGet copies both MyAssembly.dll and MyAssembly.Core.dll. But as was true of the previous example, in projects that target the .NET Framework 4, only MyAssembly.dll *from the *Net40 folder will be copied.

As in the previous example, if you want MyAssembly.Core.dll to be installed in a project that targets the .NET Framework 4, you must include it in the Net40 folder.

Grouping Assemblies by Framework Profile

NuGet also supports targeting a specific framework profile by appending a dash and the profile name to the end of the folder.

lib\{framework name}-{profile}

For example, to target the Windows Phone profile, place your assembly in a folder named sl3-wp.

Profiles supported by NuGet include:

  • Client - Client Profile
  • Full - Full Profile
  • WP - Windows Phone

At the time of this writing, to target the Windows Phone profile, the Silverlight 3 framework must be specified. It is anticipated that in the future, later versions of Silverlight will be supported on the phone.

Profile NameAbbreviations
Clientclient
WindowsPhonewp
CompactFrameworkcf
Fullfull

Common Framework and Profile Targeting Examples

The following provides examples of common targets.

ToolTargetNotes
.NET 4.0net40Just using '40' also works.
.NET 4.0 Client Profilenet40-client
.NET 4.0 Full Profilenet40-fullRequires full .NET profile
.NET 4.0 Compact Frameworknet40-cfnet40-compactframework also works.
Silverlight 4.0sl4
Windows Phone 7.0sl3-wp
Windows Phone 7.1 (Mango)sl4-windowsphone71

Deleting packages

NuGet.org does not support permanent deletion of packages, because that would break anyone who is depending on it remaining available. This is particularily true when using the workflow that restores packages on build.

Instead, NuGet.org supports a way to 'unlist' a package, which can be done in the package management page on the web site. When a package is unlisted, it no longer shows up in search and in any package listing, both on NuGet.org and from the NuGet Visual Studio extension (or nuget.exe). However, it remains downloadable by specifying its exact version, which is what allows the Restore workflow to continue working.

If you run into an exceptional situation where you think one of your packages must be deleted, this can be handled manually by the NuGet team. e.g. if there is a copyright infrigement issue, or potentially harmful content, that could be a valid reason to delete it.

Automatically Running PowerShell Scripts During Package Installation and Removal

A package can include PowerShell scripts that automatically run when the package is installed or removed. NuGet automatically runs scripts based on their file names using the following conventions:

  • Init.ps1 runs the first time a package is installed in a solution.
    • If the same package is installed into additional projects in the solution, the script is not run during those installations.
    • The script also runs every time the solution is opened. For example, if you install a package, close Visual Studio, and then start Visual Studio and open the solution, the Init.ps1 script runs again.
  • Install.ps1 runs when a package is installed in a project.
    • If the same package is installed in multiple projects in a solution, the script runs each time the package is installed.
    • The package must have files in the content or lib folder for Install.ps1 to run. Just having something in the tools folder will not kick this off.
    • If your package also has an init.ps1, install.ps1 runs after init.ps1.
  • Uninstall.ps1 runs every time a package is uninstalled.
  • These files should be located in the tools directory of your package.
  • At the top of your file, add this line: param($installPath, $toolsPath, $package, $project)
    • $installPath is the path to the folder where the package is installed
    • $toolsPath is the path to the tools directory in the folder where the package is installed
    • $package is a reference to the package object.
    • $project is a reference to the EnvDTE project object and represents the project the package is installed into. Note: This will be null in Init.ps1. In that case doesn't have a reference to a particular project because it runs at the solution level. The properties of this object are defined in the MSDN documentation.
  • When you are testing $project in the console while creating your scripts, you can set it to $project = Get-Project

If you want to learn about your actual output, NuGetPSVariables is a helper package that writes information out to a series of log files. You can make use of the package with the following call:

Install-Package NuGetPSVariables

NuGetPSVariables displays the log files and uninstalls itself.

gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.