<#
.SYNOPSIS
Advanced Template Module Generator Tool
.DESCRIPTION
This script provides an interactive tool to generate a comprehensive structure for a PowerShell module,
including advanced features like dependency management, script analyzer settings, and extensive testing setup.
.NOTES
File Name : AdvancedTemplateModuleGenerator.ps1
Author : [Your Name]
Prerequisite : PowerShell V5.1 or later
Version : 1.0
Date : [Current Date]
.EXAMPLE
.\AdvancedTemplateModuleGenerator.ps1
#>
function Show-Menu {
Clear-Host
Write-Host "=== Advanced Template Module Generator Tool ===" -ForegroundColor Cyan
Write-Host "1. Set Module Details"
Write-Host "2. Add Public Function"
Write-Host "3. Add Private Function"
Write-Host "4. Add Module Dependencies"
Write-Host "5. Configure Build Settings"
Write-Host "6. Configure Test Settings"
Write-Host "7. Generate Module Files"
Write-Host "8. Exit"
}
function Set-ModuleDetails {
$script:moduleName = Read-Host "Enter the name of the module"
$script:moduleDescription = Read-Host "Enter a brief description of the module"
$script:moduleAuthor = Read-Host "Enter the author's name"
$script:moduleVersion = Read-Host "Enter the module version (e.g., 1.0.0)"
$script:moduleLicense = Read-Host "Enter the module license (e.g., MIT)"
$script:moduleProjectUri = Read-Host "Enter the project URI (optional)"
Write-Host "Module details set successfully." -ForegroundColor Green
}
function Add-PublicFunction {
$functionName = Read-Host "Enter the name of the public function"
$script:publicFunctions += $functionName
Write-Host "Public function '$functionName' added." -ForegroundColor Green
}
function Add-PrivateFunction {
$functionName = Read-Host "Enter the name of the private function"
$script:privateFunctions += $functionName
Write-Host "Private function '$functionName' added." -ForegroundColor Green
}
function Add-ModuleDependencies {
do {
$dependencyName = Read-Host "Enter the name of the module dependency (or press Enter to finish)"
if ($dependencyName -ne "") {
$dependencyVersion = Read-Host "Enter the required version (leave blank for any version)"
$script:moduleDependencies += [PSCustomObject]@{
Name = $dependencyName
Version = $dependencyVersion
}
Write-Host "Dependency added: $dependencyName $dependencyVersion" -ForegroundColor Green
}
} while ($dependencyName -ne "")
}
function Set-BuildSettings {
$script:usePSScriptAnalyzer = (Read-Host "Use PSScriptAnalyzer for code analysis? (Y/N)") -eq 'Y'
$script:useplatyPS = (Read-Host "Use platyPS for documentation generation? (Y/N)") -eq 'Y'
Write-Host "Build settings configured." -ForegroundColor Green
}
function Set-TestSettings {
$script:usePester = (Read-Host "Use Pester for testing? (Y/N)") -eq 'Y'
$script:useCodeCoverage = (Read-Host "Include code coverage in tests? (Y/N)") -eq 'Y'
Write-Host "Test settings configured." -ForegroundColor Green
}
function Generate-ModuleFiles {
if ([string]::IsNullOrWhiteSpace($script:moduleName)) {
Write-Host "Please set module details first." -ForegroundColor Yellow
return
}
$modulePath = Join-Path -Path $PWD -ChildPath $script:moduleName
New-Item -Path $modulePath -ItemType Directory -Force | Out-Null
# Create module manifest
$manifestPath = Join-Path -Path $modulePath -ChildPath "$($script:moduleName).psd1"
$manifestParams = @{
Path = $manifestPath
RootModule = "$($script:moduleName).psm1"
ModuleVersion = $script:moduleVersion
Author = $script:moduleAuthor
Description = $script:moduleDescription
FunctionsToExport = $script:publicFunctions
PowerShellVersion = '5.1'
}
if ($script:moduleLicense) { $manifestParams['LicenseUri'] = $script:moduleLicense }
if ($script:moduleProjectUri) { $manifestParams['ProjectUri'] = $script:moduleProjectUri }
if ($script:moduleDependencies) {
$manifestParams['RequiredModules'] = $script:moduleDependencies | ForEach-Object {
if ($_.Version) { @{ModuleName = $_.Name; ModuleVersion = $_.Version} } else { $_.Name }
}
}
New-ModuleManifest @manifestParams
# Create module script file
$modulePSM1Path = Join-Path -Path $modulePath -ChildPath "$($script:moduleName).psm1"
$modulePSM1Content = @"
# Dot source public/private functions
`$public = @(Get-ChildItem -Path `$PSScriptRoot\Public\*.ps1 -ErrorAction SilentlyContinue)
`$private = @(Get-ChildItem -Path `$PSScriptRoot\Private\*.ps1 -ErrorAction SilentlyContinue)
foreach (`$import in @(`$public + `$private)) {
try {
. `$import.FullName
} catch {
Write-Error -Message "Failed to import function `$(`$import.FullName): `$_"
}
}
# Export public functions
Export-ModuleMember -Function `$public.BaseName
"@
Set-Content -Path $modulePSM1Path -Value $modulePSM1Content
# Create Public and Private folders
New-Item -Path (Join-Path -Path $modulePath -ChildPath "Public") -ItemType Directory -Force | Out-Null
New-Item -Path (Join-Path -Path $modulePath -ChildPath "Private") -ItemType Directory -Force | Out-Null
# Create function files
foreach ($function in $script:publicFunctions) {
$functionPath = Join-Path -Path $modulePath -ChildPath "Public\$function.ps1"
$functionContent = @"
function $function {
<#
.SYNOPSIS
Brief description of $function
.DESCRIPTION
Detailed description of $function
.PARAMETER Param1
Description of Param1
.EXAMPLE
$function -Param1 Value
Explanation of the example
.NOTES
Additional notes about the function
#>
[CmdletBinding()]
param (
[Parameter(Mandatory=`$true)]
[string]`$Param1
)
begin {
# Initialize any prerequisites
}
process {
# Main function logic
}
end {
# Cleanup or final actions
}
}
"@
Set-Content -Path $functionPath -Value $functionContent
}
foreach ($function in $script:privateFunctions) {
$functionPath = Join-Path -Path $modulePath -ChildPath "Private\$function.ps1"
$functionContent = @"
function $function {
[CmdletBinding()]
param (
[Parameter(Mandatory=`$true)]
[string]`$Param1
)
# Function logic here
}
"@
Set-Content -Path $functionPath -Value $functionContent
}
# Create tests folder and files
$testsFolderPath = Join-Path -Path $modulePath -ChildPath "Tests"
New-Item -Path $testsFolderPath -ItemType Directory -Force | Out-Null
if ($script:usePester) {
$testFilePath = Join-Path -Path $testsFolderPath -ChildPath "$($script:moduleName).Tests.ps1"
$testFileContent = @"
`$ModuleName = '$($script:moduleName)'
`$ModuleManifestPath = "`$PSScriptRoot\..\`$ModuleName.psd1"
Describe "`$ModuleName Module Tests" {
BeforeAll {
`$Module = Import-Module `$ModuleManifestPath -PassThru -Force
}
It "Module manifest is valid" {
Test-ModuleManifest -Path `$ModuleManifestPath | Should -Not -BeNullOrEmpty
`$? | Should -Be `$true
}
It "Module can be imported" {
`$Module | Should -Not -BeNullOrEmpty
}
Context "Function Tests" {
# Add tests for each function
$(foreach ($function in $script:publicFunctions) {
@"
It "$function exists" {
Get-Command $function -Module `$ModuleName | Should -Not -BeNullOrEmpty
}
"@
})
}
}
"@
Set-Content -Path $testFilePath -Value $testFileContent
}
# Create build configuration
$buildFolderPath = Join-Path -Path $modulePath -ChildPath "Build"
New-Item -Path $buildFolderPath -ItemType Directory -Force | Out-Null
$buildFilePath = Join-Path -Path $buildFolderPath -ChildPath "build.ps1"
$buildFileContent = @"
param (
[switch]`$Test,
[switch]`$Analyze,
[switch]`$Documentation
)
`$ModuleName = '$($script:moduleName)'
`$ModuleRoot = "`$PSScriptRoot\.."
`$OutputPath = "`$ModuleRoot\Output"
# Clean and create output directory
if (Test-Path -Path `$OutputPath) {
Remove-Item -Path `$OutputPath -Recurse -Force
}
New-Item -Path `$OutputPath -ItemType Directory -Force | Out-Null
# Copy module files to output directory
Copy-Item -Path "`$ModuleRoot\`$ModuleName.psd1" -Destination `$OutputPath
Copy-Item -Path "`$ModuleRoot\`$ModuleName.psm1" -Destination `$OutputPath
Copy-Item -Path "`$ModuleRoot\Public" -Destination `$OutputPath -Recurse
Copy-Item -Path "`$ModuleRoot\Private" -Destination `$OutputPath -Recurse
if (`$Test) {
# Run Pester tests
`$testResults = Invoke-Pester -Path "`$ModuleRoot\Tests" -PassThru
if (`$testResults.FailedCount -gt 0) {
throw "One or more tests failed."
}
}
if (`$Analyze) {
# Run PSScriptAnalyzer
`$analysisResults = Invoke-ScriptAnalyzer -Path `$OutputPath -Recurse
if (`$analysisResults) {
`$analysisResults | Format-Table
throw "PSScriptAnalyzer found one or more issues."
}
}
if (`$Documentation) {
# Generate documentation using platyPS
Import-Module platyPS
New-MarkdownHelp -Module `$ModuleName -OutputFolder "`$OutputPath\docs" -Force
}
Write-Host "Build completed successfully." -ForegroundColor Green
"@
Set-Content -Path $buildFilePath -Value $buildFileContent
# Create PSScriptAnalyzer settings file
if ($script:usePSScriptAnalyzer) {
$analyzerSettingsPath = Join-Path -Path $modulePath -ChildPath "PSScriptAnalyzerSettings.psd1"
$analyzerSettingsContent = @"
@{
Severity = @('Error', 'Warning')
ExcludeRules = @('PSUseShouldProcessForStateChangingFunctions')
Rules = @{
PSAvoidUsingCmdletAliases = @{
Whitelist = @('Where', 'Select')
}
}
}
"@
Set-Content -Path $analyzerSettingsPath -Value $analyzerSettingsContent
}
Write-Host "Module files generated successfully at: $modulePath" -ForegroundColor Green
}
# Initialize variables
$script:moduleName = ""
$script:moduleDescription = ""
$script:moduleAuthor = ""
$script:moduleVersion = ""
$script:moduleLicense = ""
$script:moduleProjectUri = ""
$script:publicFunctions = @()
$script:privateFunctions = @()
$script:moduleDependencies = @()
$script:usePSScriptAnalyzer = $false
$script:useplatyPS = $false
$script:usePester = $false
$script:useCodeCoverage = $false
# Main program loop
do {
Show-Menu
$choice = Read-Host "`nEnter your choice (1-8)"
switch ($choice) {
"1" { Set-ModuleDetails }
"2" { Add-PublicFunction }
"3" { Add-PrivateFunction }
"4" { Add-ModuleDependencies }
"5" { Set-BuildSettings }
"6" { Set-TestSettings }
"7" { Generate-ModuleFiles }
"8" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
}
if ($choice -ne "8") {
Read-Host "`nPress Enter to continue..."
}
} while ($choice -ne "8")
This Advanced Template Module Generator Tool includes:
- A menu-driven interface for easy navigation.
- Enhanced functions to:
- Set detailed module information (including license and project URI)
- Add public and private functions
- Specify module dependencies
- Configure build and test settings
Key features:
- Advanced Module Manifest Generation:
- Includes more detailed module information
- Supports specifying module dependencies
- Comprehensive Module Structure:
- Creates a more robust folder structure including build and test directories
- Enhanced Function File Generation:
- Generates more detailed function templates
- Build Script Generation:
- Creates a build.ps1 script for module building, testing, and documentation generation
- Test Configuration:
- Sets up Pester tests with placeholders for each public function
- Optionally includes code coverage settings
- PSScriptAnalyzer Integration:
- Generates a PSScriptAnalyzer settings file
- Includes PSScriptAnalyzer in the build process
- Documentation Support:
- Optionally sets up platyPS for documentation generation
- Dependency Management:
- Allows specifying module dependencies with version requirements
This tool is particularly useful for:
- Experienced PowerShell module developers
- Teams working on larger PowerShell projects
- Developers who want to follow best practices in module development
To use this script effectively:
- Run the script in PowerShell
- Use the menu options to:
- Set detailed module information
- Add public and private functions
- Specify dependencies and configure build/test settings
- Generate the module files
- Review the generated module structure and customize as needed
This advanced script provides a more comprehensive starting point for PowerShell module development, incorporating best practices and tools commonly used in professional PowerShell module projects.