I'm trying to make use of module-qualified names[1] and a DefaultCommandPrefix
and not have it break if the module is imported with Import-Module -Prefix SomethingElse
. Maybe I'm just doing something really wrong here, or those two features aren't meant to be used together.
Inside the main module file using "ModuleName\Verb-PrefixNoun args...
" works as long as "Prefix" matches the DefaultCommandPrefix
in the manifest (the module-qualified syntax seems to require the prefix used for the import[2]). But importing the module with a different prefix, all module-qualified references inside the module breaks.
After a bit of searching and trial and error, the least horrible solution I've managed to get working is to use something like the following hackish solution. But, I can't help wonder if there isn't some better way that automatically handles the prefix (just as Import-Module
obviously manages to add the prefix, my first naive though was that using just ModuleName\Verb-Noun
would automatically append any prefix to the noun, but evidently not[2].
So this is the hack I came up with, that looks up the modules prefix and appends it, then using "." or "&" to expand/invoke the command:
# (imagine this code in the `ModuleName.psm1`, and a manifest with some `DefaultCommandPrefix`)
Function MQ {
param (
[Parameter()][string]
$Verb,
[Parameter()][string]
$Noun,
[string]
$Module='ModuleName'
)
"$Module\$Verb-$((Get-Module $Module).Prefix)$Noun"
}
Function Verb-Noun {
# This works even when importing with a prefix,
# but can I be guaranteed that it's not some
# other module's cmdlet?
Verb-OtherNoun 1 2 3 '...'
#ModuleName\Verb-OtherNoun 1 2 3 '...'
. (MQ 'Verb' 'OtherNoun') 1 2 3 '...'
# or:
& (MQ 'Verb' 'OtherNoun') 1 2 3 '...'
}
(MQ
could be made more user friendly by also accepting a single string MQ "Verb-Noun"
and split/recombine automatically, and so on, etc. and all the usual disclamers)
Note: I know it would be possible to hard-code the name instead of using DefaultCommandPrefix
, e.g. as PSReadLine
does (and a bunch of other modules). But, to be honest that feels like a workaround.
Just calling Verb-OtherNoun
seems fragile to me, as the most recent one is used[3]. So I would imagine that for example just before the call adding an Import-Module
statement with a module that exports a Verb-OtherNoun
would cause the wrong (not this module's) cmdlet being called. (Perhaps a more real world scenario is a module being loaded after this module has been loaded, but before calling Verb-Noun
.)
Is there perhaps some syntax for module-qualifiaction I'm not aware of that would do something akin to Import-Module
(e.g. Module\\Verb-Noun
or Module\Verb+Noun
that would resolve and inject Module's prefix) and now that I think of it, is there some reason why Module\Verb-Noun
doesn't handle prefixes, or just that no one wrote the code for it? (I can't see how it would break things more than how using DefaultCommandPrefix
would break v2/v3[2])
[1] https://www.sapien.com/blog/2015/10/23/using-module-qualified-cmdlet-names/
[2] https://github.com/PoshCode/PowerShellPracticeAndStyle/issues/23#issuecomment-106843619