I thought about this template and found two ways to do this. I have not found real applications in my practice, so the research is quite academic. But the scripts below work fine.
An existing tool that implements this template (in its own way) is scoop .
The pattern subcommand implements the classic command line interface
app <command> [parameters]
This template introduces one script app.ps1 , which provides commands instead of providing multiple scripts or functions in a script library or module. Each command is a script in a special subdirectory, for example .. / Command.
Get available teams
app
Call team
app c1 [parameters of Command\c1.ps1]
Get team help
app c1 -?
script app.ps1 may contain common functions used by commands.
splat.ps1 (app.ps1 as such) - template with splatting
Pros:
- Minimum code and service data.
- Positional parameters work.
-? works for reference as is (short help).
Minuses:
- PowerShell v3 + splatting works funny in v2.
dynamic.ps1 (app.ps1 as such) - a template with dynamic parameters
Pros:
- PowerShell v2 +.
- TabExpansion works for options.
Minuses:
- More code, more runtime.
- Named parameters only.
- Help as
-help .
Scenarios
splat.ps1
#requires -Version 3 param( $Command ) if (!$Command) { foreach($_ in Get-ChildItem $PSScriptRoot\Command -Name) { [System.IO.Path]::GetFileNameWithoutExtension($_) } return } & "$PSScriptRoot\Command\$Command.ps1" @args
dynamic.ps1
param( [Parameter()]$Command, [switch]$Help ) dynamicparam { ${private:*pn} = 'Verbose', 'Debug', 'ErrorAction', 'WarningAction', 'ErrorVariable', 'WarningVariable', 'OutVariable', 'OutBuffer', 'PipelineVariable' $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Definition $Command = $PSBoundParameters['Command'] if (!$Command) {return} $_ = Get-Command -Name "$PSScriptRoot\Command\$Command.ps1" -CommandType ExternalScript -ErrorAction 1 if (!($_ = $_.Parameters) -or !$_.Count) {return} ${private:*r} = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary (${private:*a} = New-Object System.Collections.ObjectModel.Collection[Attribute]).Add((New-Object System.Management.Automation.ParameterAttribute)) foreach($_ in $_.Values) { if (${*pn} -notcontains $_.Name) { ${*r}.Add($_.Name, (New-Object System.Management.Automation.RuntimeDefinedParameter $_.Name, $_.ParameterType, ${*a})) } } ${*r} } end { if (!$Command) { foreach($_ in Get-ChildItem $PSScriptRoot\Command -Name) { [System.IO.Path]::GetFileNameWithoutExtension($_) } return } if ($Help) { Get-Help "$PSScriptRoot\Command\$Command.ps1" -Full return } $null = $PSBoundParameters.Remove('Command') & "$PSScriptRoot\Command\$Command.ps1" @PSBoundParameters }
source share