2 minute read

TL;DR - PowerShell needs centralized package management. Please go up-vote this request to have it added to PowerShell.


I love PowerShell, and I love writing reusable PowerShell modules. They work great when I am writing scripts for myself. The problem comes in when I write a script that depends on some modules, and I then want to share that script with others. I basically have 2 options:

  1. Track down all of the module files that the script depends on, zip them all up, and send them to the recipient along with instructions such as, “Navigate to this folder on your PC, create a new folder with this name, copy file X to this location, rinse, repeat…”.
  2. Track down all of the module files that the script depends on and copy-paste their contents directly into the top of the script file, so I just send the user one very large file.

Neither of these solutions are ideal. Maybe I’m missing something? In my opinion, PowerShell really needs centralized package management; something similar to Ruby Gems would be great. Basically a website where users can upload their scripts with a unique ID, and then in their PowerShell script at the top of the file just list the modules that the script depends on. If the modules are not installed on that PC yet, then they would automatically be downloaded and installed. This would make PowerShell so much more convenient, and I believe it would help drive more users to write reusable modules and avoid duplicating modules that have already been written (likely better) by others.

In order for this to work though, it has to be baked directly into the PowerShell architecture by the PowerShell team; it’s not something that a 3rd party could do. So to try and bring this feature request to Microsoft’s attention, I have create a Suggestion on the MS Connect site. Please go up-vote it.

Before thinking to create a feature request for this (duh), I spammed some of my favourite PowerShell Twitter accounts (@JamesBru @ShayLevy @dfinke @PowerShellMag @StevenMurawski @JeffHicks @ScriptingGuys) to bring it to their attention and get their thoughts; sorry about that guys! This blog’s comments are a better forum than Twitter for discussing these types of things.

If you have thoughts on centralized package management for PowerShell, or have a better solution for dealing with distributing scripts that depend on modules, please leave a comment below. Thanks.

Happy coding!

Update

While PowerShell does not provide a native module management solution, Joel “Jaykul” Bennett has written one and all of the modules are hosted at http://poshcode.org/, although I believe it can download modules from other sources as well (e.g. GitHub or any other URL). One place that it cannot download files from is CodePlex since CodePlex does not provide direct download links to the latest versions of files or to their download links (it is done through Javascript). Please go up-vote this issue and this issue to try and get this restriction removed.

Update 2

PowerShell does not provide a native module management solution using the PowerShellGet module with modules hosted on the PowerShell Gallery :-)

Comments

Zach Bonham

Just some thoughts on the subject. This comes up every so often with teams that I’ve worked with that write PowerShell. How to share code? Most don’t. Or copy pasta like you describe.

A few of us have tried sharing code using ‘dot’ sourced libraries. This allowed us to get latest of a project in version control, and either branch or copy into our ‘project’. PowerShell modules seemed to require too much overhead for what we were trying to accomplish. Plus, I don’t think any of us really understood, in a typical enterprise, why we’d want to bother? We seemed to strike the right balance thru dot sourcing.

We typically followed the convention of having a top level [lib].ps1, which just

.\yourlib.ps1 .\supportingfiles.ps1 .\modules\shared(s).ps1

Ideally, we would have liked to been able to do:

ps-get ‘sqlclient’

and have our sql client data access module dropped into the current folder.

.\mylib.ps1 .\modules\sqlclient.ps1

Though, we’d probably want to have a manifest (gemfile) which contained the versions we depended on, etc. - this could be where PowerShell modules would come into play? We handled versions through source control.

I’d be curious to see if the problem could be solved using an format (nuget/chocolatey) rather than spinning off a new one or waiting for OEM solution - though I’ll be the first to admit that I’m not exactly thrilled with general purpose package manager options on Windows.

deadlydog

@Zach Bonham Thanks for sharing your thoughts Zach. In terms of Dot Sourcing vs Modules, http://stackoverflow.com/questions/14882332/powershell-import-module-vs-dot-sourcing has some great information. Basically the big differences that I see are:

  1. Modules can have “private” functions; that is you can explicitly control what variables and functions you want to expose to users of the module. This is great when creating a library, as you likely want to have some private functions for internal use that aren’t meant to be called directly by users of the library. This may not be a problem for you when only distributing scripts to your own small team, but quickly becomes a problem when creating general purpose modules meant to be used by anybody/everybody.

  2. Dot sourcing can actually run a script, whereas modules are purely for importing functions that your script is meant to explicitly call. I often think of dot sourcing like an “include” in php; that is, it is pretty much copy/pasting to dot sourced code into your script, so any code that is not encapsulated in a function will be ran; so dot sourced scripts can actually be used to do some work. Modules on the other hand are more like a “using” statement in C#, in that they just import a collection of functions that you can call; the Import-Module statement doesn’t do anything on its own.

  3. Modules are namespaced, ensuring conflicts don’t occur when importing many modules; if 2 scripts that you dot source have the same function name, they will conflict.

  4. As of PowerShell v3, you don’t have to use Import-Module anymore; as long as the module is placed in a file in your $env:PSModulePath it can find it automatically. This applies to intellisense too, which can be a great feature. With dot sourcing, you actually have to run the dot source line once to import it into your session before you can take advantage of intellisense.

So dot sourcing and modules are similar, but serve two different purposes.

As for using NuGet or Chocolatey, this is definitely an option for packaging and distributing your module and it’s dependencies to make it easier for the recipients, but there is still work on the end users part to find the package, download it, and install it properly to the proper location. With full native integration, it would be possible to just add one line to your script, such as “Get-DependencyModule SomeModuleID-Version”, to have it automatically do all of this work for you and the end user. Essentially I could email my script to someone and they just double-click it to run it and everything just works (perhaps they would get a prompt where they have to confirm downloading the module or something).

Great questions. Thanks for sharing your thoughts!

Leave a Comment

Your email address will not be published. Required fields are marked *

Loading...