Keeping Track of PowerShell Functions in Script Modules when Dot-Sourcing PS1 Files

I’m picking up where I left off in a previous blog article Write Dynamic Unit Tests for your PowerShell Code with Pester. I’m using the dynamic Test-MrFunctionsToExport Pester test that I wrote about in that previous blog article. Currently, the test is failing for my MrToolkit module that’s part of my PowerShell repository on GitHub:

Test-MrFunctionsToExport -ManifestPath .\GitHub\PowerShell\MrToolkit\MrToolkit.psd1


Based on the previous results, I can easily determine that more functions exist in the module folder than are specified in the FunctionsToExport section of the module manifest. That may sound like a simple fix but once you have tons of PS1 files in the module folder and a similar number specified in the manifest, it becomes difficult to know what’s missing so I’ve written a tool to generate a list of the function names:

function Get-MrFunctionsToExport {

    Returns a list of functions in the specified directory.

    Get-MrFunctionsToExport is an advanced function which returns a list of functions
    that are each contained in single quotes and each separated by a comma unless the
    simple parameter is specified in which case a simple list of the base file names
    for the functions is returned.

    Path to the folder where the functions are located.

    Pattern to exclude. By default profile scripts and Pester tests are excluded.

    Return function names from subdirectories in addition to the specified directory.

    Return a simple list instead of a quoted comma separated list.

    Get-MrFunctionsToExport -Path .\MrToolkit

    Get-MrFunctionsToExport -Path .\MrToolkit -Simple



    Author:  Mike F Robbins
    Twitter: @mikefrobbins

    param (
          If (Test-Path -Path $_ -PathType Container) {
          else {
            Throw "'$_' is not a valid directory."
        [string]$Path = (Get-Location),

        [string[]]$Exclude = ('*profile.ps1', '*.tests.ps1'),



    $Params = @{
        Exclude = $Exclude

    if ($PSBoundParameters.Recurse) {
        $Params.Recurse = $true

    $results = Get-ChildItem -Path "$Path\*.ps1" @Params |
               Select-Object -ExpandProperty BaseName

    if ((-not($PSBoundParameters.Simple)) -and $results) {
        $results = $results -join "', '"
        Write-Output "'$results'"
    elseif ($results) {
        Write-Output $results


For those of you who didn’t read the previous blog article that I referenced, I’ve moved to the model of placing each of my functions into a separate PS1 file and the file base name is the same as the function name. Each PS1 file is dot-sourced in the PSM1 file when the module is imported and a list of the function names must exist in the FunctionsToExport section of the module manifest (or exported via Export-ModuleMember in the PSM1 file).

I’ll use this tool to generate a list of function names. If nothing is specified in the FormatsToProcess or TypesToProcess section of the module manifest, it can be updated programmatically using the Update-ModuleManifest cmdlet. Unfortunately a known error is generated as shown in the following example if either or both of these are specified:

Update-ModuleManifest -Path .\GitHub\PowerShell\MrToolkit\MrToolkit.psd1 -FunctionsToExport (Get-MrFunctionsToExport -Path .\GitHub\PowerShell\MrToolkit\ -Simple)


Update-ModuleManifest : Cannot update the manifest file ‘.\GitHub\PowerShell\MrToolkit\MrToolkit.psd1’ because the
manifest is not valid. Verify that the manifest file is valid, and then try again.’The member ‘FormatsToProcess’ in
the module manifest is not valid: Cannot find path
‘C:\Users\mikefrobbins\AppData\Local\Temp\1707008812\GitHub\PowerShell\MrToolkit\MrToolkit.ps1xml’ because it does not
exist.. Verify that a valid value is specified for this field in the
‘C:\Users\mikefrobbins\AppData\Local\Temp\1707008812\NewManifest.psd1′ file.’
At line:1 char:1
+ Update-ModuleManifest -Path .\GitHub\PowerShell\MrToolkit\MrToolkit.p …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (System.Argument…rd errorRecord):ArgumentException) [Update-ModuleMan
ifest], ArgumentException
+ FullyQualifiedErrorId : UpdateManifestFileFail,Update-ModuleManifest

The sub-command used in the previous example creates a simple list of the function names:

Get-MrFunctionsToExport -Path .\GitHub\PowerShell\MrToolkit\ -Simple


Luckily, I’ve written the Get-MrFunctionToExport function so it generates a list in the proper format that can be pasted into the module manifest if you happen to run into a scenario such as this one where Update-ModuleManifest can’t be used.

Get-MrFunctionsToExport -Path .\GitHub\PowerShell\MrToolkit\


The easiest way to copy the results of the previous command is to simply pipe it to clip.exe:

Get-MrFunctionsToExport -Path .\GitHub\PowerShell\MrToolkit\ | clip.exe


After pasting the results into the FunctionsToExport section of the module’s manifest (PSD1 file), the Pester test runs without issue:

Test-MrFunctionsToExport -ManifestPath .\GitHub\PowerShell\MrToolkit\MrToolkit.psd1


Keeping track of functions and making sure they’re all specified in the FunctionsToExport section of the module manifest can be a annoying to maintain but it’s a necessary evil if you want module auto-loading to work properly when placing the functions from your modules in separate PS1 files.

Why not make your life a little easier by creating tools to make building other tools easier?