How to Create a PowerShell Module

In the last part of this series I demonstrated how to add custom formatting to your PowerShell scripts and functions. This requires an additional format.ps1xml file, which you have to add to your PowerShell session using Update-FormatData. The challenge is that when you share your script with someone, you need to include the ps1xml file and make sure that it gets loaded. Instead of doing this manually, it makes more sense to package everything as a PowerShell module. A module is a collection of one or more PowerShell files with at least one file with a psm1 file extension. More on that in a moment.

PowerShell looks for modules in directories that are part of the %PSModulePath% environmental variable. The two primary locations are under %UserProfile%\Documents\WindowsPowerShell\Modules and C:\Windows\System32\WindowsPowerShell\v1.0\Modules. The folder under your user profile does not exist by default, and you may have to create it. If you look at %PSModulePath%, you may also see other locations depending on other installed products. You can also modify the path yourself.

Packaging a PowerShell System Uptime Clock as a PowerShell Module

Starting with PowerShell 3.0, you can run any command from a module without having to first import it. PowerShell will search the module directories. If your module is in another directory, you will have to manually import it by first specifying the path.

I’m going to take what I had from my last article and create a module. First I need to create the necessary folder.

One very important note: the name of the module folder must be the same as the module file. In my case I will be creating a file called MyUptime.psm1 and putting it in this directory. I’ll also copy my ps1xml file to the module directory

You can also move it if you prefer. To create the module file, at a minimum all you need to do is save the script file with your functions as a psm1 file, remembering that the name needs to be the same as the directory. But, you can do much more. Here’s my version of MyUptime.psm1

In many ways this is no different than any other script file. For the sake of demonstration, I moved my private IsWsmanAvailable function out of the Get-MyUptime function. This makes it easier to revise either function. You’ll also notice toward the end that I’m defining an alias for my command.

The last step is to tell PowerShell what I want exposed from my module. In my case I want to make sure users see my alias and primary function.

My private function is still available to Get-MyUptime, but it isn’t visible to the user in PowerShell. I could stop there if I didn’t have any custom type or format extensions. All I need to do is run the command in PowerShell.

Running get-myuptime in Windows PowerShell. (Image Credit: Jeff Hicks)
Running get-myuptime in Windows PowerShell. (Image Credit: Jeff Hicks)


However, I don’t have my custom formatting. So I need to take the next step and create a module manifest. A manifest gives you granular control over how a module is used. The manifest file has a psd1 file extension and will have the same name as the folder and your psm1 file. This means I will be creating MyUptime.psd1.

The manifest follows a specific format and once you have one you can copy and paste to create new ones. But I’ll use the New-ModuleManifest cmdlet to generate it. The cmdlet has many parameters to correspond to the different settings in the manifest. I’ll need to define a path for the new file.

Every module has a unique GUID. For a new module, I’ll need a new GUID. This is the easy way to create one:

You only create the manifest once. I’ve put the parameters in a hashtable to splat against New-ModuleManifest to make it easier to read.

Each key in the hashtable is the same as a parameter in New-ModuleManifest. Most of the values should be self-explanatory. Be sure to specify your psm1 file as the root module. I’m also specifying that I want to load my custom format file. My module doesn’t have any cmdlets or variables so I’m explicitly setting those values to be empty. Here’s the finished manifest.

Now look what happens when I start using the commands:

To review, my module directory has the same name as my module file and manifest.

The module directory has the same name as the module file and manifest. (Image Credit: Jeff Hicks)
The module directory has the same name as the module file and manifest. (Image Credit: Jeff Hicks)


Modules can be quite complex and consist of many files. All I have done in our journey is to move from simple commands to a re-usable tool that you can share with others. Not everything has to be written in PowerShell as a module or even as an advanced function. You could have stopped anywhere along our journey. But I wanted you to know where you could go when you are ready to venture out on your own journey.

Related Topics:

  • PowerShell

    Don't have a login but want to join the conversation? Sign up for a Petri Account