Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating powershell modules from multiple files, referencing with module

Tags:

powershell

I creating a PowerShell script module using separate source files. What is the canonical way to reference source functions internal to the module from other internal source files?

For example if my module is created from PS source code in files "foo" and "bar"; and a function in "foo" needs to call a function in "bar", what is the best way to do that?

It doesn't seem like dot-sourcing would be a good idea. Nor does making the component files ("foo" and "bar") psm1 files. Is this the idea behind the "ScriptsToProcess" field in the psd1 file?

Am I thinking about this wrong (non-"PowerShelly")? Should I just dump everything into a single psm1?

like image 264
Dweeberly Avatar asked Jun 12 '17 22:06

Dweeberly


People also ask

How do you create a module manifest in PowerShell?

To create and use a module manifest The best practice to create a module manifest is to use the New-ModuleManifest cmdlet. You can use parameters to specify one or more of the manifest's default keys and values. The only requirement is to name the file.

What is psd1 and psm1?

. psm1 files contain main source code for a powershell module and . psd1 manifest data. You have to install them.

What is a psd1 file?

File used by Windows PowerShell, a shell program that includes more advanced features than the Windows Command Prompt; contains various configuration information for a PowerShell script or module. PSD1 files are used for storing module manifest information in hash table format.


1 Answers

I've personally followed the practice laid out by RamblingCookieMonster in his blog here: http://ramblingcookiemonster.github.io/Building-A-PowerShell-Module/

Which is to organise your functions in to separate .ps1 files under sub-folders \Public and \Private. Public contains the functions the user should be able to call directly, Private is for the functions that are only used internally by your module.

Then in the .psm1 file you load the functions via a loop and dot sourcing as follows:

#Get public and private function definition files.
    $Public  = @( Get-ChildItem -Path $PSScriptRoot\Public\*.ps1 -ErrorAction SilentlyContinue )
    $Private = @( Get-ChildItem -Path $PSScriptRoot\Private\*.ps1 -ErrorAction SilentlyContinue )

#Dot source the files
    Foreach($import in @($Public + $Private))
    {
        Try
        {
            . $import.fullname
        }
        Catch
        {
            Write-Error -Message "Failed to import function $($import.fullname): $_"
        }
    }

# Here I might...
    # Read in or create an initial config file and variable
    # Export Public functions ($Public.BaseName) for WIP modules
    # Set variables visible to the module and its functions only

Export-ModuleMember -Function $Public.Basename
  • Source of this example: https://github.com/RamblingCookieMonster/PSStackExchange/blob/db1277453374cb16684b35cf93a8f5c97288c41f/PSStackExchange/PSStackExchange.psm1

You should then also explicitly list your Public function names in your .psd1 module manifest file under the FunctionsToExport setting. Doing this allows these functions to be discoverable and the module to be auto-loaded when they are used.

like image 192
Mark Wragg Avatar answered Oct 07 '22 20:10

Mark Wragg