Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Internal functions in PowerShell Module

I'm writing a module, and I have some helper functions that I don't want exposed, but I do want available to module functions internally. I have set up my directory structure like:

root\
..Private
....Invoke-PrivateTest.ps1
....private.psd1
....private.psm1
..Public
....Get-Something.ps1
....Public.psd1
....Public.psm1
..test.psd1

I've setup a repository on github https://github.com/jpbruckler/test that has all the module files in it.

The behavior that I'm expecting is that Get-Something is a public function. When running Get-Command -Module Test it should be listed. On the contrary, Invoke-PrivateTest should not be in the output of that command.

When calling Get-Something it should output the text Invoke-PrivateTest called. Instead, I get an error stating that the command Invoke-PrivateTest doesn't exist.

I am explicitly saying in test.psd1 that only the Get-Something function is to be exported.

Both the Private module and the public module are being called via the NestedModules property in test.psd1. Any help or pointers would be appreciated.

like image 716
John Bruckler Avatar asked Sep 16 '26 20:09

John Bruckler


2 Answers

@PetSerAl pointed me in the right direction. Ultimately this came down to a scoping issue. The way I had the module arranged, each sub-module would need to make a call to load the private module, which is a bunch of code duplication - and also what I was hoping to avoid by splitting out some helper functions.

To get it all to work, instead of multiple sub modules, I just broke up the Public folder into sub folders that will hold scripts that do similar things, basically removing all the .psd1 and .psm1 files from the Public directory. I did the same thing for the Private directory. This left me with a bunch of loose .ps1 files that I load in test.psm1 with the following code:

$Private = (Get-ChildItem -Path (Join-Path $PSScriptRoot 'Private') -Filter *.ps1)
$Public = (Get-ChildItem -Path (Join-Path $PSScriptRoot 'Public') -Filter *.ps1 -Recurse)


foreach ($Script in $Public) {
    . $Script.FullName
    Export-ModuleMember $Script.BaseName
}

foreach ($Script in $Private) {
    . $Script.FullName
}

I've modified the test module at https://github.com/jpbruckler/test to reflect the changes I made.

like image 98
John Bruckler Avatar answered Sep 18 '26 12:09

John Bruckler


Unless you have other reasons to put the code into separate (sub)modules I'd keep it in one folder and control what's exported via the function names. Use "official" notation (<Verb>-<Noun>) for the names of public functions and omit the hyphen in the names of private function (<Verb><Noun>). That way you can export public functions in your global .psd1 like this:

FunctionsToExport = '*-*'
like image 32
Ansgar Wiechers Avatar answered Sep 18 '26 11:09

Ansgar Wiechers