PowerShell Modules

In this episode of the Learn PowerShell series we’ll examine PowerShell Modules. In previous episodes we covered PowerShell scripts and PowerShell Functions where we began to create solutions and solve problems using PowerShell. Many folks spend time at the scripts and functions stage as they experiment and get better with PowerShell. As you continue your PowerShell journey you may eventually find that others want to use what you create! To effectively share your code with others, you’ll want to look to creating PowerShell modules!

A PowerShell module is simply a psm1 file that contains PowerShell logic. You can take a PowerShell script .ps1 and save it as a .psm1 file. This offers several advantages including:

  • Code can now be import using Import-Module
  • There is now control over what functions are import (public vs private functions)
  • Scope of variables controls

When combined with a .psd1 file you can take even further control of your module by providing additional metadata about the module project. A manifest also enables you to publish your module to the PowerShell Gallery for the entire world to use! This enables easy access your module with simple cmdlets like Install-Module.

Video

If you prefer video format over written documentation, I discuss this topic in the following TechThoughts video:

What is a PowerShell Module?

A PowerShell Module is structured PowerShell code that you can reuse. You may want to reuse the code for your own projects, or make your solution available to others. You can share scripts, but they lack the capabilities that modules offer. For example, you can version control a PowerShell module. This gives users the ability to ensure they are using code with the latest features and bug fixes. Modules can also be hosted on internal repositories or on the PowerShell Gallery for easy access and installation.

PowerShell Module Components

PowerShell Module File

A PowerShell Module consists of a few basic components with the primary being the PowerShell module file. This is represented with a .psm1 extension. The psm1 is essentially a script that contains the functions and core logic of your module. This module file is the minimum requirement for a working PowerShell module.

Lets say we have a script, learnpowershell.ps1 which contains the function Get-LearnPowerShellInfo. You could simply save the ps1 script as a psm1. This converts the script to a module, giving you the ability to import it as shown below:

# a psm1 module can now be imported
Import-Module .\learnpowershell.psm1

# we can confirm that the module is loaded
Get-Module learnpowershell

ModuleType Version    PreRelease Name                 ExportedCommands
---------- -------    ---------- ----                 ----------------
Script     0.0                   learnpowershell     Get-LearnPowerShellInfo

# now that the module is imported we can see what commands are available
Get-Command -Module learnpowershell

CommandType     Name                                  Version    Source
-----------     ----                                  -------    ------
Function        Get-LearnPowerShellInfo               0.0        learnpowershell

While this works, it lacks certain capabilities. For example, note that the module has a version of 0.0. This is because the module file itself does not have the ability to provide details such as the module version.

PowerShell Module Manifest

While it is technically possible to only use the PowerShell module file, most modules also include a module manifest. A module manifest is a file that contains a hash table of keys and values. These keys and values make up the metadata of your PowerShell module. This metadata provides a lot of detail about your module. It also enables you to take additional control over your module’s behavior.

The manifest contains many elements. For a full list visit check out How to write a PowerShell module manifest. You can also view a sample module manifest. Here are a few common elements that module authors typically leverage:

  • RootModule – the .psm1 that will be import by the manifest
  • ModuleVersion – version number of the module
  • GUID – unique identifier of the module for publication
  • Author – Author of the module
  • Description – functionality that the module provides
  • PowerShellVersion – minimum version of PowerShell that the module supports
  • RequiredModules – other modules that this module depends on
  • FunctionsToExport – your logic may contain many supporting functions in addition to public functions you want your users to use. You can surface just the public functions to your users here.
Creating a PowerShell Module Manifest

You can create a module manifest with a simple PowerShell command:

# create a basic module manifest
New-ModuleManifest -Path C:\learnpowershell\learnpowershell.psd1

Open the manifest in your editor of choice and fill out the various elements. Once editing is complete, test the validity of the manifest edits by running:

# test a module manifest
Test-ModuleManifest .\learnpowershell.psd1

ModuleType Version    PreRelease Name                    ExportedCommands
---------- -------    ---------- ----                    ---------------
Manifest   0.0.1                 learnpowershell

If you receive no errors the manifest passed validity check. You should now have two files:

  1. learnpowershell.psd1 – the PowerShell Module Manifest containing meta data about the module
  2. learnpowershell.psm1 – PowerShell Module file containing functions and logic
ls
Directory: c:\learnpowershell

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---            05/30/21    21:50           4156 learnpowershell.psd1
-a---            05/30/21    18:38           9183 learnpowershell.psm1

With the psd1 in the mix you no longer import the psm1 directly. Import the manifest instead. Remember, the manifest specifies the root module that will be imported.

# import a module by specifying the manifest
Import-Module .\learnpowershell.psd1

# we can confirm that the module is loaded
Get-Module learnpowershell

ModuleType Version    PreRelease Name                   ExportedCommands
---------- -------    ---------- ----                   ----------------
Manifest   0.0.1                 learnpowershell

Installing PowerShell Modules

Install Module from Repository

Using standard cmdlets like Find-Module and Install-Module you can install modules from a repository. The PowerShell Gallery is the most popular public repository and is registered by default.

# the PowerShell Gallery is registered by default
Get-PSRepository

Name                      InstallationPolicy   SourceLocation
----                      ------------------   --------------
PSGallery                 Trusted              https://www.powershellgallery.com/api/v2

# search for modules that are tagged with the Telegram key word
Find-Module -Tag Telegram | Format-List

Name                       : PoshGram
Version                    : 1.16.0
Type                       : Module
Description                : PoshGram provides functionality to send various message types to a
                             specified Telegram chat via the Telegram Bot API.

# install a module from the PowerShell Gallery
Install-Module -Name PoshGram -Scope CurrentUser

It is possible to register additional repositories using the Register-PSRepository cmdlet. Many organizations elect to host their own company-specific modules in an internal repository.

Install Module Manually

You can also install PowerShell modules manually. The psd1 and psm1 simply need to be placed in a folder in the $env:PSModulePath. These directory paths differ depending on PowerShell version, operating system type, and scope. For instance, if you are installing a module for all users in PowerShell 7 on Windows it would be installed into the C:\Program Files\PowerShell\Modules location. If you installed just for your user it would be placed in $env:USERPROFILE\Documents\PowerShell\Modules. Reference a list of installation locations:

  • PowerShell
    • Windows
      • $env:USERPROFILE\Documents\PowerShell\Modules
      • C:\Program Files\PowerShell\Modules
    • Linux
      • /home/user/.local/share/powershell/Modules
      • /usr/local/share/powershell/Modules
  • Windows PowerShell
    • C:\Program Files\WindowsPowerShell\Modules
    • C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules

Once you’ve selected an installation destination, create a folder name that is the same name as the module itself. Then copy the psd1 and psm1 files into that directory. You can now import the module without specifying a direct path.

# change dir to the modules install folder
cd $env:USERPROFILE\Documents\PowerShell\Modules

# create a new folder that is the same name as your module
New-Item -Name learnpowershell -ItemType Directory

# copy the psd1 and psm1 files to this new directory

# verify that PowerShell can now source that module
Get-Module learnpowershell -ListAvailable

Directory: C:\Users\user\Documents\PowerShell\Modules

ModuleType Version    PreRelease Name                                PSEdition ExportedCommands
---------- -------    ---------- ----                                --------- ----------------
Manifest   0.0.1                 learnpowershell                     Desk

Evaluating a PowerShell Module

You can test and evaluate any module you find without directly installing it. Using the Save-Module cmdlet you can download a module from a repository to a directory of your choosing. From there you can import it manually for testing and evaluation.

# save a module to a directory of your choice
Save-Module PoshGram -Path C:\eval -Repository PSGallery

# change directory to the downloaded module
cd C:\eval\PoshGram\1.16.0

# import the module directly for testing and evaluation
Import-Module .\PoshGram.psd1

Publishing PowerShell Modules to the PowerShell Gallery

As a first step, you’ll need to register an account on the PowerShell Gallery website. This is a simple process, especially if you already have a Microsoft account.

Armed with a login, you’ll be able to click on your username which will take you to the page that contains your API key.  This API key is required to Publish scripts or modules to the PowerShell Gallery. Once you have your API key you’re ready to get your script or module published.

Publishing modules is relatively straightforward. The module needs to be installed on the current machine you wish to publish from. This is because Publish-Module has to be able to locate the module. If you are creating a module locally, simply install it manually as shown above.

# publish your module to the PowerShell Gallery
Publish-Module -Name "learnpowershell" -NuGetApiKey "your-api-key-goes-here" -Repository PSGallery

Don’t forget to also check out the PowerShellGallery Publishing Guidelines and Best Practices!

PowerShell Module Example

There are thousands of modules on the Gallery. Most of them add real world functionality to your PowerShell install! For the purposes of this episode, I created a basic PowerShell module, LearnPowerShell. Here are a couple of tasks that you can complete to get hands on with an actual PowerShell module:

  1. Search for the module (LearnPowerShell) on the PowerShell Gallery
  2. Install the module on your device automatically or manually
  3. Locate the module on your device and find the psd1 and psm1 files
  4. Explore the psm1 file and what it contains
  5. Explore the psd1 file. What metadata does it have about the module?

Advanced PowerShell Module Building

At this point we’ve established that all that is needed for a working PowerShell module is the .psm1, likely paired with a .psd1. But, when looking at some open source PowerShell module projects like PoshGram, (and many others) you will find a great deal many more files and folders in these projects.

Many module authors integrate CI/CD practices into their module development efforts. They leverage automated tests, check for proper formatting, generate help, and combine functions together to build the project for publication.

Despite this added complexity you’ll find that each project still tracks towards creating a .psm1 and .psd1 as the final product. This is then published for others to use. We will cover advanced PowerShell module building techniques in a later lesson.

Additional Reading

Series Navigation<< Manage Cloud with PowerShell

Leave a Reply

Your email address will not be published.