Correct way of calling functions in module for creating new users in AD

I’m working on a module for creating users in our AD. We currently have a batch script doing this work in one big file, but I want to break it down into separate functions and package it as a module.

Here is the structure of the module as it looks today:
| MGADUser.psd1
| MGADUser.psm1
| Convert-SpecialCharacters.ps1
| New-MGStudentAccountName.ps1

I only export the functions from the Public folder and anything in Private is called by New-MGADUser.ps1.

Convert-SpecialCharacters.ps1 contains a function of the same name and takes a string, converts it to lower case and replaces characters such as ä,ö and å with a, o and a respectively and returns the converted string.
New-MGStudentAccountName.ps1 is still a work in progress but basically it will take the converted names, grab the first two characters from first name and and the first four from last name and finally prefix the current year.
New-MGADUser.ps1 should be accessible from the command line and take the first and last name of a new student and from that call the functions in Private in order to create a SAM account name matching our template and finally passing everything to New-ADUser from the ActiveDirectory module.

I actually have two questions but my primary concern is of the flow(?) of the thing. Most recommendations go towards splitting up tasks in separate smaller functions for increased readability and simplicity. I get that, I’m just not sure how to write the calling function to get the right result.

Let me try to make a rough skelefon of what I imagine:
New student: Göran Olof Västergren
$firstName = “Göran Olof” passed to Convert-SpecialCharacters.ps1 and returned as $firstName = “goranolof”
$lastName = “Västergren” passed to Convert-SpecialCharacters.ps1 and returned as $lastName = “vastergren”
$firstName and $lastName passed to New-MGStudentAccountName.ps1 and returned as $SAMAccountName: “19govast”

In the end I want to be able to create a new user with a unique SAM account name, place the user in the right OU and groups. But first I need to get a clearer image of how to pass the different variables through the different functions to acheive the first steps.

To recap:
How do I pass the name through the functions in Private to get my desired outcome?
Should each function be a separate file in Private?

Kind regards


No reason to put them into separate files. You can put many functions in a single module with no problem. (And you can actually put multiple functions in a single .ps1 and then dot-source the file into another .ps1 to get access to the all of the functions in that new file, similar to an include in C++. But I don’t think that’s recommended practice…)

So, you’re wanting to make a single execution of New-MGADUser.ps1 that will make the necessary calls to the rest of the functions and create the new user, right?

If that’s the case, why not put all of your functions into one module and then only publish the functions you want to be accessible outside of the module? Just use Export-ModuleMember with a list of the functions you want to be accessible.

$exports = @(

Export-ModuleMember $exports

Then you can put your Convert-SpecialCharacters.ps1 and New-MGStudentAccountName.ps1 in the same module with the functions that will use them, so that way you don’t have to worry about including them, etc.

No matter where the files are , you can control it. when creating modules, I would suggest you to use module manifest capabilities to restrict what to be exposed.

Internally you can have variables in script scope which is accessible across the module. Its better to parameterize your functions to accept those variables as arguments.

There are alot of PowerShell projects out there in Github, you can explore and see how these are organised.

Thank you for your replies

I feel I might not have been clear in what I was wondering. All of the functions are in the same module “MGADUser” but I have separated them into two folders: Private for functions which are only called by other functions/files in the module and Public which contains the functions which are exported in the Module Manifest and called by the user directly.

My hope is that once the module is completely done it will allow me to add, remove and move users around our AD.

I have looked at a number of Powershell projects - among others the Rubrik Module which I used as a sort of template with the Private/Public folder divide and exporting only the functions from the Public folder.

However, writing out my question seems to have rebooted my thought processes about this, so this is the basic form of my New-MGADUser.ps1 in the Public folder:

Right now I only return the $samAccountName, but once it’s done it should add the user to the AD.

Does this look reasonable?

Kind regards