if I have a module called foo
C:\Users\gary\Documents\PowerShell\Modules\foo\foo.psm1
C:\Users\gary\Documents\PowerShell\Modules\foo\foo.psd1
With the content of foo.psd1
being:
@{
ModuleVersion = '0.0.1'
FunctionsToExport = @('*')
RootModule = 'foo.psm1'
}
and foo.psm1
:
Function Encode-Path{
[CmdletBinding()]
Param(
[Parameter(ValueFromPipeline, Mandatory)]
$Path
)
Process {"Some process"}
End {"Ending..."}
}
Function Decode-Path{
[CmdletBinding()]
Param(
[Parameter(ValueFromPipeline, Mandatory)]
$Path
)
Process {"Some process"}
End {"Ending..."}
}
Simply calling the Encode-Path
at the shell will fail with:
Encode-Path: The term 'Encode-Path' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
I sometimes fix this by calling pwsh.exe
within the session and then:
Get-Module -ListAvailable
but it too sometimes does not even work and when it does there is a long delay, as it will import every module on my system.
I know this issue is being caused by my use of unapproved verb. I really don't like the <verb><noun>
at all. I don't work with a team, I just use PowerShell to make my life easy, so please don't just suggest I get on board with it.
Searching around I have not found any solution for this, I just keep coming across solutions for Import-Module -DisableNameChecking
which is addresses a separate issue, which is to supress warning messages about "unapproved verbs"
I am just looking for a way to auto import modules as I invoke their commands, Ideally avoid having to import all modules at once.
Your symptom isn't consistent with your problem description / sample code.
PowerShell's de facto behavior is as follows (written as of v7.4.x):
Auto-loading happens for any module placed in one of the directories listed in $env:PSModulePath
.
When auto-loading happens, there is no warning for exported commands that do not adhere to PowerShell's naming convention, i.e. commands that do not use the <verb>-<noun>
convention, with <verb>
needing to be one of the approved verbs.
By contrast, explicitly loading (importing) a given module that exports commands with nonstandard names does generate a warning:
If Import-Module
is used for explicit importing, you can use the -DisableNameChecking
switch to silence the warning.
If using module
is used - which is a must if you want to import class
and enum
definitions from a script module - you can NOT silence the warning.
If you want to ensure that no warning is ever emitted:
Give your functions a standard name to begin with - which you must export too, however.
Define - and export - aliases for those functions, using the desired nonstandard names (alias names are not subject to the warning) - see the bottom section for an example.
In other words: if your module is located in one of the directories in $env:PSModulePath
, loading it implicitly by invoking one of its exported commands will not result in a warning.
Get-Module -ListAvailable
[...] when it does there is a long delay, as it will import every module on my system.
-ListAvailable
does not import every module - it simply reports all modules that are discoverable via $env:PSModulePath
, along with their exported commands an aliases.
However, you can help speed up discovery by avoiding wildcard expressions; e.g., instead of using FunctionsToExport = @('*')
in your module manifest, enumerate the functions to export explicitly: `FunctionsToExport = @('Encode-Path', 'Decode-Path')
# Create a directory for a `sample` module in the current user's module location:
# Get the root dir. of the current user's modules.
$currUserModuleRootDir = ("$(Split-Path $PROFILE)\Modules", "$HOME/.local/share/powershell/Modules")[$env:OS -ne 'Windows_NT']
# Create a 'sample' subdirectory for it, to create a module by that name.
$sampleModuleDir = New-Item -Force -Type Directory (Join-Path $currUserModuleRootDir sample)
# Create the root script module (`*.psm1`):
@'
# Define the functions with *standard* names.
Function ConvertTo-__Path {
[CmdletBinding()]
Param(
[Parameter(ValueFromPipeline, Mandatory)]
$Path
)
Process {"Some process"}
End {"Ending..."}
}
Function ConvertFrom-__Path {
[CmdletBinding()]
Param(
[Parameter(ValueFromPipeline, Mandatory)]
$Path
)
Process {"Some process"}
End {"Ending..."}
}
# Now define *alias* with the desired - nonstandard - names:
Set-Alias Encode-Path ConvertTo-__Path
Set-Alias Decode-Path ConvertFrom-__Path
'@ > (Join-Path $sampleModuleDir sample.psm1)
# Create the module's manifest:
@'
@{
ModuleVersion = '0.0.1'
FunctionsToExport = @('ConvertTo-__Path', 'ConvertFrom-__Path')
AliasesExport = @('Encode-Path', 'Decode-Path')
RootModule = 'sample.psm1'
}
'@ > (Join-Path $sampleModuleDir sample.psd1)
After running the above:
Encode-Path
and Decode-Path
should be auto-discoveredImport-Module sample
or using module sample
should work without warning.If you later want to remove the sample module, run the following (you may have to run Remove-Module sample
first):
Remove-Item -Recurse (Join-Path ("$(Split-Path $PROFILE)\Modules", "$HOME/.local/share/powershell/Modules")[$env:OS -ne 'Windows_NT'] sample)