Thursday, January 20, 2011

Installing NuGet packages directly from the command line

Most of the coverage around NuGet revolves against its clean integration to Visual Studio, which makes adding references to packages as easy as adding references to local assemblies. While this is indeed a key scenario, it is important to note that the core of NuGet is completely decoupled from Visual Studio, and was designed with that goal from day 1.

If we look back at the early days of NuGet, it was in many ways inspired by the ‘Nu’ project (which members have since joined NuGet). What Nu had was a solid command line driven experience to bring down .NET bits to your machine. In their case, it was based on Ruby Gems, but that is an implementation details. Take a look at Rob Reynolds’s original screencast to see what the Nu experience was about.

While we have been planning all along to provide the same experience with NuGet (in addition to the VS experience of course), it’s something that had somewhat fallen off the radar, and it just had not been done. This was unfortunate, because we already had all the plumbing to make it happen, and all it needed was about 10 lines of code to expose this!

So I’m happy to say that we have now filled this little hole by implementing a new ‘install’ command in our NuGet.exe command line tool. Using it couldn’t be any easier, and I’ll walk you through an example.

Where do I get NuGet.exe?

You first need to get NuGet.exe. This is the same tool that package authors have been using to create packages and upload them to the http://nuget.org gallery.

The easiest way to get it is to download it from CodePlex.

You can also obtain it via NuGet itself by installing the package name NuGet.CommandLine (using Visual Studio).

How do I run it?

The best way to demonstrate it is to just show a sample session.

D:\>md \Test

D:\>cd \Test

D:\Test>nuget list nhi
FluentNHibernate 1.1.0.694
FluentNHibernate 1.1.1.694
NHibernate 2.1.2.4000
NHibernate 3.0.0.2001
NHibernate 3.0.0.3001
NHibernate 3.0.0.4000
NHibernate.Linq 1.0
NHWebConsole 0.2
SolrNet.NHibernate 0.3.0

D:\Test>nuget install NHibernate
'Iesi.Collections (≥ 1.0.1)' not installed. Attempting to retrieve dependency from source...
Done.
'Antlr (≥ 3.1.3.42154)' not installed. Attempting to retrieve dependency from source...
Done.
'Castle.Core (≥ 2.5.1)' not installed. Attempting to retrieve dependency from source...
Done.
Successfully installed 'Iesi.Collections 1.0.1'.
Successfully installed 'Antlr 3.1.3.42154'.
Successfully installed 'Castle.Core 2.5.2'.
Successfully installed 'NHibernate 3.0.0.4000'.

D:\Test>tree
Folder PATH listing
Volume serial number is 26FF-2C8A
D:.
├───Antlr.3.1.3.42154
│   └───lib
├───Castle.Core.2.5.2
│   └───lib
│       ├───NET35
│       ├───NET40ClientProfile
│       ├───SL3
│       └───SL4
├───Iesi.Collections.1.0.1
│   └───lib
└───NHibernate.3.0.0.4000
└───lib

D:\Test>dir Antlr.3.1.3.42154\lib
Volume in drive D has no label.
Volume Serial Number is 26FF-2C8A

Directory of D:\Test\Antlr.3.1.3.42154\lib

01/20/2011  05:06 PM           117,760 Antlr3.Runtime.dll

Why would you want to use this instead of the Visual Studio integration?

For most users, the Visual Studio integration will be the right choices. But suppose you want to work much more ‘manually’, and not deal with VS or even with a .csproj file. e.g. all you want is to bring down nhibernate.dll so you can write some code against it, and compile it manually using ‘csc /r:nhibernate.dll MyCode.cs’.

In this scenario, you just want NuGet to download the assemblies for you, and leave the rest to you. It still saves you a lot of time by letting you easily download the bits and all their dependencies, but it doesn’t force you into a development model that may not be want you want.

So I don’t think it’s a feature that the majority of users will use, but it is important to have it for those who need it.

26 comments:

  1. Very nice, I just tried it in an environmet where I cannot install the NuGet VS-plugin due to permission issues. It nicely gets the packages in my directory, but it does not change my csproj. I wouldn't mind if it did that.
    Also there is no uninstall. Looking forward to the next version!

    ReplyDelete
  2. @mountain: indeed, this is currently only about bringing down the package bits, and not trying to automatically add them to any project. Maybe we can think about that in the future.

    As for uninstall, just delete the package folder :)

    ReplyDelete
  3. Hi David,

    Thanks for the info. I was wondering if there were plans to allow a user to get multiple packages in one shot? Something along the lines of:

    D:\foo> nuget install Castle.Windsor Castle.Windsor-log4net Castle.DynamicProxy FluentNHibernate

    It would be awesome if NuGet managed the dependencies in such a way to make sure that the 4 libraries I requested all worked together.

    ReplyDelete
  4. @Bobby: NuGet already manages dependencies. See my example above where I just ask for NHibernate and it bring in 3 additional packages. You don't need to ask for them one by one.

    ReplyDelete
  5. Yes but say I want to use Fluent NHibernate and Fluent Validation. They share a dependency say Castle.Core but maybe not the same version. It would be nice if i could request the two packages in one request and NuGet does whatever magic is needed to make them play nice together. See what I am saying?

    ReplyDelete
  6. All of this is taken care of today by NuGet if you install into a project from VS. But the command line tool allows side by side of multiple versions of a package, so it does not attempt to do any unification.

    ReplyDelete
  7. Assuming I have a "local" feed which contains my private packages, is it possible to use the command-line utility to update my projects with the latest versions of my packages ?

    ReplyDelete
  8. @Maciek: you can use the -source attribute to specify the feed. However, it doesn't currently work if packages.config contains packages from multiple feeds. There is a bug tracking this.

    ReplyDelete
  9. Ok, tried something like this but no luck;

    nuget.exe Install JQuery -Path .\Test

    How can I achieve this?

    ReplyDelete
  10. Also, is there a way to uninstall package with command line?

    ReplyDelete
  11. @Tugberk: use the -OutputDirectory (or -o) flag, not -Path. To uninstall, simply delete folder.

    ReplyDelete
  12. @David cool. thanks a lot.

    ReplyDelete
  13. What does the command-line install process do, exactly? The connotation of the word "install" includes things like registry entries and GAC assemblies, but the only visible result of a "nuget install" command is a new folder with some files in it. If that's all "nuget install" does, maybe it should be called "nuget download" instead.

    ReplyDelete
  14. @Qwertie: you're correct, calling the command 'install' was a poor choice.

    ReplyDelete
  15. Really nice, thanks for making it available. It would be nice if "list" had an option to include matching package name only. If I run ".\nuget.exe list entityf" I see all the packages that need entity framework (I guess, anyway a bunch of stuff).

    not really nuget.exe related but I note that the fwlink when I do "nuget sources" is all digits, when rendered with the 7 segment scheme associated with 1970s style digital watches, become valid alphabetic characters, and that it spells llhoez.

    peace out man

    ReplyDelete
  16. @lmagruder agreed that the 'nuget list' behavior can return way too much. Feel free to open an issue about it on http://nuget.codeplex.com/.

    Wow, I don't think anyone has ever looked that closely at our fw URL. There must be a hidden meaning in there! :)

    ReplyDelete
  17. I blogged about creating a local Nuget repository/cache here: http://joshilewis.wordpress.com/2012/01/13/creating-a-local-nuget-cacherepository/

    It would be great if Nuget could provide better support for this in the future. One feature I'd really like to see is the ability to scan a local repository, and update (the Nuget install command) all packages if there are newer packages available.

    ReplyDelete
  18. @Joshua: would you mind opening an issue on http://nuget.codeplex.com/ to track this? Thanks!

    ReplyDelete
    Replies
    1. Done: http://nuget.codeplex.com/workitem/1958
      Thanks!

      Delete
  19. Thanks very much for this blog entry, it is very helpful. When I see how MSFT is nowadays providing software I wonder if they ever have been in a real enterprise. Downloading Software right from the internet onto a developer PC, well that is not really realistic. Maybe on my home & hobby pc but not in a corporate environment with security policies in place.

    ReplyDelete
  20. Hi David,

    I have just looking into Nuget to be used with VS2008 as we develop software on Compact Framework. I have managed to package CF assemblies and install it and all works fine from command line. I was wondering if we can update the packages without the packages.config from command line for VS2008.

    ReplyDelete
  21. @ajmal Could you post your question to http://nuget.codeplex.com/ instead? It'll get more people seeing it there. Thanks!

    ReplyDelete
  22. David. Form my tests and your answer Qwertie I see that there is no way to trigger Install.ps1 or Init.ps1 in the package when you are using command line, correct?

    ReplyDelete
  23. Great explanation! I would like your help on a question. I don’t know if this blog is the correct place for it, but here goes.

    I’m trying to use the AddExtension command from package AddConsoleExtension with no success. My goal is to use the NuGet Copy Extension. I have installed the NuGet Extend using the command:
    NuGet.exe Install /ExcludeVersion /OutputDir "D:\Documents and Settings\myuser\Local Settings\Application Data\NuGet\Commands" AddConsoleExtension

    After that, when I try to execute the command:
    NuGet.exe addextension nuget.copy.extension

    I’m receiving the following error message:
    Method not found: 'Void NuGet.Commands.InstallCommand..ctor(NuGet.IPackageRepositoryFactory, NuGet.IPackageSourceProvider)'.

    Do you know what I am doing wrong?

    Thank you!

    ReplyDelete
  24. @Paulo: the best place to ask NuGet questions is http://nuget.codeplex.com/. Thanks!

    ReplyDelete
  25. Did anyone get around updating .csproj file from command line?

    ReplyDelete