Geeks With Blogs
Alex Hildyard
Creating Powershell modules isn't hard, but the task has many nuances, and it can be difficult deciding what information is relevant. My own objective was very simple, and I suspect it's the most common scenario of all. I had a directory of .ps1 scripts, and I simply wanted to turn them into a module, so that I could write something like "Import-Module MyModule", and immediately have access to all the functions I had defined.

To do this, here's the most basic set of tasks you need to perform (and then I'll give you a script to do all this automatically):

1. Create the module folder within your $PSModulePath. If you have a locked down box then you may want to install modules into your local profile rather than system wide, but I've assumed you want to install to one of the default system locations

2. Create a .psd1 manifest within this folder, giving it the same name as your module. You can do this by hand, but it makes more sense to call the New-ModuleManifest cmdlet

3. Add the names of the files containing functions you want exported to the "NestedModules" attribute within your manifest

4. Copy across the files you want in your module, renaming ".ps1" files to ".psm1"

The script below does all this, and also includes support for module versioning. When you have multiple versions of the same module available, Powershell will resolve calls to the latest version. To use it, just point it at a directory of script file, make up a name for your module, and hit return. Once the module's been created, it'll be loaded automatically into memory, and any previous versions flushed out. You can check the methods exported from your module with (Get-Module someModule).ExportedCommands

Finally, perhaps the first thing you'll want to package is ... the Package-Module file itself! That way, the method will always be in scope when you need to create modules of your own. Enjoy!


<#
.SYNOPSIS
Creates a Powershell module and accompanying manifest from a set of script and/or module files

.DESCRIPTION
Creates a Powershell module and accompanying manifest from a set of script and/or module files.

.PARAMETER Path
The path either to the script file or directory of files (.ps1, .psm1) from which the module should be created

.PARAMETER ModuleName
The name of the module. If the module already exists

.PARAMETER ModuleVersion
The version of the module. If unspecified, defaults to 1.0.0.0

.EXAMPLE
Package-Module -Path "C:\temp\ProjectResources" -ModuleName "MyModule" -ModuleVersion "1.0.0.0"

.NOTES
    Author:   Alex Hildyard
    Date:     7th September 2016
    Profile:  https://uk.linkedin.com/in/alexhildyard
    Blog:     http://geekswithblogs/alexhildyard

.LINK
http://geekswithblogs/alexhildyard
#>
function Package-Module
{
    Param(
        [Parameter(Mandatory=$True, HelpMessage="Specify the path to a .ps1 or .psm1 file or directory of .ps1 or .psm1 files")]
        [string]$Path,
        
        [Parameter(Mandatory=$True, HelpMessage="Specify the module name to create or update")]
        [string]$ModuleName,

        [Parameter(Mandatory=$False, HelpMessage="Specify the module version (default is 1.0.0.0)")]
        [string]$ModuleVersion="1.0.0.0"
    )

    # Confirm path is valid
    if (!(Test-Path $Path))
    {
        Write-Error "Invalid path: $Path"
    }    
    else
    {
        # Create versioned module directory, if not yet present
        $modulePath = "$env:ProgramFiles\WindowsPowershell\Modules\$ModuleName\$ModuleVersion"

        # Drop the module directory if it already exists, to remove any stale files
        If ((Test-Path $modulePath))
        {
            Write-Information "Removing module directory: $modulePath"
            Remove-Item $modulePath -Recurse -Force
        }

        # Recreate the module directory
        Write-Information "Creating module directory: $modulePath" 
        New-Item -Path $modulePath -ItemType Directory
        
        # Gather together a set of script and module files to turn 
        # into a single module
        $modules = @()

        gci -Path $Path -Include *.psm1, *.ps1 -Recurse |% `
        {
            $module = $_.BaseName
            $modules += $module
            
            Write-Information "Uploading module: $module"
            
            # Call the new file .psm1, even if it was previously a .ps1
            Copy-Item $_.FullName "$modulePath\$module.psm1" -Force
        }


        # Now we have all the information we need to create the manifest
        Write-Information "Creating manifest"
        New-ModuleManifest -Path "$modulePath\$ModuleName.psd1"

        
        $manifest = Get-Content "$modulePath\$ModuleName.psd1"

        # Generate the NestedModules attribute
        $nestedModules = "NestedModules = @("
        $nestedModules += $modules |% { "`"$_`";" }
        $nestedModules += ")"

        # Fix up the manifest file, replacing the "commented out" 
        # NestedModules with our custom list;
        # also update the version if specified
        $lines = @()

        ($manifest -split "`n") |% `
        { 
            $line = $_.ToString()
            
            if ($line.Contains("NestedModules"))
            {
                $lines += $nestedModules
            }
            elseif ($line.Contains("ModuleVersion"))
            {
                $lines += "ModuleVersion = '$ModuleVersion'"
            }
            else
            {
                $lines += $line
            }
        }

        # Write out the updated manifest
        Set-Content "$modulePath\$ModuleName.psd1" $lines

        # Unload the module if it's already loaded
        if ((Get-Module -Name $ModuleName) -ne $null)
        {
            Write-Information "Unloading module: $ModuleName"
            Remove-Module $ModuleName
        }

        # And finally (re)import the module into our namespace
        Write-Information "Importing module: $ModuleName"
        Import-Module $ModuleName
    }
}

Posted on Wednesday, September 7, 2016 2:44 PM Powershell | Back to top


Comments on this post: Creating Powershell Modules the Easy Way!

# re: Creating Powershell Modules the Easy Way!
Requesting Gravatar...
Excellent work, everything is very clearly narrated and a special thank you for such a convenient text format
food near me
Left by maodzedun on Jul 28, 2017 11:37 AM

Your comment:
 (will show your gravatar)


Copyright © Alex Hildyard | Powered by: GeeksWithBlogs.net