Luke Puplett Luke Puplett - 3 months ago 17
PowerShell Question

Can I make a module from a bunch of single-function scripts?

We've accumulated a bunch of scripts, each looks and feels like CmdLets, i.e. it has a set of declared params and then it immediately calls a Main function which does the work, calling private sub-functions within.

An example is

Remove-ContentLine.ps1
which just spits out the contents of a file or piped input except for lines matching some pattern.

So they're like little "function-scripts".

Is there any way I can aggregate these scripts into a module while also keeping them exactly as they are in files?

Edit

If your hunch is that its easier to just copy paste and refactor them into a
psm1
then just say ;)

Answer

You ask:

Is there any way I can aggregate these scripts into a module while also keeping them exactly as they are in files?

But I am certain that is not what you really want. If so, then all of your code will immediately execute when you load the module! Rather, I think what you want is that each of your scripts should be contained within a function; that group of functions is then loaded when you import the module; and you can then execute any of your functions on demand.

The process is very straightforward, and I have written an extensive article on just how to do that (Further Down the Rabbit Hole: PowerShell Modules and Encapsulation) but I will summarize here:

(1) Edit each file to wrap the entire contents into a function and conclude with exporting the function. I would suggest name the function based on the file name. Thus, Remove-ContentLine.ps1 should now look like this:

function Remove-ContentLine()
{
    # original content of Remove-ContentLine.ps1 here
}
Export-ModuleMember Remove-ContentLine

(2) Decide on a name for your module and create a directory of that name. Let's call it MyModule. Within the MyModule directory, create a subdirectory to place all your .ps1 files; let's call that ScriptCmdlets.

(3) Create a module file MyModule.psm1 within MyModule whose contents will be exactly this:

Resolve-Path $PSScriptRoot\ScriptCmdlets\*.ps1 |
? { -not ($_.ProviderPath.Contains(".Tests.")) } |
% { . $_.ProviderPath }

Yes, every module (.psm1) file I write contains that identical code!

(4) Create a module manifest MyModule.psd1 within MyModule using the New-ModuleManifest cmdlet.

Then to use your module, just use Import-Module. But I urge you to review my article for more details to gain a better understanding of the process.