Use Nuget to Share PowerShell Modules in your Enterprise

May 23, 2011 at 7:13 PMAndy Schneider

Nuget is not just for developers! If you are an IT Pro, you can use it as well. Nuget is a relatively new tool from Microsoft that provides the ability for people to easily share and use code. Microsoft is marketing it to developers as the way to share and use Open Source code in Visual Studio Projects. It does a great job at this and is really starting to take off in the developer community. But we, IT Pros, can take it and use it for PowerShell Modules.

So why would you want to use Nuget to source your enterprise scripts?

  • Versioning– You can match your Module Version numbers with the Nuget Package version
  • Dependencies – In a Nuget Package, you can say this package depends on this package, so check to see if its installed and if not, please install it for me.
  • At least 10 other cool things that I haven’t discovered yet.
    Nuget is a client server application. You can save a bunch of packages up on a server, and you use the client to download and install these packages. Microsoft hosts a Nuget server that currently has around 1500 published packages that you can use.

Last week at Teched Scott Hanselman gave a talk on using Nuget in the Enterprise.  The quick version of the talk is that you can host your own internal Nuget Server. In fact, all you really need to do is set up a file share. The other key is that all you need to access the packages on a Nuget Server is the Nuget command line tool

After seeing this talk, I was thinking this could be a great tool to distribute and share PowerShell Modules with the rest of my IT Department. What I didn’t know was whether or not it would be easy to package up a module and then install it using Nuget. So I started playing. As an example, I am going to use a Module I wrote to manage my work items in TFS.

The first thing to do is download the Nuget command line tool. After you download it, be sure to unblock it because it was downloaded from the Internet. I put the file in a directory in my documents folder and created an alias to it.

image

Once that is set up, you can start creating a package. There are a couple things you need to do if you are using the command line version of Nuget.

First, you need to create a spec file.  You can do this with the command nuget spec, as shown below. You can see that it creates an XML file.

image

There are all kinds of properties here that you can set. I am going to leave everything as default for demo purposes, except that I am going to rip out the dependency node and change the tag values to something more reasonable. This could obviously be automated very easily, but I simply used good old notepad2.

Now the dependency node is gone and tags are updated.

image

Once we have this we can create the package, again using nuget.exe. I really should mention that there are conventions for structuring a package. You can read all about it on http://nuget.org. I am going to completely ignore them because all I really care about the PowerShell Module.

Nuget.exe has a parameter called pack. You can specify a directory to package up by specifying the basepath parameter, the spec file, and the output directory.

image

Now I have a package called tfs.1.0.nupkg. NUPKG is the extension for Nuget Package. All this really is a zip file. In fact,you can rename this to tfs.1.0.zip and unzip the contents. In there is all the files for my modules.

OK, so now that I have a package, I need to put it somewhere where people can access it and pull it down with a Nuget client. There are tons of articles on how to create your own Nuget Server. http://docs.nuget.org/docs/creating-packages/hosting-your-own-nuget-feeds.

If you just want to use a file share, you can do that. Or you can actually build a NuGet Server Web Site. I guarantee that you won’t have to write any code, but you would have to install Visual Studio Express, or get a developer to build a quick app for you. NuGet server itself is a Nuget Package. With Visual Studio installed, I had my NuGet Server up and running in under 10 minutes. 

After you set up your Nuget Server, there is a directory where you can place your packages. It is appropriately named, “Packages.” Here is the directory where I have all my files for my local instance of IIS. You can see that I have two packages up here, one for the DataOnTap Module and the one we just created.

image

Here is the client listing the available packages from this source.

image

For the sake of demonstration, I created a folder called c:\modules and used nuget.exe to install my module there.

image

The only thing wrong with this is that the folder name contains the version and the nupkg file is still around. This can all be cleaned up pretty easily, manually, using PowerShell, or probably with some Nuget options I haven’t found yet.

I will be testing this out this week too see what else I can come up with. I am looking forward to seeing how versioning works. Also, I want to wrap some of this functionality with Advanced Functions.

If you install Visual Studio and Nuget, you will also get a set of PowerShell cmdlets to manage packages. However, as of right now the Module is not a separate download. I’ll look into this and let you know what else I find. I am sure there will be at least one or two follow up posts on this as I learn more about NuGet.

Posted in: PowerShell | Modules | Nuget

Tags:

How to Package and Distribute PowerShell Cmdlets, Functions, and Scripts

April 4, 2011 at 10:53 PMAndy Schneider

I have noticed quite a bit of discussions and questions in various online communities on how to package and distribute the PowerShell Cmdlets, Functions, and Scripts. What I love about PowerShell is that you can be fast and loose with distributing functionality, very rigorous, or anywhere in between, when it comes to code distribution. I have sent one-liners via IM to folks and I have checked code into Team Foundation Server. It all depends on what your goal is.

I would like to discuss distributing code with a little more rigor than using email or IM as a distribution vector, although that does work great in some situations. Whether you are a developer writing compiled binary cmdlets or an IT Pro writing functions, answer is Modules.  You can read all about them in the help documents. Just run

PS > Help about_module

 

The beauty of Modules in PowerShell is that they allow you to easily distribute and deploy your code or cmdlets to others using nothing but copy and paste.  Let’s say you have a module with a a lot of functions to Get, Set, and Remove Network Settings, and you named this module Network. All you need to do is create a folder called “Network” and put your module files into that folder.

There are 2 default locations for Modules. There is one at the system level and also one for the current user, similar to how profiles work. The System Modules directory is

%windir%\System32\WindowsPowerShell\v1.0\Modules

and the one for the current user can be found at

%UserProfile%\Documents\WindowsPowerShell\Modules 

There are three basic types of modules; Script, Manifest, and Binary. Let’s look at each one, as they tend to build on on another.

Script Modules

Script modules are really nothing more than a .PS1 file renamed to .PSM1. For example, if you have a script that has a list of functions you use everyday called myfunctions.ps1, you could turn it into a module by renaming the script to myfunctions.psm1. Then, instead of dot sourcing your script, you could just use Import-Module to bring all those functions into your PowerShell session.

Manifest Modules

Manifests can be used to add a bunch of useful information for code authors and users. A manifest is a separate file that you can include with your PSM1 file or your compiled Module, which is just a DLL. The manifest file is just a a PowerShell HashTable. You can use a cmdlet called New-ModuleManifest to create one with some very basic information. Manifests are really nice for adding version information and prerequisites for your module. If you create a folder called  c:\windows\sytem32\windowspowershell\v1.0\modules\myModule and drop in a PSM1 file and a PSD1 file, PowerShell will load the manifest.  You just need to put in the ModuleToProcess field to add your PSM1 or DLL.

#
# Module manifest for module 'demo'
#
# Generated by: Andy Schneider
#
# Generated on: 4/4/2011
#

@{

# Script module or binary module file associated with this manifest
ModuleToProcess = ''

# Version number of this module.
ModuleVersion = '1.0'

# ID used to uniquely identify this module
GUID = '8e420ad8-c7d7-4139-8d2e-02d4e31416a9'

# Author of this module
Author = 'Andy Schneider'

# Company or vendor of this module
CompanyName = 'get-powershell'

# Copyright statement for this module
Copyright = '2011 - Use at your own discretion - if it kills your cat - not my fault'

# Description of the functionality provided by this module
Description = 'To demo a module manifest'

# Minimum version of the Windows PowerShell engine required by this module
PowerShellVersion = ''

# Name of the Windows PowerShell host required by this module
PowerShellHostName = ''

# Minimum version of the Windows PowerShell host required by this module
PowerShellHostVersion = ''

# Minimum version of the .NET Framework required by this module
DotNetFrameworkVersion = ''

# Minimum version of the common language runtime (CLR) required by this module
CLRVersion = ''

# Processor architecture (None, X86, Amd64, IA64) required by this module
ProcessorArchitecture = ''

# Modules that must be imported into the global environment prior to importing this module
RequiredModules = @()

# Assemblies that must be loaded prior to importing this module
RequiredAssemblies = @()

# Script files (.ps1) that are run in the caller's environment prior to importing this module
ScriptsToProcess = @()

# Type files (.ps1xml) to be loaded when importing this module
TypesToProcess = @()

# Format files (.ps1xml) to be loaded when importing this module
FormatsToProcess = @()

# Modules to import as nested modules of the module specified in ModuleToProcess
NestedModules = @()

# Functions to export from this module
FunctionsToExport = '*'

# Cmdlets to export from this module
CmdletsToExport = '*'

# Variables to export from this module
VariablesToExport = '*'

# Aliases to export from this module
AliasesToExport = '*'

# List of all modules packaged with this module
ModuleList = @()

# List of all files packaged with this module
FileList = @()

# Private data to pass to the module specified in ModuleToProcess
PrivateData = ''

}
 

Binary Modules

If you are a developer or an IT Pro that loves to code, you might want to create a compiled module. This is a module that contains Cmdlets and or Providers that are compiled, and are typically written in C# or VB.NET. A binary module is actually a DLL file. You can read all about creating a compiled cmdlets here on MSDN. Just like a PSM1 module, you can create a module manifest and add the DLL into ModulesToProcess in your manifest.

Using Modules

There are several cmdlets that allow you to interact with Modules

image

What most of these do should be pretty obvious from their names. One nifty trick is the –listAvailable switch on get-module. this will list all the modules that are available on your system, so you know which ones you can import. You can even filter this based on Module type.

image

Posted in: Package | Distribute Code | Modules

Tags: