Public/New-LocalLogonTask.ps1

function New-LocalLogonTask {
    <#
        .SYNOPSIS
            Creates a new scheduled task that runs on user logon.
 
        .DESCRIPTION
            Creates a new Windows Scheduled Task that executes when users log on:
            - Configures task with specified name and description
            - Sets up logon trigger for execution
            - Supports hidden tasks
            - Allows command arguments
            - Implements security best practices
            - Provides detailed logging
 
            The task is created using the Schedule.Service COM object and configured
            to run with standard user privileges.
 
        .PARAMETER Name
            [String] Name of the scheduled task.
            Must be unique within the Task Scheduler.
            Used to identify the task in Task Scheduler.
 
        .PARAMETER Description
            [String] Detailed description of the task's purpose.
            Appears in Task Scheduler properties.
 
        .PARAMETER Author
            [String] Name of the task creator.
            Used for administrative tracking.
 
        .PARAMETER Command
            [String] Full path to the executable or script to run.
            Must be accessible to the executing user.
 
        .PARAMETER CommandArguments
            [String] Optional arguments passed to the command.
            Default: None
 
        .PARAMETER Hidden
            [Switch] If specified, hides the task from Task Scheduler UI.
            Default: Task is visible
 
        .EXAMPLE
            New-LocalLogonTask -Name "UpdateProfile" `
                            -Description "Updates user profile at logon" `
                            -Author "IT Department" `
                            -Command "C:\Scripts\Update-Profile.ps1"
 
            Creates a visible logon task that runs a PowerShell script.
 
        .EXAMPLE
            $params = @{
                Name = "SecurityScan"
                Description = "Runs security scan at logon"
                Author = "Security Team"
                Command = "C:\Program Files\Scanner\scan.exe"
                CommandArguments = "/quiet /full"
                Hidden = $true
            }
            New-LocalLogonTask @params
 
            Creates a hidden logon task with command arguments.
 
        .OUTPUTS
            [void]
 
        .NOTES
            Used Functions:
                Name ║ Module/Namespace
                ══════════════════════════════════════╬════════════════════════
                Get-FunctionDisplay ║ EguibarIT
                Write-Verbose ║ Microsoft.PowerShell.Utility
                Write-Error ║ Microsoft.PowerShell.Utility
 
        .NOTES
            Version: 1.1
            DateModified: 31/Mar/2024
            LastModifiedBy: Vicente Rodriguez Eguibar
                            vicente@eguibar.com
                            Eguibar IT
                            http://www.eguibarit.com
 
        .LINK
            https://github.com/vreguibar/EguibarIT
        .LINK
            https://learn.microsoft.com/en-us/windows/win32/taskschd/task-scheduler-objects
    #>


    [CmdletBinding(
        SupportsShouldProcess = $true,
        ConfirmImpact = 'Medium'
    )]
    [OutputType([void])]

    Param
    (
        # Param1 help description
        [Parameter(Mandatory = $true,
            HelpMessage = 'Name of the scheduled task',
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            ValueFromRemainingArguments = $false,
            Position = 0)]
        [ValidateNotNullOrEmpty()]
        [string]
        $name,

        # Param2 help description
        [Parameter(Mandatory = $true,
            HelpMessage = 'Description of the task',
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            ValueFromRemainingArguments = $false,
            Position = 1)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Description,

        # Param3 help description
        [Parameter(Mandatory = $true,
            HelpMessage = 'Author of the task',
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            ValueFromRemainingArguments = $false,
            Position = 2)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Author,

        # Param4 help description
        [Parameter(Mandatory = $true,
            HelpMessage = 'Command to execute',
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            ValueFromRemainingArguments = $false,
            Position = 3)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Command,

        # Param5 help description
        [Parameter(Mandatory = $false,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            ValueFromRemainingArguments = $false,
            HelpMessage = 'Optional command arguments',
            Position = 4)]
        [string]
        $CommandArguments,

        # Param6 help description
        [Parameter(Mandatory = $false,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            ValueFromRemainingArguments = $false,
            HelpMessage = 'Hide task from Task Scheduler UI',
            Position = 5)]
        [switch]
        $Hidden
    )

    Begin {
        Set-StrictMode -Version Latest

        # Initialize logging
        if ($null -ne $Variables -and
            $null -ne $Variables.Header) {

            $txt = ($Variables.Header -f
                (Get-Date).ToString('dd/MMM/yyyy'),
                $MyInvocation.Mycommand,
                (Get-FunctionDisplay -HashTable $PsBoundParameters -Verbose:$False)
            )
            Write-Verbose -Message $txt
        } #end If

        ##############################
        # Module imports

        ##############################
        # Variables Definition

    } #end Begin

    Process {
        # https://msdn.microsoft.com/en-us/library/windows/desktop/aa383607(v=vs.85).aspx
        try {

            if ($PSCmdlet.ShouldProcess($Name, 'Create logon task')) {
                Write-Debug -Message ('Creating task service object for {0}' -f $Env:COMPUTERNAME)

                # Create the TaskService object
                $service = [Type]::GetTypeFromProgID('Schedule.Service')
                $taskService = [Activator]::CreateInstance($service)
                $taskService.Connect($Env:COMPUTERNAME)
                $rootFolder = $taskService.GetFolder('\')

                $taskDefinition = $service.NewTask(0)

                # Set registration info using direct property access
                Write-Debug -Message 'Configuring task registration info'
                $taskDefinition.RegistrationInfo.Description = $Description
                $taskDefinition.RegistrationInfo.Author = $Author

                # Configure settings using direct property access
                Write-Debug -Message 'Configuring task settings'
                $taskDefinition.Settings.Enabled = $true
                $taskDefinition.Settings.StartWhenAvailable = $true
                $taskDefinition.Settings.Hidden = $Hidden.IsPresent

                # Create logon trigger using method calls
                Write-Debug -Message 'Creating logon trigger'
                $trigger = $taskDefinition.Triggers.Create(9) # TriggerTypeLogon
                $trigger.Id = 'LogonTriggerId'
                $trigger.Enabled = $true

                # Trigger variables that define when the trigger is active
                $trigger.StartBoundary = '2014-10-0T22:00:00'
                #$trigger.DaysInterval = 1
                $trigger.Id = 'LogonTriggerId'
                $trigger.Enabled = $true

                # Create action using method calls
                Write-Debug -Message ('Creating task action: {0}' -f $Command)
                $action = $taskDefinition.Actions.Create(0)
                $action.Path = $Command
                if ($PSBoundParameters.ContainsKey('CommandArguments')) {
                    $action.Arguments = $CommandArguments
                } #end If

                # Register task
                Write-Debug -Message ('Registering task: {0}' -f $Name)
                $rootFolder.RegisterTaskDefinition(
                    $Name,
                    $taskDefinition,
                    6, # Create or update
                    $null, # No user
                    $null, # No password
                    0         # Run only when user is logged on
                )

                Write-Verbose -Message ('Successfully created task: {0}' -f $Name)

            } #end If
        } catch {
            Write-Error -Message ('Failed to create logon task {0}: {1}' -f $Name, $_.Exception.Message)
            throw
        }
    } #end Process

    End {
        if ($null -ne $Variables -and
            $null -ne $Variables.Footer) {

            $txt = ($Variables.Footer -f $MyInvocation.InvocationName,
                'creating new task.'
            )
            Write-Verbose -Message $txt
        } #end If
    } #end End

} #end Process New-LocalLogonTask