Public/New-pseScheduledTask.ps1

Function New-pseScheduledTask {

    [cmdletbinding()]

    Param (
        [parameter (mandatory = $false)]
        [string]$Taskname,

        [parameter (mandatory = $true)]
        [string]$Description,

        [parameter (mandatory = $false)]
        [string]$TaskFolder = 'PSEngine',

        [parameter (mandatory = $true)]
        [string]$Path,

        [parameter (mandatory = $false)]
        [string]$Arguments,

        [parameter (mandatory = $false)]
        [string]$StartIn,

        [parameter (mandatory = $false)]
        [ValidateSet('AtLogon', 'AtStartup', 'Daily')]
        [string]$Trigger = 'AtStartUp',

        [parameter (mandatory = $false)]
        [ValidateSet('BUILTIN\Users', 'NT AUTHORITY\SYSTEM', 'BUILTIN\Administrators')]
        [string]$RunAs = 'NT AUTHORITY\SYSTEM',

        [parameter (mandatory = $false)]
        [int]$DelayTaskByXMinutes,

        [parameter (mandatory = $false)]
        $RepeatEveryXMinutes,

        [switch]$RunWithHighestPrivilege,

        [switch]$StartTaskImmediately,

        [switch]$IgnoreTestPath,

        [switch]$TurnOffExecutionTimeLimit
    )

    DynamicParam {
        if ($Trigger -eq 'Daily') {
            # Define parameter attributes
            $paramAttributes = New-Object -Type System.Management.Automation.ParameterAttribute
            $paramAttributes.Mandatory = $true

            # Create collection of the attributes
            $paramAttributesCollect = New-Object -Type `
                System.Collections.ObjectModel.Collection[System.Attribute]
            $paramAttributesCollect.Add($paramAttributes)

            # Create parameter with name, type, and attributes
            $dynParam1 = New-Object -Type `
                System.Management.Automation.RuntimeDefinedParameter("RandomiseTaskUpToXMinutes", [int], $paramAttributesCollect)
            $dynParam2 = New-Object -Type `
                System.Management.Automation.RuntimeDefinedParameter("Time", [string], $paramAttributesCollect)

            # Add parameter to parameter dictionary and return the object
            $paramDictionary = New-Object -Type System.Management.Automation.RuntimeDefinedParameterDictionary
            $paramDictionary.Add("RandomiseTaskUpToXMinutes", $dynParam1)
            $paramDictionary.Add("Time", $dynParam2)
            return $paramDictionary
        }
    }

    Begin {
        # Assign dynamic parameters to variables so they can be tested if they were used later in the script.
        $RandomiseTaskUpToXMinutes = $PSBoundParameters['RandomiseTaskUpToXMinutes']
        $Time = $PSBoundParameters['Time']

    }

    Process {

        if ($Trigger -eq 'Daily' -and $RandomiseTaskUpToXMinutes -and $DelayTaskByXMinutes) {
            Write-Error "Please do not use '-DelayTaskByXMinutes' with '-randomiseTaskUpToXminutes'"
        }

        # Path check
        $pathExists = Test-Path $Path -PathType Leaf

        if ($IgnoreTestPath) {
            Write-Host "Skipping path verification due to -IgnoreTestPath switch" -ForegroundColor DarkGray
        }

        if ($pathExists -eq $false -and $IgnoreTestPath -eq $false) {
            Write-Host "The path $path does not exist. Please use the -IgnoreTestPath switch to override this error." -ForegroundColor DarkYellow
            return
        }

        # If -TaskName was not used, then get the leaf name of the path to use instead
        if ([string]::IsNullOrEmpty($taskname)) {
            $TaskName = Get-pseLeafName -filePath $path
        }

        # Check if the task already exists
        try {
            Get-pseScheduledTask -TaskName $TaskName -ea stop | out-null
            Write-Host "The task $TaskName already exists. Please use a different name." -ForegroundColor DarkYellow
            return
        } catch {
            Write-Host "Task $taskname not found - OK to proceed." -ForegroundColor DarkGray
        }

        # Create the scheduled task action
        try {
            $taskAction = New-pseScheduledTaskAction -IsPs1Script (Test-psePS1Extension -filePath $Path) -path $Path -arguments $Arguments -startin $StartIn -ea stop
        } catch {
            Write-Error "New-pseScheduledTaskAction error: $_"
        }

        # Create the task trigger
        try {
            if ($Trigger -eq 'daily') {
                Write-Host "The '-daily' trigger has been selected" -ForegroundColor DarkGray
                $taskTrigger = New-pseScheduledTaskTrigger -trigger $Trigger -time $Time -RandomiseTaskUpTo $RandomiseTaskUpToXMinutes -RepeatEveryXMinutes $RepeatEveryXMinutes -ea stop
            } else {
                $taskTrigger = New-pseScheduledTaskTrigger -trigger $Trigger -DelayTaskUpToXMinutes $DelayTaskByXMinutes -RepeatEveryXMinutes $RepeatEveryXMinutes -ea stop
            }
        } catch {
            Write-Error "New-pseScheduledTaskTrigger error: $_"
        }


        # Set the task run level
        try {
            if ($RunWithHighestPrivilege.IsPresent) {
                Write-Host "The '-RunWithHighestPrivilege' switch has been selected" -ForegroundColor DarkGray
                $taskPrincipal = New-pseScheduledTaskPrincipal -RunAs $RunAs -RunWithHighestPrivilege -ea stop
            } else {
                $taskPrincipal = New-pseScheduledTaskPrincipal -RunAs $RunAs -ea stop
            }
        } catch {
            Write-Error "New-pseScheduledTaskPrincipal error: $_ "
        }

        # Set the task settings
        try {
            if ($TurnOffExecutionTimeLimit.IsPresent) {
                $taskSettings = New-pseScheduledTaskSettingsSet -TurnOffExecutionTimeLimit -ea stop
            } else {
                $taskSettings = New-pseScheduledTaskSettingsSet -ea stop
            }
        } catch {
            Write-Error "New-pseScheduledTaskSettingsSet error: $_"
        }

        # Create the scheduled task
        $params = @{
            TaskName    = $TaskName
            Description = $Description
            TaskPath    = "\$TaskFolder"
            Action      = $taskAction
            Trigger     = $taskTrigger
            Principal   = $taskPrincipal
            Settings    = $taskSettings
        }

        try {
            Create-pseScheduledTask @params -ea stop | Out-Null
        } catch {
            Write-Error "Create-pseScheduledTask: $_"
        }


        # Start the task immediately if the -StartTaskImmediately switch was used
        if ($StartTaskImmediately.IsPresent) {
            try {
                Write-Host "Starting task $TaskName"
                Start-ScheduledTask -TaskName $TaskName -TaskPath "\$TaskFolder" -ea stop -ev x
                Write-Host "Task $TaskName started successfully." -ForegroundColor DarkGreen
            } catch {
                Write-Error "Start-ScheduledTask: An error occured starting the task: $x"
            }
        }
    }
}