Private, easily installable library packages with NuGet and MyGet

Most, if not all, software development organizations have their own set of standard tool libraries, and Offbeat Solutions is no exception. We’ve only been at this for about a year, and thus far we’ve rolled up just one, a generic tool belt that we unimaginatively called “oblib”. Now, while libraries are fun, managing the installation of libraries can suck major donkey. So enter NuGet, the fledgling package manager from Microsoft. NuGet, and particularly its Visual Studio extension makes it ridiculously easy to install your favorite libraries. Wouldn’t it be great if your private tools were just as easily installable? Who says they can’t be? Let’s do this thing! If you’ve installed ASP.NET MVC 3 tooling for Visual Studio, you’ve already got the NuGet extension. If not, install it from Visual Studio Gallery. [Note: if you already have NuGet installed, you may want to check the Extension Manager for updates – the early versions didn’t always play nice with MyGet authentication] NuGet packages are relatively simple beasts. You build the packages by creating a manifest file containing some metadata about the package in question, point the command line tool NuGet.exe at the metadata file and… that’s about it. Doesn’t sound too hard, so let’s give it a whirl! Let’s start by getting the command line tool. Open the project you want to package, go to Solution Explorer in Visual Studio and right-click on the References node. There should be an option titled “Manage NuGet Packages…”:

Click on the menu item, and up pops a dialog. On the left side of the dialog, expand the “Online” section, and then type “nuget command line” to the search field in the top right corner. That should bring up a package named NuGet.CommandLine:

Click on the “Install” button next to the package. Visual Studio should work for a moment, and then you can close the dialog. At this point, there should be a folder named “packages” at the root of your solution, containing the package we just installed. Now that we’ve got the command line tool, let’s create the package manifest, also known as a NuSpec file. Open up a command prompt (I prefer PowerShell) and go to the project directory. Invoke NuGet by calling packages\NuGet.CommandLine.1.5.21005.9019\tools\NuGet.exe spec path\to\yourlibrary.dll (adjust paths by taking into account your version of the command line package and the path to your compiled library):

This should produce a file starting with the name of your library, ending in .nuspec. Go back to Visual Studio, include the file in your solution and open it up in Visual Studio. It should look something like this:

<?xml version="1.0"?>
<package>
<id>$id$</id>
<version>$version$</version>
<title>$title$</title>
<authors>$author$</authors>
<owners>$author$</owners>
<projectUrl>http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE</projectUrl>
<iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>
<description>$description$</description>
<releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
<tags>Tag1 Tag2</tags>
</package>

Fill in something sensible, then save the file and close it. Go back to your command shell, create a directory called “release” and then call NuGet.exe pack yourlibrary.csproj –Build –OutputDirectory release:

Et voilà, we’ve got a NuGet package! Now, let’s make that a part of the build process. Unload the project in Visual Studio, and open the project file in the source editor. Add this as the AfterBuild task (adjusting for paths again):

  <Target Name="AfterBuild">
<RemoveDir Directories="$(ProjectDir)\release\" /> <MakeDir Directories="$(ProjectDir)\release\" />
<Exec Command="$(SolutionDir)\Packages\NuGet.CommandLine.1.5.21005.9019\tools\NuGet.exe pack$(ProjectFileName) -OutputDirectory $(ProjectDir)\release" /> </Target>  Reload the project, rebuild it, and with any luck, you should have a “release” folder containing a shiny, new NuGet package. Now that we’ve come this far, the last missing step is to make the package easily available. To this end, we’re going to use MyGet, a service that provides hosting for private NuGet feeds. After registering, you can create a package feed, set permissions to it and generate an API key – you should probably go do that now. At this point you store your API key for NuGet to use by calling NuGet.exe setApiKey [key] –Source [feed]/api/v1/: (Note: In case the blank spaces in the screenshot look confusing – that’s where I’ve erased my API key from public scrutiny). At this point, it’s a simple matter of running NuGet.exe push [package] –Source [feed]: and adding your private feed to Visual Studio. Open up Package Manager Settings: Add your personal feed to the list of available feeds: Once you’ve done this, you can install your package by opening up the “Manage NuGet Packages…” dialog again. At this point, if you configured your feed to require authentication, Visual Studio will prompt you for your user name and password. If you didn’t, you’ll get the feed contents straight away: Clicking on “Install” will pop up a progress indicator, after which the deed is done, and the library is ready for use. This concludes our show! Of course, this is by no means the whole story. There’s a bunch of stuff to consider from this point onwards. Some of them include: • Package dependencies: when your package requires another package in order to work • API versioning: what sort of changes can you make without breaking clients • Automatic publishing from a CI server But those are all topics for a later day. Get assembly files from GAC using PowerShell A while ago I found myself in an unfortunate situation where I had to use Reflector to figure out what I was doing wrong when interacting with third-party components. Unfortunately, a large part of the third-party code was in assemblies that were installed in the GAC, and I was unable to find them anywhere else. Here’s a quick PowerShell one-liner that helped me out: dir C:\Windows\Assembly -Recurse -Filter "VendorName*.dll" | foreach { copy$_.FullName C:\Temp\assemblies }

That was pretty quick and easy to come up with, and it makes me very glad I decided to learn the basics of PowerShell.

Speeding up PowerShell V1 startup time

One of the issues I had with PowerShell V1 that made me diss it was the considerable delay in starting it up.

Turns out there’s a relatively easy fix. You can AOT-compile the assemblies for what I hear is a significant drop in load times.

Power to the people

My esteemed colleague Jouni Heikniemi is a speaker at this year’s TechDays Finland. His topic is “PowerShell for Developers”. We had a chance to hear his presentation beforehand this morning. I’ve been meaning to do so for a few years now, but after the presentation I finally found the motivation to try and write an actual PowerShell script for myself.

The problem

I wanted a simple script to bundle an ASP.NET web application in a directory – basically, copy all the files that are essential to running the app, and nothing more. Something I’d typically use a NAnt or MSBuild task for.

The solution

So I fired up PowerShell ISE (I assume that’s Integrated Scripting Environment) and after a few attempts, came up with this:

$targetPath = "deploy" if (Test-Path$targetPath) { Remove-Item $targetPath -Recurse -Force } New-Item$targetPath -type directory

Copy-Item -Path .\App_Data -Destination $targetPath -Recurse Copy-Item -Path .\App_GlobalResources -Destination$targetPath -Recurse -Filter "*.resx"
Copy-Item -Path .\bin -Destination $targetPath -Recurse -Filter "*.dll" Copy-Item -Path ("*.as?x", "*.js", "*.gif", "*.jpg", "Web.config") -Destination$targetPath

Since it creates a directory that can be deployed as an application, I saved the snippet as Deploy.ps1 (in hindsight, Build.ps1 would have been a better name, but I’m too lazy to take another screenshot).

This bit of script is very specific to my needs, so don’t take it as a textbook example of good PowerShell scripting.

The snag and the resolution

As it turns out, PowerShell scripts aren’t allowed to run, at all, by default. Fortunately, the default is relatively easy to change. Fire up PowerShell or the ISE with administrative privileges, and type:

Set-ExecutionPolicy RemoteSigned

RemoteSigned means you’re free to run unsigned scripts as long as they’re locally created, but scripts downloaded from other sources need to be signed. In case you’re curious, downloaded scripts are identified based on Alternate Data Streams.

PowerShell will ask you to confirm this. In the case of ISE, by means of a really, really long-ass dialog text:

Once you confirm the change, you can restart PowerShell with limited privileges, and scripts will work.

For more info on PowerShell, visit Jouni’s series of blog posts on the topic.