Do helper functions in a NuGet Packages init.ps1 have to be global?

Mar 23, 2011 at 5:54 PM

This is a straight copy and paste from my StackOverflow question (

I'm wanting to write a couple commands for the NuGet package manager console to insert Gists from GitHub. I have 4 basic commands

  • List-Gists 'user'
  • Gist-Info 'gistId'
  • Gist-Contents 'gistId' 'fileName'
  • Gist-Insert 'gistId' 'fileName'

All of my commands depend on a couple utility functions, and I'm struggling with whether they need to be global or not.

# Json Parser
function parseJson([string]$json, [bool]$throwError = $true) {    
    try {
        $result = $serializer.DeserializeObject( $json );    
        return $result;
    } catch {                
        if($throwError) { throw "ERROR: Parsing Error"}
        else { return $null }            

function downloadString([string]$stringUrl) {
    try {        
        return $webClient.DownloadString($stringUrl)
    } catch {         
        throw "ERROR: Problem downloading from $stringUrl"

function parseUrl([string]$url) {
    return parseJson(downloadString($url));

Can I just have these utility functions outside of my global functions, or will I need to include them in each of the global functions definition scope somehow?



Mar 24, 2011 at 2:45 AM

The best way to do this is to write a powershell module (psm1 file) and import it in your init.ps1. You can selectively export members from the script that way.

Mar 24, 2011 at 2:51 AM

Does that somehow limit my helper functions to just my packages scope?  For example, would anyone be able to use my downloadString(...) function if it's in a .psm1 file?  I'm worried about possible having multiple downloadString(...) methods overwriting or throwing errors on declaration eventually.

Mar 24, 2011 at 3:49 AM

Yes, it keeps them private. We're going to start a best practice page on how to add methods to the console. Everyone doing this should be using modules.

Mar 24, 2011 at 3:57 AM
Edited Mar 24, 2011 at 3:58 AM

dfowler is correct - you need to create a PSM1 file. It's as easy as just renaming your ps1 file to psm1. Then, from your init.ps1 file, run:  import-module <path_to_my.psm1>. I would suggest you use powershell-conformant verbs for your functions though. "Gist" is not an approved verb. At this point you're probably asking "verbs? approved? whut?" -- take a look at this list: The whole point of using standardized verbs is so that the longer you use powershell, the easier you will find it to discover the right commands. I don't really know what your functions are meant to do, but I can guess. This is how I would suggest you name them :

get-gist <-user | -gistid> # get info on a gist by user or gist id. use parametersets to offer alternate invocation
import-gist  # read from github into local file or the console; if -file is not specified, output to console; accept pipeline input from get-gist for context gist(s)
export-gist  # send to github from local file, or from pipeline input (possibly from cat/get-content)

Btw, It doesn't really matter about your helper functions. If they cannot be used by external callers (private to module,) then "parseUrl" etc is fine.
To limit which functions are available outside of the module, use the Export-ModuleMember cmdlet at the foot of your psm1 file with the -Function parameter. Your parse helper functions will be callable from the exported functions, but not directly from the console.

I'll be putting together a wiki/docs page on this site soon with some more guidelines.

Microsoft PowerShell MVP
2008 - 2011

Mar 24, 2011 at 4:00 AM

Oisin knows what he’s talking about. We were lax with our “verbs” but he whipped us into shape too. J

Mar 24, 2011 at 2:16 PM

Thanks for the great info.

I was feeling antsy last night so I put together what I had into an initial version of the package; I'll have to re-write with your suggestions this weekend.

It's called Gist4u2, and I wrote a short blog post about how I use it.


Mar 24, 2011 at 3:22 PM

Good stuff. If you need a hand fixing up the parameters and parametersets to get pipeline binding working, let me know.