Resources/Samples/Script-Complex.ps1

#requires -version 5
<#
.SYNOPSIS
    Complex PowerShell script with advanced features and proper structure.

.DESCRIPTION
    This script demonstrates complex PowerShell patterns including begin/process/end blocks,
    comprehensive error handling, pipeline support, and advanced parameter validation.

.PARAMETER InputObject
    Objects to process via pipeline or direct parameter input.

.PARAMETER Path
    File or directory path for processing.

.PARAMETER Action
    The action to perform on the input objects.

.PARAMETER Force
    Forces the operation without confirmation prompts.

.PARAMETER WhatIf
    Shows what would happen without actually performing the operation.

.INPUTS
    Objects can be piped to this script for processing.

.OUTPUTS
    PSCustomObject containing processing results and status information.

.NOTES
    Version: 1.0
    Author: Your Name
    Creation Date: $(Get-Date -Format 'yyyy-MM-dd')
    Purpose/Change: Initial complex script development

.EXAMPLE
    .\ScriptName.ps1 -Path "C:\Data" -Action "Process"
    Processes files in the specified directory.

.EXAMPLE
    Get-ChildItem "C:\Data" | .\ScriptName.ps1 -Action "Validate" -Verbose
    Processes piped objects with verbose output.

.LINK
    Related documentation or resources
#>


#region Script Parameters
[CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'Path')]
param (
    [Parameter(Mandatory = $false, Position = 0, ValueFromPipeline = $true, ParameterSetName = 'Pipeline')]
    [ValidateNotNull()]
    [object[]]$InputObject,

    [Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'Path')]
    [ValidateScript({
            if (-not (Test-Path $_)) {
                throw "Path '$_' does not exist."
            }
            return $true
        })]
    [string]$Path,

    [Parameter(Mandatory = $false)]
    [ValidateSet('Process', 'Validate', 'Report', 'Cleanup')]
    [string]$Action = 'Process',

    [Parameter(Mandatory = $false)]
    [switch]$Force
)
#endregion Script Parameters

begin {
    #region Initialization
    Set-StrictMode -Version Latest
    $ErrorActionPreference = 'Stop'
    $ProgressPreference = 'Continue'

    Write-Debug "Script started at $(Get-Date)"
    Write-Verbose "Parameter Set: $($PSCmdlet.ParameterSetName)"
    Write-Verbose "Action: $Action"

    # Initialize counters and collections
    $processedCount = 0
    $errorCount = 0
    $results = [System.Collections.Generic.List[PSCustomObject]]::new()

    # Validate prerequisites
    try {
        Write-Verbose "Validating script prerequisites..."

        # Add any required validation here
        if ($PSCmdlet.ParameterSetName -eq 'Path') {
            Write-Verbose "Validating path: $Path"
            if (-not (Test-Path $Path)) {
                throw "Specified path does not exist: $Path"
            }
        }

        Write-Verbose "Prerequisites validated successfully"
    }
    catch {
        Write-Error "Prerequisites validation failed: $($_.Exception.Message)"
        exit 1
    }
    #endregion Initialization
}

process {
    try {
        Write-Debug "Processing block started"

        # Determine input source
        $itemsToProcess = switch ($PSCmdlet.ParameterSetName) {
            'Pipeline' {
                Write-Verbose "Processing pipeline input"
                $InputObject
            }
            'Path' {
                Write-Verbose "Processing path input: $Path"
                Get-ChildItem -Path $Path -ErrorAction Stop
            }
        }

        # Process each item
        foreach ($item in $itemsToProcess) {
            try {
                Write-Debug "Processing item: $($item.Name ?? $item.ToString())"

                # Construct operation description for ShouldProcess
                $target = $item.Name ?? $item.ToString()
                $operation = "Perform $Action operation"

                if ($PSCmdlet.ShouldProcess($target, $operation)) {
                    # Main processing logic based on action
                    $result = switch ($Action) {
                        'Process' {
                            Write-Verbose "Processing item: $target"
                            [PSCustomObject]@{
                                Item = $target
                                Action = $Action
                                Status = 'Processed'
                                Timestamp = Get-Date
                                Details = "Successfully processed $target"
                            }
                        }
                        'Validate' {
                            Write-Verbose "Validating item: $target"
                            $isValid = $true  # Add validation logic here
                            [PSCustomObject]@{
                                Item = $target
                                Action = $Action
                                Status = if ($isValid) { 'Valid' } else { 'Invalid' }
                                Timestamp = Get-Date
                                Details = "Validation completed for $target"
                            }
                        }
                        'Report' {
                            Write-Verbose "Reporting on item: $target"
                            [PSCustomObject]@{
                                Item = $target
                                Action = $Action
                                Status = 'Reported'
                                Timestamp = Get-Date
                                Details = "Report generated for $target"
                            }
                        }
                        'Cleanup' {
                            Write-Verbose "Cleaning up item: $target"
                            if ($Force -or $PSCmdlet.ShouldContinue("Clean up $target?", "Confirm Cleanup")) {
                                [PSCustomObject]@{
                                    Item = $target
                                    Action = $Action
                                    Status = 'Cleaned'
                                    Timestamp = Get-Date
                                    Details = "Cleanup completed for $target"
                                }
                            } else {
                                [PSCustomObject]@{
                                    Item = $target
                                    Action = $Action
                                    Status = 'Skipped'
                                    Timestamp = Get-Date
                                    Details = "Cleanup skipped for $target"
                                }
                            }
                        }
                    }

                    # Add result to collection and output
                    $results.Add($result)
                    Write-Output $result
                    $processedCount++

                    # Update progress
                    if ($itemsToProcess.Count -gt 1) {
                        $percentComplete = [math]::Round(($processedCount / $itemsToProcess.Count) * 100, 2)
                        Write-Progress -Activity "Processing Items" -Status "Processed $processedCount of $($itemsToProcess.Count)" -PercentComplete $percentComplete
                    }
                }
                else {
                    Write-Verbose "Operation cancelled by user for: $target"
                }
            }
            catch {
                $errorCount++
                $errorResult = [PSCustomObject]@{
                    Item = $item.Name ?? $item.ToString()
                    Action = $Action
                    Status = 'Error'
                    Timestamp = Get-Date
                    Details = "Error: $($_.Exception.Message)"
                }

                $results.Add($errorResult)
                Write-Error "Failed to process item '$($item.Name ?? $item.ToString())': $($_.Exception.Message)"

                # Continue processing other items unless in strict mode
                if ($ErrorActionPreference -eq 'Stop') {
                    throw
                }
            }
        }
    }