Public/New-PSScriptInfo.ps1
Function New-PSScriptInfo { <# .SYNOPSIS Generates PSScriptFileInfo metadata. .DESCRIPTION Generates PSScriptFileInfo metadata to the console, a new script file, or an existing script file. .PARAMETER Author The name of the script's author. .PARAMETER CompanyName The company name of the script's author. .PARAMETER Description A detailed description of the script's intended purpose. .PARAMETER SkipDescription Skips creation of the `Description` field in the script. This can be useful if a full help file already exists or is to be implemented. .PARAMETER OutputPath The path to which to export the script. Absolute and relative paths are both supported. .PARAMETER Force Forces an overwrite of an existing file. .PARAMETER PassThru Returns output to the console in addition to producing a file. .EXAMPLE # Outputs a script info block to the console New-PSScriptInfo -Description "My description." .EXAMPLE # Outputs a script info block to the console, omitting the description field New-PSScriptInfo -SkipDescription .EXAMPLE # Outputs a script info block to the console with a custon "Author Field" New-PSScriptInfo -Description "My description." -Author "John Smith" .EXAMPLE # Outputs a script info block to a new script file New-PSScriptInfo -Description "My description." -OutputPath "C:\Path\To\MyNewScript.ps1" .EXAMPLE # Outputs a script info block to an existing script file New-PSScriptInfo -Description "My description." -OutputPath "C:\Path\To\MyExistingScript.ps1" .EXAMPLE # Outputs a script info block to an existing script file Get-Item "C:\Path\To\MyExistingScript.ps1" | New-PSScriptInfo -SkipDescription .EXAMPLE # Outputs a script info block to all existing script files in a folder; each will contain a unique GUID Get-ChildItem "C:\Path\To\MyExistingScripts\*.ps1" -File | New-PSScriptInfo -SkipDescription .NOTES - PowerShell script files with the .ps1 extension are the only filetype supported. This is by design; .psm1 files should have an accompanying module manifest that contains the relevant metadata. #> [CmdletBinding(DefaultParameterSetName="Description")] PARAM ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [String]$Author, [Parameter(Mandatory=$false)] [ValidateNotNullOrEmpty()] [String]$CompanyName = $Author, [Parameter(Mandatory=$false)] [ValidateNotNullOrEmpty()] [String]$Version = "1.0.0", [Parameter(Mandatory=$true, Position=0, ParameterSetName="Description")] [ValidateNotNullOrEmpty()] [String]$Description, [Parameter(Mandatory=$false, ParameterSetName="SkipDescription")] [Switch]$SkipDescription, [Parameter(Mandatory=$false, Position=1, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [ValidateNotNullOrEmpty()] [Alias("Filename","FullName")] [String]$OutputPath ) # Create dynamic parameters DynamicParam { IF ($OutputPath) { # Create runtine dictionary $ParamDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new() # Define parameter attributes $Attribute = [System.Management.Automation.ParameterAttribute]@{ Mandatory = $false } # Create attribute collection $AttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]$Attribute # Create parameter object and add name, type, attribute collection $PassThruParameter = [System.Management.Automation.RuntimeDefinedParameter]::new('PassThru',[Switch],$AttributeCollection) $PassThruParameter.Value = $false $PSBoundParameters['PassThru'] = $PassThruParameter.Value # Add parameter to runtime dictionary $ParamDictionary.Add('PassThru',$PassThruParameter) # Create parameter object and add name, type, attribute collection $ForceParameter = [System.Management.Automation.RuntimeDefinedParameter]::new('Force',[Switch],$AttributeCollection) $ForceParameter.Value = $false $PSBoundParameters['Force'] = $ForceParameter.Value # Add parameter to runtime dictionary $ParamDictionary.Add('Force',$ForceParameter) return $ParamDictionary } } BEGIN { # Transfer Dynamic Parameters to runtime $PassThru = $PSBoundParameters['PassThru'] $Force = $PSBoundParameters['Force'] # Locally scope ErrorActionPreference for predictable behavior of Try/Catch blocks inside the function $ErrorActionPreference = 'Stop' # Determine Description based on Parameters supplied by the user $ScriptDescription = SWITCH ($SkipDescription) { $true {"Blank"} $false {$Description} } # Build parameter block for New-ScriptFileInfo command in PROCESS block $Params = @{ Version = "1.0.0" Author = $Author CompanyName = $CompanyName Copyright = "(c) $($(Get-Date).Year) $CompanyName" Description = $ScriptDescription } } PROCESS { # Create output variable $Results = '' #region Generate Script Info $ScriptInfo = SWITCH ($SkipDescription) { $true {(New-ScriptFileInfo @Params -PassThru).Split('>')[0]+'>' + "`r`n`r`n"} $false {(New-ScriptFileInfo @Params -PassThru).Replace('Param()','')} } IF ($OutputPath) { # Test whether output path is a file or directory SWITCH -Regex ($OutputPath) { # Test whether $OutputPath is a .ps1 file ".ps1$" { $OutputFilename = $OutputPath.Split('\')[-1] $OutputDirectory = $OutputPath.Substring(0,$OutputPath.LastIndexOf('\')) } Default { Write-Error "$OutputPath is not a .ps1 file. Please specify a valid filepath and try again." -ErrorAction Continue Continue } } # Create directory if it doesn't exist IF (!(Test-Path $OutputDirectory)) { TRY { New-Item -Path $OutputDirectory -ItemType File -Force | Out-Null } CATCH { Write-Warning "Unable to create directory $OutputDirectory. Defaulting to present working directory: $PWD" $OutputDirectory = $PWD } } # Try to get file contents ; on failure create file if it doesn't exist TRY { $FileContents = Get-Content $OutputPath -Raw } CATCH { TRY { Resolve-Path $OutputPath | Out-Null # If file exists and function is unable to retrieve contents, throw error Write-Error "Unable to retrieve contents for file $OutputPath. " -ErrorAction Continue Continue } CATCH { New-Item $OutputPath -ItemType File | Out-Null $FileContents = '' } } # Add ScriptInfo to beginning of file contents $Results = $ScriptInfo + $FileContents # Output file $Results | Out-File $OutputDirectory\$OutputFilename -Encoding ascii -Force:$Force } ELSE { $Results = $ScriptInfo } # Return results to the console if an output has not been specified or -Passthru has been selected IF(!$OutputPath -or $Passthru) { Write-Output $Results } } END { # Nothing to see here. Move along. } } |