Noveris.Tasker.psm1

<#
#>


################
# Global settings
$ErrorActionPreference = "Stop"
Set-StrictMode -Version 2.0

################
# Script variables

Class TaskerSettings
{
    [System.Collections.Hashtable]$Variables

    [ScriptBlock]$DefaultBlock
    [ScriptBlock]$ErrorBlock
    [ScriptBlock]$WarningBlock
    [ScriptBlock]$VerboseBlock
    [ScriptBlock]$DebugBlock
    [ScriptBlock]$InformationBlock

    TaskerSettings()
    {
        $this.Variables = @{}

        $this.DefaultBlock = $null
        $this.ErrorBlock = $null
        $this.WarningBlock = $null
        $this.VerboseBlock = $null
        $this.DebugBlock = $null
        $this.InformationBlock = $null
    }
}

<#
#>

Function New-TaskerSettings
{
    [CmdletBinding()]
    param(
    )

    $prefs = New-Object TaskerSettings

    $prefs
}

<#
#>

Function Update-TaskerSettings
{
    [CmdletBinding(DefaultParameterSetName="default")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipeline,ParameterSetName="default")]
        [Parameter(Mandatory=$true,ValueFromPipeline,ParameterSetName="SetVariable")]
        [Parameter(Mandatory=$true,ValueFromPipeline,ParameterSetName="RemoveVariable")]
        [TaskerSettings]$Settings,

        [Parameter(Mandatory=$false,ParameterSetName="default")]
        [string]$InformationPreference,

        [Parameter(Mandatory=$false,ParameterSetName="default")]
        [string]$ErrorActionPreference,

        [Parameter(Mandatory=$false,ParameterSetName="default")]
        [string]$DebugPreference,

        [Parameter(Mandatory=$false,ParameterSetName="default")]
        [string]$VerbosePreference,

        [Parameter(Mandatory=$true,ParameterSetName="SetVariable")]
        [string]$SetVariable,

        [Parameter(Mandatory=$true,ParameterSetName="RemoveVariable")]
        [string]$RemoveVariable,

        [Parameter(Mandatory=$true,ParameterSetName="SetVariable")]
        [AllowEmptyString()]
        $Value,

        [Parameter(Mandatory=$false,ParameterSetName="default")]
        [AllowNull()]
        [ScriptBlock]$DefaultBlock,

        [Parameter(Mandatory=$false,ParameterSetName="default")]
        [AllowNull()]
        [ScriptBlock]$ErrorBlock,

        [Parameter(Mandatory=$false,ParameterSetName="default")]
        [AllowNull()]
        [ScriptBlock]$WarningBlock,

        [Parameter(Mandatory=$false,ParameterSetName="default")]
        [AllowNull()]
        [ScriptBlock]$VerboseBlock,

        [Parameter(Mandatory=$false,ParameterSetName="default")]
        [AllowNull()]
        [ScriptBlock]$DebugBlock,

        [Parameter(Mandatory=$false,ParameterSetName="default")]
        [AllowNull()]
        [ScriptBlock]$InformationBlock
    )

    if ($Settings -eq $null)
    {
        throw New-Object ArgumentException -ArgumentList "Null Settings value passed to Update-TaskerSettings"
    }

    foreach ($param in $PSBoundParameters.Keys)
    {
        switch ($param)
        {
            "InformationPreference" {
                $null = $Settings.Variables["InformationPreference"] = $InformationPreference
                break
            }

            "ErrorActionPreference" {
                $null = $Settings.Variables["ErrorActionPreference"] = $ErrorActionPreference
                break
            }

            "DebugPreference" {
                $null = $Settings.Variables["DebugPreference"] = $DebugPreference
                break
            }

            "VerbosePreference" {
                $null = $Settings.Variables["VerbosePreference"] = $VerbosePreference
                break
            }

            "SetVariable" {
                $null = $Settings.Variables[$SetVariable] = $Value
                break
            }

            "RemoveVariable" {
                if ($Settings.Variables.ContainsKey($RemoveVariable))
                {
                    $null = $Settings.Variables.Remove($RemoveVariable)
                }

                break
            }

            "DefaultBlock" {
                $Settings.DefaultBlock = $DefaultBlock
                break
            }

            "ErrorBlock" {
                $Settings.ErrorBlock = $ErrorBlock
                break
            }

            "WarningBlock" {
                $Settings.WarningBlock = $WarningBlock
                break
            }

            "VerboseBlock" {
                $Settings.VerboseBlock = $VerboseBlock
                break
            }

            "DebugBlock" {
                $Settings.DebugBlock = $DebugBlock
                break
            }

            "InformationBlock" {
                $Settings.InformationBlock = $InformationBlock
                break
            }
        }
    }
}

<#
#>

Function Format-TaskerRun {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true,ValueFromPipeline)]
        $Content,

        [Parameter(Mandatory=$true)]
        [TaskerSettings]$Settings
    )
    
    process {
        if ([System.Management.Automation.InformationRecord].IsAssignableFrom($Content.GetType()) -and
            $Settings.InformationBlock -ne $null)
        {
            Write-Verbose "Writing as InformationBlock"
            $Content | ForEach-Object $Settings.InformationBlock
            return
        }

        if ([System.Management.Automation.VerboseRecord].IsAssignableFrom($Content.GetType()) -and
            $Settings.VerboseBlock -ne $null)
        {
            Write-Verbose "Writing as VerboseBlock"
            $Content | ForEach-Object $Settings.VerboseBlock
            return
        }

        if ([System.Management.Automation.WarningRecord].IsAssignableFrom($Content.GetType()) -and
            $Settings.WarningBlock -ne $null)
        {
            Write-Verbose "Writing as WarningBlock"
            $Content | ForEach-Object $Settings.WarningBlock
            return
        }

        if ([System.Management.Automation.DebugRecord].IsAssignableFrom($Content.GetType()) -and
            $Settings.DebugBlock -ne $null)
        {
            Write-Verbose "Writing as DebugBlock"
            $Content | ForEach-Object $Settings.DebugBlock
            return
        }

        if ([System.Management.Automation.ErrorRecord].IsAssignableFrom($Content.GetType()) -and
            $Settings.ErrorBlock -ne $null)
        {
            Write-Verbose "Writing as ErrorBlock"
            $Content | ForEach-Object $Settings.ErrorBlock
            return
        }

        if ($Settings.DefaultBlock -ne $null)
        {
            Write-Verbose "Writing as DefaultBlock"
            $Content | ForEach-Object $Settings.DefaultBlock
            return
        }

        Write-Verbose "Writing without ScriptBlock"
        $Content
    }
}

<#
#>

Function Invoke-TaskerScript
{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [TaskerSettings]$Settings,

        [Parameter(Mandatory=$true)]
        [ScriptBlock]$ScriptBlock,

        [Parameter(Mandatory=$false)]
        $Params,

        [Parameter(Mandatory=$false,ValueFromPipeline)]
        $InputObject = $null,

        [Parameter(Mandatory=$false)]
        [switch]$RethrowException = $false
    )

    process
    {
        if ($Settings -eq $null)
        {
            throw New-Object ArgumentException -ArgumentList "Null Settings passed to Invoke-TaskerScript"
        }
    
        if ($ScriptBlock -eq $null)
        {
            throw New-Object ArgumentException -ArgumentList "Null ScriptBlock passed to Invoke-TaskerScript"
        }

        # Determine whether to pass an input object to script block
        $passInputObject = $false
        if ($PSBoundParameters.Keys.Contains("InputObject"))
        {
            $passInputObject = $true
        }

        # Create a new scope, define variables and then call new script block,
        # which inherits variables from the outer script block scope.
        $i = 0
        $variables = New-Object 'System.Collections.ArrayList' -ArgumentList $Settings.Variables

        & {
            # Create new variables in local scope for the script block to inherit
            for ( ; (Get-Variable -Scope 1 -Name i).Value -lt (Get-Variable -Scope 1 -Name variables).Value.Count ;
                (Set-Variable -Scope 1 -Name i -Value ((Get-Variable -Scope 1 -Name i).Value+1)))
            {
                Set-Variable -Name (Get-Variable -Scope 1 -Name variables).Value[(Get-Variable -Scope 1 -Name i).Value].Name -Value (Get-Variable -Scope 1 -Name variables).Value[(Get-Variable -Scope 1 -Name i).Value].Value
            }

            try {
                if ((Get-Variable -Scope 1 -name passInputObject).Value)
                {
                    # Use ForEach-Object to pass underBar to script block
                    # Redirect all streams to success stream
                    (Get-Variable -Scope 1 -Name InputObject).Value | ForEach-Object (Get-Variable -Scope 1 -Name ScriptBlock).Value *>&1
                }
                else
                {
                    # Use call operator, if underbar is not required
                    # Redirect all streams to success stream
                    &((Get-Variable -Scope 1 -Name ScriptBlock).Value) *>&1
                }
            } catch {
                # If an error is generated, pass this exception through the pipeline
                if ((Get-Variable -Scope 1 -Name RethrowException).Value)
                {
                    throw $_
                }

                $_
            }
        }
    }
}