Module Builder

This module is used to build, update and publish modules.

I have switched my workflow for making modules a few times now, from creating a module from the ground up to having a script put the scaffolding together for the PSD1 and PSM1 files.

Currently I am using a method of compiling separate functions into a module along with creating all of the necessary files, this is by far my favorite way of doing it as it is much easier to work on when the modules get larger and more complicated as everything can be separated at the function level. It can also allow you to separate Public and Private functions, I do not currently do this as I have yet to find a need for it in my environment.

Here is an example of how I currently have my code structured. You don’t necessarily have to follow the same structure but the build module may need some adjusting to work with a different structure.

function Build {
    Developer:  Mike Polselli
    PSVersion:  5.0
    Language:   PowerShell
    Purpose:    This script will compile scripts into a module. Its purpose is to create a module while leaving the "Functions" as individual scripts for easy management and updating.
    Displays helpful information about the script.
    Identifies the module you wish to build.
    Used when you are building a new module, this will create the necessary files and prompt for a description.
    Publishes the module to the CompanyName Repository.
    Updates the module manifest, uses the Microsoft versioning standard.
    Build -Help
    Build -Identity Logging
    Build -Identity Logging -Publish -Update Revision
    Build -Identity SomeModule -NewModule

    Enter a description for SomeModule.: This is a description of the module.
    [cmdletbinding(DefaultParameterSetName = "Primary")]
    param (
        [Parameter(ParameterSetName = "NewModule", Position = 0, Mandatory = $true)]
        [Parameter(ParameterSetName = "Publish", Position = 0, Mandatory = $true)]
        [Parameter(ParameterSetName = "Primary", Position = 0, Mandatory = $true)]

        [Parameter(ParameterSetName = "NewModule", Position = 1)]

        [Parameter(ParameterSetName = "Publish", Position = 2)]

        [Parameter(ParameterSetName = "Publish", Position = 3)]
        [ValidateSet('Major', 'Minor', 'Build', 'Revision')]

        [Parameter(ParameterSetName = "Help")][switch]$Help
    if ($Help) {
        Get-Help $MyInvocation.MyCommand.Name -Full | more
    $Path = "\\$env:USERDNSDOMAIN\Path\To\Module\Scripts"
    $NewPath = $Path | Split-Path -Parent
    if ($NewModule) {
        # Creates required files and folders for the new module.
        try {
            # This will stop existing modules from being overwritten.
            New-Item -Path $NewPath\$Identity -ItemType Directory -ErrorAction Stop
            New-Item -Path $NewPath\$Identity\$Identity'.psm1' -ItemType File
            $Properties = @{
                Path          = "$NewPath\$Identity\$Identity.psd1"
                Author        = 'YourName'
                CompanyName   = 'CompanyName'
                Description   = Read-Host -Prompt "Enter a description for $Identity."
                ModuleVersion = ''
                RootModule    = $Identity
            New-ModuleManifest @Properties
        catch {
            Write-Warning "The module $Identity already exists!"

    $Scripts = Get-ChildItem $Path\$Identity -Include *.ps1 -Recurse
    $Module = Get-ChildItem $NewPath\$Identity -Include *.psm1 -Recurse
    $Manifest = Get-ChildItem $NewPath\$Identity -Include *.psd1 -Recurse

    $Functions = @()
    Set-Content -Path $Module -Value $null

    foreach ($Script in $Scripts) {
        # Adds Functions to the module.
        # Adds the Function names to an array to export.
        $Code = Get-Content -Path $Script.FullName
        Add-Content -Path $Module -Value $Code -Force
        Add-Content -Path $Module -Value "`n" -Force
        $Functions += $Script.Name.Split('.')[0]
    Update-ModuleManifest -Path $Manifest -FunctionsToExport $Functions

    $GetFile = Get-ChildItem -Path $NewPath\$Identity *.psd1
    Test-ModuleManifest -Path $GetFile.FullName

    if ($Publish) {
        # Publishes the module.
        $GetCurrentVersion = Get-Content -Path $GetFile.FullName | Select-String -Pattern '^ModuleVersion = (.*)'
        [version]$CurrentVersion = $GetCurrentVersion.Matches.Groups[1].Value.Replace("'", '')
        switch ($Update) {
            Major { $UpdatedVersion = "{0}.{1}.{2}.{3}" -f ($CurrentVersion.Major + 1), $CurrentVersion.Minor, $CurrentVersion.Build, $CurrentVersion.Revision }
            Minor { $UpdatedVersion = "{0}.{1}.{2}.{3}" -f $CurrentVersion.Major, ($CurrentVersion.Minor + 1 ), $CurrentVersion.Build, $CurrentVersion.Revision }
            Build { $UpdatedVersion = "{0}.{1}.{2}.{3}" -f $CurrentVersion.Major, $CurrentVersion.Minor, ($CurrentVersion.Build + 1), $CurrentVersion.Revision }
            Revision { $UpdatedVersion = "{0}.{1}.{2}.{3}" -f $CurrentVersion.Major, $CurrentVersion.Minor, $CurrentVersion.Build, ($CurrentVersion.Revision + 1) }
        (Get-Content -Path $GetFile.FullName -Raw) -replace $GetCurrentVersion.Matches.Groups[1].Value, $UpdatedVersion.Insert($UpdatedVersion.Length, "'").Insert(0, "'") | Set-Content -Path $GetFile.FullName

        Publish-Module -Path $NewPath\$Identity -Repository RepositoryName

$IdentityBlock = {
    param($CommandName, $ParameterName, $WordToComplete, $CommandAst, $FakeBoundParameter)
    $Path = "\\$env:USERDNSDOMAIN\Path\To\Module\Scripts"
    (Get-ChildItem $Path).Name | Where-Object {
        $PSItem -like "$WordToComplete*"
    } | ForEach-Object {

Register-ArgumentCompleter -CommandName Build -ParameterName Identity -ScriptBlock $IdentityBlock

As with all code you find on the internet, look it over, tinker with it, test it, and so on before you use it in any production environments!