PSModuleTemplate.psm1

function New-ProjectTemplate
{
    [CmdletBinding()]
    [OutputType([System.Void])]
    Param
    (
        [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Name,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Description,

        [Parameter()]
        [switch]
        $Force
    )

    $SafeProjectName = $Name
    
    if ($Name -match '\s+'){
        $SafeProjectName = $Name.ToLowerInvariant() -replace ' ', '_'    
    }
    
    $ModuleName = [System.Globalization.CultureInfo]::CurrentCulture.TextInfo.ToTitleCase($SafeProjectName)
    $ResourcesFolder = "$PSScriptRoot\Resources\New-ProjectTemplate" | Resolve-Path
    
    $Psd1TemplatePath = Join-Path -Path $ResourcesFolder -ChildPath 'PSModuleName.psd1'
    $Ps1TestTemplatePath = Join-Path -Path $ResourcesFolder -ChildPath 'PSModuleName.tests.ps1'
    $Ps1ProgramTemplatePath = Join-Path -Path $ResourcesFolder -ChildPath 'Program.ps1'
    
    $Psd1TemplateContent = Get-Content -Path $Psd1TemplatePath -Raw
    $Ps1TestTemplateContent = Get-Content -Path $Ps1TestTemplatePath -Raw
    $Ps1ProgramTemplateContent = Get-Content -Path $Ps1ProgramTemplatePath -Raw
    
    $Tokens =  @{
        ModuleName=$ModuleName
        Guid=[Guid]::NewGuid().ToString()
        Author=$env:USERNAME
        Year=(Get-Date).Year
        Description=$Description
        CompanyName=$env:USERDOMAIN
    }

    $RegexOptions = [System.Text.RegularExpressions.RegexOptions]::IgnoreCase
    $Tokens.GetEnumerator() | ForEach-Object {
        $Pattern = [Regex]::Escape('<{0}>' -f $_.Key)        
        $Psd1TemplateContent = [Regex]::Replace($Psd1TemplateContent, $Pattern, $_.Value, $RegexOptions)
        $Ps1TestTemplateContent = [Regex]::Replace($Ps1TestTemplateContent, $Pattern, $_.Value, $RegexOptions)
        $Ps1ProgramTemplateContent = [Regex]::Replace($Ps1ProgramTemplateContent, $Pattern, $_.Value, $RegexOptions)
    }

    $CurrentDirectory = (Get-Location).Path
    $Destination = Join-Path -Path $CurrentDirectory -ChildPath $ModuleName

    if ((Test-Path -Path $Destination -PathType 'Container') -and (-not $Force.IsPresent)){
        $WShell = New-Object -ComObject Wscript.Shell
        $WShell.Popup('Ya existe un m�dulo con este nombre. Si est� seguro de continuar utilice el par�metro -Force',0,'Atenci�n',48)
        return
    }

    New-Item -Path $Destination -ItemType 'Directory' -ErrorAction SilentlyContinue | Out-Null 
    
    $Psd1ModulePath = Join-Path -Path $CurrentDirectory -ChildPath ('{0}\{0}.psd1' -f $ModuleName)
    New-Item -Path $Psd1ModulePath -ItemType 'File' -Value $Psd1TemplateContent -Force | Out-Null 

    $Ps1TestModulePath = Join-Path -Path $CurrentDirectory -ChildPath ('{0}\{0}.Tests.ps1' -f $ModuleName)    
    New-Item -Path $Ps1TestModulePath -ItemType 'File' -Value $Ps1TestTemplateContent -Force | Out-Null 

    $Ps1ProgramModulePath = Join-Path -Path $CurrentDirectory -ChildPath ('{0}\Program.ps1' -f $ModuleName)    
    New-Item -Path $Ps1ProgramModulePath -ItemType 'File' -Value $Ps1ProgramTemplateContent -Force | Out-Null 
    
    Copy-Item -Path (Join-Path -Path $ResourcesFolder -ChildPath 'Config.psd1') -Destination $Destination -Force | Out-Null 
    Copy-Item -Path (Join-Path -Path $ResourcesFolder -ChildPath 'Functions.psm1') -Destination $Destination -Force | Out-Null 
    Copy-Item -Path (Join-Path -Path $ResourcesFolder -ChildPath 'PSModuleName.psm1') -Destination ($Destination + '\{0}.psm1' -f $ModuleName) -Force | Out-Null 

    Get-ChildItem -Path $Destination    
}