How to install a new "local" module (with a manifest) to local host

I have built a powershell module and wish to install it locally. Once I have it fully tested, I intend to publish it to a public repository, but for now, I need to install/test locally first.

Briefy, I have constructed a module, copied it over to an install location and tried to install it using install-module, but it continuously fails with the message: ‘No match was found for the specified search criteria and module name …’.

I should also say I’m using PowerShell version 7.0, on macOS, and this is the first time I’m working with modules, even though I’ve written plenty of scripts in the past.

So, my module name is ‘XLDPlusPlus’ which consists of the main entry script: xld-converter.ps1, which depends on a further 4 ps1 scripts. Up to now, I have dot sourced the other scripts and that has been fine.

Some details:

  1. $env:PSModulePath: '/Users/Plastikfan/.local/share/powershell/Modules:/usr/local/share/powershell/Modules:/usr/local/microsoft/powershell/7/Modules'
  2. Module path: '/Users/Plastikfan/.local/share/powershell/Modules/XLDPlusPlus'
  3. Module file: '/Users/Plastikfan/.local/share/powershell/Modules/XLDPlusPlus/XLDPlusPlus.psm1'
  4. Module manifest file: '/Users/Plastikfan/.local/share/powershell/Modules/XLDPlusPlus/XLDPlusPlus.psd1'
Referring to this guide How to write a PowerShell module manifest I used the New-ModuleManifest command. I can list available modules as follows (extraneous output removed for clarity):

$ Get-Module -List

ModuleType Version PreRelease Name PSEdition ExportedCommands
---------- ------- ---------- ---- --------- ----------------
Script 0.0.1 XLDPlusPlus Desk {Convert-Audio, cvaudio}

As you can see, XLDPlusPlus is the module name and from the manifest I have exported 2 items, the command ‘Convert-Audio’ and an alias ‘cvaudio’. So the user can use the command by its name Convert-Audio or its alias cvaudio.

In the manifest:

FunctionsToExport = @("Convert-Audio")
AliasesToExport = @("cvaudio")
So, the module is visible to powershell. However, when I go to install via install-module -name XLDPlusPlus I see the following error message:

PS /Users/Plastikfan> Install-Module -Name XLDPlusPlus
Install-Package: /usr/local/microsoft/powershell/7/Modules/PowerShellGet/PSModule.psm1:9685
Line |
9685 | … talledPackages = PackageManagement\Install-Package @PSBoundParameters
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| No match was found for the specified search criteria and module name 'XLDPlusPlus'. Try Get-PSRepository to see all available registered module repositories.

PS /Users/Plastikfan>

I am not sure what is meant but this error. I thought you could install modules from a local source (ie from /Users/Plastikfan/.local/share/powershell/Modules), but it seems like it’s trying to find XLDPlusPlus from a public repository, which it clearly won’t be able to do yet, since I have not published it.

If I check Get-PSRepository then I see:

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

I then tried to see if I could import the module so the Convert-Audio command was available to use in the powershell session using import-module -name XLDPlusPlus, but then I saw this error:

PS /Users/Plastikfan> Import-Module -name XLDPlusPlus
.: /Users/Plastikfan/.local/share/powershell/Modules/XLDPlusPlus/XLDPlusPlus.psm1:1
Line |
1 | . ./xld-converter.ps1
| ~~~~~~~~~~~~~~~~~~~
| The term './xld-converter.ps1' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included,
| verify that the path is correct and try again.

PS /Users/Plastikfan>

which is understandable. If you look at the .psm1 file inside the module, it simply dot sources the entry script xld-converter, which can’t be found unless you’re already in the module directory. (I want to be able to install the module, without having to cd to that directory, which for the user would be a real pain).

The whole point of this task, is that I want to define a Powershell module that users can install locally on their machines (either from a public repo, or by manually downloading and installing) without having to run estoteric commands. I may need to define an install script to get round the issue of not being able to dot source internal scripts without getting ‘xxx not recocognised as the name of a cmdlet etc’ errors, so if there are more online resources that can help me with that, I’d appreciate some pointers.

Please take a peek at my code in github to see specifically how I defined the manifest and the module as a whole at XLDPlusPlus repo on Github.

Thank you.

 

 

 

 

 

Actually, I have just had a thought. Please can somebody clarify what installing a module actually means. If all it means is copying the source code over to a known module location (a location in PSModulePath), then I would suggest that I don’t need to install the module (it’s already there and visible to Get-Module). And indeed, does it mean that installing a module is only required by other users, and that actually, it can only work from a public repository? If this is indeed the case, then the only problem I have to solve is how do I get import-module to work without getting errors and making the Convert-Audio command (and the cvaudio alias) available to use in a powershell session.

 

‘Installing’ the module is making it available, typically on the local file system where Powershell can import it. The $env:PSModulePath is an environment variable that contains paths that will be searched for module imports by short name. If you do:

Import-Module XLDPlusPlus

This will search those directories for a PSM1 named XLDPlusPlus. Additionally, if you typed Convert-Audio, these paths will be searched and automatically import the module. Import of the module basically places the code in memory so that it can be executed. Modules can also be imported referencing a full path:

Import-Module C:\MyRepository\Powershell\Modules\XLDPlusPlus\XLDPlusPlus.psm1

Some other suggestions:

  • Definitions (xld-definitions) should be a GET\SET. Typically, this should be simple to manage like XML or JSON saved in the module to persist the settings, but you can also just set a variable when the module is imported as well. Here is something along those lines, https://powershell.anovelidea.org/powershell/how-i-implement-module-variables/, but it is missing another option which is $MyInvocation.MyCommand.Module.PrivateData being leveraged in the module. One implementation is https://www.powershellgallery.com/packages/PSJira/1.2.5.251
  • The utils (e.g. xld-utils) can be broken out into separate scripts and referenced as Privateor Internal, you can see this in the PSJira example above.

Hi Rob,

thanks very much for your reply, most appreciated. As you can probably deduce from my other additional reply when I requested clarification of the meaning of powershell module install, I have realised the error of my ways and am now much clearer on things. And you have made some very good and valued points about how I can improve the module, which I’ll take on board and implement. Also, those other references are great and I can see how I’d like to further enhance the module, particularly with the use of global state.

Could you confirm that the reason for my original errors when attempting to install XLDPlusPlus, was because it was not found in the public repository ‘https://www.powershellgallery.com/api/v2’?

Cheers