Question:
I believe for Register-ScheduledTask
you can specify -User "System"
or do something like:
1 2 |
$principal = New-ScheduledTaskPrincipal -UserId SYSTEM -LogonType ServiceAccount -RunLevel Highest |
How do I do this with Register-ScheduledJob
?
This command will be running the context of the local admin so it will have access to do this. I just don’t see this option in the cmdlet.
Here is an example of how to do this with the scheduled tasks cmdlet
edit: Does windows make this impossible by design? If I open an interactive PS session as the system (using psexec) and try to create a schedualed job I get an error:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
PS C:\Windows\system32> Register-ScheduledJob -Name systemsssss -ScriptBlock {'s dfsdfsdfsd'} Register-ScheduledJob : An error occurred while registering scheduled job definition systemsssss to the Windows Task Scheduler. The Task Scheduler error is: (32,4):UserId:. At line:1 char:1 + Register-ScheduledJob -Name systemsssss -ScriptBlock {'sdfsdfsdfsd'} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (Microsoft.Power...edJobDefini tion:ScheduledJobDefinition) [Register-ScheduledJob], ScheduledJobExceptio n + FullyQualifiedErrorId : CantRegisterScheduledJobDefinition,Microsoft.Pow erShell.ScheduledJob.RegisterScheduledJobCommand |
This same command works fine when run as the local administrator account
Answer:
First use Register-ScheduledJob to create your PowerShell job.
Then use Set-ScheduledTask to change a startup account to the Local System or any other built-in accounts, i.e. SYSTEM
, LOCAL SERVICE
, NETWORK SERVICE
, etc.
Use the following PS-script. Or download it from my GitHub Gist
The code is self-explanatory (I believe).
You can run it multiple times under an administrative account if you want to check how it works.
BTW, I prefer to use jobs (Register-ScheduledJob
) over tasks because jobs allow me to embed PowerShell script blocks (strings) instead using of external script files. Look at -ScriptBlock
below.
Also pay attention to -RunElevated
. It is a must be.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
$ErrorActionPreference = 'Stop' Clear-Host #### Start of Main Logic ########################### $taskName = "my_PowerShell_job" $accountId = "NT AUTHORITY\SYSTEM"; #$accountId = "NT AUTHORITY\LOCAL SERVICE"; $task = Get-ScheduledJob -Name $taskName -ErrorAction SilentlyContinue if ($task -ne $null) { Unregister-ScheduledJob $task -Confirm:$false Write-Host " @ The old ""$taskName"" PowerShell job has been unregistered"; Write-Host; } # Uncomment the following exit command to only delete your job. # exit; # Shchedule your job. Using of -AtStartup as an example. $trigger = New-JobTrigger -AtStartup; $options = New-ScheduledJobOption -StartIfOnBattery -RunElevated; Write-Host " @ Registering of ""$taskName"" job"; Register-ScheduledJob -Name $taskName -Trigger $trigger -ScheduledJobOption $options ` -ScriptBlock { # Put your code here. Write-Host Your job has been launched!; } $principal = New-ScheduledTaskPrincipal -UserID $accountId ` -LogonType ServiceAccount -RunLevel Highest; $psJobsPathInScheduler = "\Microsoft\Windows\PowerShell\ScheduledJobs"; $someResult = Set-ScheduledTask -TaskPath $psJobsPathInScheduler ` -TaskName $taskName -Principal $principal #### End of Main Logic ########################### Write-Host; Write-Host " @ Let's look at running account of ""$taskName"" PowerShell job" $task = Get-ScheduledTask -TaskName $taskName $task.Principal Write-Host " @ Let's start ""$taskName"" manually" Start-Job -DefinitionName $taskName | Format-Table Write-Host " @ Let's proof that ""$taskName"" PowerShell job has been launched"; Write-Host; Start-Sleep -Seconds 3 Receive-Job -Name $taskName Write-Host; |