task.ps1

function Register-LogonTask {
    <#
    .SYNOPSIS
        Registers a task to run at user logon.

    .DESCRIPTION
        Registers a scheduled task that runs when the current user logs in. The task starts when available,
        runs on batteries and is given no execution time limit.
        An existing task is left untouched unless -Force is given.
        The task runs with the privileges the user logs on with, unless -Elevated is given.

    .PARAMETER Name
        Name of the task.

    .PARAMETER Executable
        The location of the executable to run.

    .PARAMETER Argument
        The argument to pass to the executable.

    .PARAMETER Path
        Path in the task scheduler. Default: root path ("\").

    .PARAMETER Elevated
        If specified, the task runs with the highest privileges available to the user,
        as "Run with highest privileges" in the task scheduler.

    .PARAMETER Force
        If specified, overwrites the task if it already exists.

    .OUTPUTS
        Nothing.

    .EXAMPLE
        Register-LogonTask -Name "MyTask" -Executable "C:\MyFolder\MyExecutable.exe"

    .EXAMPLE
        Register-LogonTask -Name "MyTask" -Path "\MyFolder" -Executable "C:\MyFolder\MyExecutable.exe" -Argument "MyArgument"

    .EXAMPLE
        Register-LogonTask -Name "MyTask" -Executable "C:\MyFolder\MyExecutable.exe" -Elevated

    .NOTES
        Alias for -Elevated: -Administrator
        A task of the current user needs no administrator privileges. An -Elevated task does:
        it auto-elevates through Invoke-Elevated (sudo --inline) when the session is not already elevated.
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param (
        [Parameter(Mandatory)]
        [string] $Name,
        [Parameter(Mandatory)]
        [string] $Executable,
        [string] $Argument,
        [string] $Path = "\",
        [Alias("Administrator")]
        [switch] $Elevated,
        [switch] $Force
    )

    # -Elevated asks for a run level only an administrator registers,
    # so an unelevated session hands the registration over to an elevated one
    $elevates = $Elevated -and -not (Test-Elevated)

    if ($elevates) { Assert-SudoAvailable }

    # trailing backslash at root only
    $taskLocation = $Path.EndsWith("\") ? "$Path$Name" : "$Path\$Name"

    # New-ScheduledTaskAction rejects blank -Argument, so passed only where there is one
    $actionArgument = $Argument ? @{ Argument = $Argument } : @{}

    $action = New-ScheduledTaskAction -Execute $Executable @actionArgument
    $trigger = New-ScheduledTaskTrigger -AtLogOn -User "${env:USERDOMAIN}\${env:USERNAME}"
    $settings = New-ScheduledTaskSettingsSet `
        -StartWhenAvailable `
        -AllowStartIfOnBatteries `
        -DontStopIfGoingOnBatteries `
        -ExecutionTimeLimit (New-TimeSpan)

    # default principal: current user, interactive, limited run level
    # principal built for Highest run level alone
    $elevatedPrincipal = $Elevated `
        ? @{ Principal = New-ScheduledTaskPrincipal `
                -UserId "${env:USERDOMAIN}\${env:USERNAME}" `
                -LogonType Interactive `
                -RunLevel Highest
        } `
        : @{}

    $task = New-ScheduledTask `
        -Trigger $trigger `
        -Action $action `
        -Settings $settings `
        @elevatedPrincipal

    if ($PSCmdlet.ShouldProcess($taskLocation, "Register logon task")) {
        # task built here, handed over as XML, so the elevated session runs
        # the task scheduler's own command, resolvable anywhere
        if ($elevates) {
            $command = @(
                "Register-ScheduledTask"
                "-TaskName", $Name
                "-TaskPath", $Path
                "-Xml", ($task | Export-ScheduledTask)
            )
            if ($Force) { $command += "-Force" }
            # registered task written through by elevated session, dropped as in-process
            Invoke-Elevated $command | Out-Null
            return
        }

        Register-ScheduledTask `
            -TaskName $Name `
            -TaskPath $Path `
            -InputObject $task `
            -Force:$Force `
            -ErrorAction Stop `
        | Out-Null
    }
}