Skip to content

Instantly share code, notes, and snippets.

@jborean93
Created August 23, 2024 04:39
Show Gist options
  • Save jborean93/886f3e6fef0c6e80e2eaff3ee42b2957 to your computer and use it in GitHub Desktop.
Save jborean93/886f3e6fef0c6e80e2eaff3ee42b2957 to your computer and use it in GitHub Desktop.
Invokes a PowerShell script as a scheduled task changing the logon type to a BATCH logon.
# Copyright: (c) 2024, Jordan Borean (@jborean93) <[email protected]>
# MIT License (see LICENSE or https://opensource.org/licenses/MIT)
Function Invoke-AsScheduledJob {
<#
.SYNOPSIS
Runs a scriptblock as a scheduled job.
.DESCRIPTION
This is a helper function to run PowerShell code as a scheduled task.
It uses the ScheduledJob module to manage the scheduled task interface
and deal with how data is serialized to and from the job.
.PARAMETER ScriptBlock
The PowerShell script to run.
.PARAMETER ArgumentList
Any arguments to provide positionally to the script when running.
.EXAMPLE
Invoke-AsScheduledJob { whoami /all }
.NOTES
The scheduled job will run as a scheduled task running as that user. This
is useful for running code that cannot be run as a NETWORK logon like the
Windows Update API.
Be careful about what data is provided as the ScriptBlock and ArgumentList,
the ScheduledJob module will store them in a file for when the job is
started.
As the ScheduledJob API was removed in PowerShell 7+, this function will
only work in Windows PowerShell (powershell.exe 5.1).
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, Position = 0)]
[scriptblock]
$ScriptBlock,
[Parameter(Position = 1, ValueFromRemainingArguments = $true)]
[PSObject[]]
$ArgumentList
)
$jobArgs = @{
Name = "Invoke-AsScheduledJob-$(New-Guid)"
ScriptBlock = $ScriptBlock
ScheduledJobOption = @{
RunElevated = $True
StartIfOnBatteries = $True
StopIfGoingOnBatteries = $False
}
}
if ($ArgumentList) {
$jobArgs.ArgumentList = $ArgumentList
}
$registeredJob = Register-ScheduledJob @jobArgs
try {
$registeredJob.RunAsTask()
$start = Get-Date
while (-not ($job = Get-Job -Name $jobArgs.Name -ErrorAction SilentlyContinue)) {
if (((Get-Date) - $start).TotalSeconds -gt 30) {
throw "Job did not start within 30 seconds"
}
Start-Sleep -Seconds 1
}
$job | Receive-Job -AutoRemoveJob -Wait
}
finally {
$registeredJob | Unregister-ScheduledJob
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment