it:ad:powershell:howto:create_a_powershell_module

IT:AD:Powershell:HowTo:Create a Powershell Module

Summary

Whereas *.ps1 scripts are cheaky little useful scripts that get things done, Modules are the modular building blocks of a maintainable and reusable strategy.

Essentially, a module is just a new namespace. Any data member or function that you declare inside of the module will be accessible by other module members. But, it’s out of scope for your interactive session. So, you just have to export the members that you’d like to be publicly accessible. (Basically just like Python’s import statement.)

There is some set up cost though.

The process of creating powershell modules approximately is * converting the extension from *.ps1 to *.psm1, * adding to the bottom of the script a declaration of what methods in the script you are exposing as callable. * installing in a WellKnown/ Modules directory. * debugging is a little harder due to a feature of *.psm1 files in that reloading doesn't refresh the script – you have to unload/reload before you see the changes applied…a bit annoying. * It's optional to add a description of the script's functionality as a *.psd1 in the same directory as the *.psm1

Modules are controlled by the same security as Scripts.

So if you haven't already

Set-ExecutionPolicy Unrestricted

  • Create a *.psm1 rather than a *.ps1 file.
    • Unfortunately, stops being easily editable/refreshable in PS ISE (have to Unload/Reload everytime – see below).

You'll have to be stricter with the way you name files.

But once addressed, complete the file, with the following exporting of methods as the last lines of the file.

export-modulemember -function Show-Calendar

until you do, consider turning off import warnings: import-module <path-to-module> -DisableNameChecking

Modules are saved in a folder under one of the “Powershell Module Root Paths”. By default there are 2 – one per User, one System wide one.

You can get your current “Powershell Module Root Paths” as follows:

# works much the same as the PATH Environment Variable:
$env:PSModulePath

The default will be something like:

WindowsPowerShell\Modules;C:\windows\system32\WindowsPowerShell\v1.0\Modules\

In other words:

  • C:\windows\system32\WindowsPowerShell\v1.0\Modules\
  • %userprofile%\documents\windowspowershell\modules\mymodule
    • Note that at MOE, the default path is a sibling, not child of the Document folder:
      • %userprofile%\windowspowershell\modules\mymodule


* WRONG:`%userprofile%\documents\windowspowershell\modules\mymodule`
* CORRECT: `%userprofile%\windowspowershell\modules\mymodule`
* `windows\system32\windowspowershell\V1.0\modules\mymodule`

You are not limited to use only those paths… You can update your environment as follows:

In those root dirs, you create a folder with the same name (eg: “xact”) as the Module filename (eg: “xact”)

In that folder you place your xact.psm1 file, that is export-modulemember methods from it.

/{root}/
/{root}/xact/
/{root}/xact/xact.psm1

Whereas Scripts one just loads with 'dot' loading, *.psm1 files have to be loaded/unloaded.

# all following forms are valid:
import-module {path-needed-if-not-module-root}/untitled1.psm1
import-module untitled1.ps1
import-module untitled1
import-module <path-to-module> -DisableNameChecking   #if you want it to shut up about not adhering to Get-Verb

It's easy.

But there's a catch … if you load A, which imports B and C, and B imports C as well, then the file is only loaded once. Makes sense. But it makes debugging harder than with *ps.1 files which you can just reload/refresh after every edit.

You have to unload files before you can reload them.

remove-module untitled1

If we're talking about *.ps1 script functions, one can document them by putting extended comments at the bottom of the function.

Something like:

 <#
	.SYNOPSIS
	--TODO:Summary

	.DESCRIPTION
	--TODO:Describe

	.PARAMETER --TODO:ParamName--
	--TODO: Describe 


	.EXAMPLE

	.LINK
	http://skysigal.com

	.NOTES
#>    

Then you can

get-help myFunc

Alternatively, for modules, consider:

 New-ModuleManifest 

See: https://www.simple-talk.com/sysadmin/powershell/an-introduction-to-powershell-modules/

By default Scripts are not loaded.

You have to import-module... them into the IDE.

But Powershell looks for file in its $profile variable (it's going to be %userprofile\$profile – which ends up being

# per user
$useprofile\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1.

# All users (notice different filename)
C:\Windows\System32\WindowsPowerShell\V1.0\Microsoft.PowerShell_profile.ps1

It's just the first script that's run when the IDE is loaded.

So you can just create the file, and add

import-module mytest

get-command -type cmdlet *-*module* | select name

  • Get-Module pattern
    • Gets a list of the modules currently loaded in memory.
  • Import-Module
    • Loads a module into memory and imports the public commands from that module.
  • Remove-Module
    • Removes a module from memory and removes the imported members.
  • Export-ModuleMember
    • Used to specify the members of a module to export to the user of the module.
  • New-ModuleManifest
    • Used to create a new metadata file for a module directory.
  • Test-ModuleManifest
    • Run a series of tests on a module manifest validating its contents.
  • New-Module
    • Create a new dynamic module.
  • /home/skysigal/public_html/data/pages/it/ad/powershell/howto/create_a_powershell_module.txt
  • Last modified: 2023/11/04 01:54
  • by 127.0.0.1