Auto-Loading Cmdlets as part of a Module dynamically

Viewed 106

So, I was thinking: I have a lot (!) of custom cmdlets, but I don't want them to load all of them in my profile, because, naturally, that will take a lot of time. (I work fast, so my tools need to be fast.) But also, I don't want to always load them manually, because, well that's annoying. (And again ... I work fast!)

Luckily, there's a neat functionality called "Auto-Loading" which will totally solve my problem ... kind of. I just have to put my cmdlets into script modules, and they will be loaded automatically, right?

It seems though, there need to be some requirements met, for PowerShell to "detect" the cmdlets belonging to a module. The easiest way I know so far, is to simply put each cmdlet in a single ps1 file and then create a manifest somewhat like this:

@{
    ModuleVersion = "1.0"
    NestedModules = @(
        "Get-Something.ps1",
        "Remove-Something.ps1",
        "Test-Something.ps1",
        "Run-Something.ps1",
        "Invoke-Something.ps1",
        "Start-Something.ps1",
        "Stop-Something.ps1"
    ),
    CmdletsToExport = @(
        "Get-Something",
        "Remove-Something",
        "Test-Something",
        "Run-Something",
        "Invoke-Something",
        "Start-Something",
        "Stop-Something"
    )
}

This does work. But as I said .. I work fast, and I'm lazy. It would be much easier, if the module could discover its members dynamically. Basically, all ps1 files in the same folder. This would work pretty easily with some code in the psm1 file. But then, the Auto-Loading would not work. I understand PowerShell does need to know the exported cmdlets before hand.

Is there any other, dynamic way to do that, other than specifying them explicitly in the psd1 module manifest?

1 Answers

If you are worried about the size or organization of your module, create different modules for the different common subjects of your cmdlets, and put your functions into the psm1 for each module. Then make sure you add the cmdlet definitions to CmdletsToExport in the module manifest (psd1). If you have a centralized feed, distributing your modules becomes easy, and if you simply want all of them at a given time you can create a top level module that lists your other modules as dependencies so they get installed when you install the top level module. Unless you have hundreds to thousands of cmdlets to export as part of a single module, you shouldn't need to worry about performance problems.

For each module you have on the PSModulePath, you can use wildcards in the CmdletsToExport and FunctionsToExport sections of your manifest for auto-complete to work, if you don't want to export them name by name.

Edit: Technically, you can call Set-PSReadLineKeyHandler and Register-ArgumentCompleter yourself, however, you have the same problem now in that you need to add this to the $profile for each user or machine where you want the autocomplete to work, in addition to shipping your code there in the first place. So it doesn't really solve your issue.

Related