Shared Helper (Private) Functions

Let’s say I have 3 modules. Each has private and public functions. Now let’s say I have a private function in each module that does the same thing (same code). I don’t want to update 3 identical private functions. Instead, I want to share one private function between the 3 modules.

I could:

  1. Create a "Helper" module that becomes a dependency to the other 3 modules, but I want the functions in Helper to be private and I'm not sure how a module can access a private function from another module.
  2. Create a "Helper" module but the private functions are public instead. This method would defeat the purpose of keeping the functions private.
  3. Add some logic to each module when loaded to dot source a script file that contains the private functions. This idea does not settle well with me and seems counterproductive especially with a DevOps approach.
  4. Bite the bullet and deal with identical functions. Even more counterproductive.
I have not come across a solution when searching on this, and I'm hoping someone from the community has dealt with this. I would love to hear how you handled shared private functions.

Hi Kevin,

I am just dropping my opinion here, if a function is being called from more than one module then it can’t be a private function at all, if you don’t want to expose the code then you can write the same functionality using .Net and create an assembly, and the same you can reference in your modules.

There could be some other options, let’s see any other suggestions from the community.

Thank you.

You can do what Pester does and have the module created as a submodule. I don’t quite know exactly how it’s done myself as I’ve never really had the need to do so, but it couples several other modules (like Axiom) in its singular module, and doesn’t expose any of the functions from those modules directly.

https://github.com/pester/Pester/blob/e8324fe1fa9b1b23732401b9adfd3a5d07138eb7/Pester.psm1#L649-L653

Looks like it’s simply done as a manifest-less module and directly executed to import the commands.

private and public functions in PowerShell modules are decided by the author based on what he/she export as a member of the module.
Function for modules need not to be in same psm1, you can have common functions in a common.helper.ps1 and refer them in all three modules or like joel mentioned, create them in a psm1 and do import-module with the full path to the psm1.

Thank you for your feedback. Using common.helper.ps1 sounds interesting. I’m thinking of an idea on how to execute that and implement that into the development pipeline. We use SCCM compliance to distribute modules to our technician computers. I could do the same and deploy the common.helper.ps1 file. To load the ps1 in each module, I would have to add a line to dot source the ps1 file from within each module psm1?

No need to dot source the script. You can use the ScriptsToProcess key in the manifest.

# Script files (.ps1) that are run in the caller's environment prior to importing this module.
#ScriptsToProcess = @('.\common.helper.ps1')

Not sure that’s a good idea. That runs in the caller’s scope, so anything in there will be exported and exposed to that scope.

I was running some scripts with task scheduler in Windows with the system user, everything was ok, yesterday edited and modified the scripts and they still running but when I tried the same schedule they don’t run, changed to a RDP user and run when it is logged in option selected on task scheduler and it runs and works fine, what can I do to run these scripts without a logged user? Thank you!

Correct and the same is in the comments, else dot sourcing script common.helper.ps1 or Import-Module with the common.helper.psm1 is the other option.