3

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.

2
  • Nested modules a independent from each other. If you want to use Private from Public, then Public should import Private. Commented Jan 24, 2016 at 17:54
  • That I didn't know. I must not be looking in the right place for module documentation. This gives me some ideas on how to accomplish. Commented Jan 24, 2016 at 20:11

2 Answers 2

2

@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.

Sign up to request clarification or add additional context in comments.

1 Comment

I think this solution could be quite useful. The linked GitHub repo is not available. Could you either make the code available on GitHub or edit this answer to include more of the source code? Working examples are gold. Thanks!
1

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 = '*-*'

1 Comment

The primary reason I don't use this approach is because non-standard names is not best practice, and can lead to a bunch of ugly warning text being output to the console.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.