I've registered a new startup job as follows
$trigger = New-JobTrigger -AtStartup -RandomDelay 00:00:30
$option = New-ScheduledJobOption -RunElevated –ContinueIfGoingOnBattery
Register-ScheduledJob -Name startup_test -FilePath C:\startup.ps1 -Trigger $trigger -ScheduledJobOption $option
My startup.ps1 script is as follows
New-Item c:\test_startup_success.txt -type file
When I restart the windows server 2012 R2 core, it doesn't create the file. Have restarted using
shutdown /r
But if I use test it using, it created the file
Start-Job -DefinitionName startup_test
Is there anything that I'm missing which needs to be done specifically for startup jobs?
Update:
I executed the following command to see if the job failed, but the output was empty.
Get-WinEvent -LogName Microsoft-Windows-TaskScheduler/Operational | Where {$_.Message -like "*fail*"}
My wild guess is that the job itself is not getting executed. Some condition is probably not getting satisfied. Even the Job trigger is enabled
PS C:\Windows\System32\WindowsPowerShell\v1.0> Get-ScheduledJob | Get-JobTrigger
Id Frequency Time DaysOfWeek Enabled
-- --------- ---- ---------- -------
1 AtStartup True
Related
I'm at my wits end trying to get a scheduled task to persist after a Windows Server 2019 reboot. I'm using powershell to create the scheduled task.
It triggers just fine and I can see it running before the reboot. Then the Server adds the ADDS component and Forest and reboots. After the reboot, no matter what I try, I can't get the scheduled task to start properly again.
Note that this exact code below works just fine on Windows 10 for adding a scheduled task to restart itself after a reboot. Any help appreciated. Are there some settings that need to be here for Windows Server that differ for Win10?
Here is the error description: After the reboot, in the task summary, it says "The last run of the task was terminated by the user" with last run time right before the reboot. The next run time keeps on incrementing every minute. In the History the error is, "Task Scheduler Failed to Start" with "Additional Data: Error Value: 2147943726."
# Create a scheduled task action
$sta = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-NoProfile -WindowStyle Hidden -command "C:\Terraform\ImportUsers.ps1"'
# Create a schedule task trigger
$stt = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionDuration (New-TimeSpan -Days 1) -RepetitionInterval (New-TimeSpan -Minutes 1)
# Create a new scheduled task setting
$sts = New-ScheduledTaskSettingsSet -StartWhenAvailable -RestartInterval (New-TimeSpan -Minutes 1) -RestartCount 3
# Set it to Stop the existing instance (for proper startup after reboot)
$sts.CimInstanceProperties.Item('MultipleInstances').Value = 3
# Register new scheduled task
Register-ScheduledTask ImportDomainUser01 -Action $sta -Settings $sts -Trigger $stt -User "LocalAdmin" -Password "LocalAdminPassword"
I was able to get this working using powershell scheduled jobs instead of a traditional scheduled task. This solution below persists across a reboot on Windows Server 2019:
$jt = New-JobTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 1) -RepetitionDuration (New-Timespan -Hours 48)
Register-ScheduledJob -Name ImportUsers01 -ScriptBlock { C:\script.ps1 } -Trigger $jt
I have a script that sets up the (AWS) instance (joins domain, hardening etc).
Part of it (load GPO backups, create OUs and users) needs to run after a reboot, so I figured I create a scheduled task for it.
But I can't get it to get the access it needs!
$psexe = Join-Path $PSHOME powershell.exe
$T = New-ScheduledTaskTrigger -AtStartup
$P = New-ScheduledTaskPrincipal -UserId "NT AUTHORITY\SYSTEM" -RunLevel Highest -LogonType ServiceAccount
$S = New-ScheduledTaskSettingsSet
$A = New-ScheduledTaskAction -Execute $psexe -Argument "-NoProfile -NonInteractive -NoLogo -ExecutionPolicy Unrestricted -File C:\Windows\Temp\install_gpo.ps1"
$D = New-ScheduledTask -Action $A -Principal $P -Trigger $T -Settings $S
Register-ScheduledTask -TaskName "Install GPO" -InputObject $D -ErrorAction Ignore
The script itself is fairly simple:
Start-Transcript -path C:\log-install_gpo.txt
Import-GPO -BackupGpoName LogonBanner -TargetName LogonBanner -Path C:\Windows\Temp\GpoBackups -CreateIfNeeded
gpupdate
Stop-Transcript
Running the task (!) manually from the task scheduler GUI and looking at the log file, I see:
Username: DOMAIN\SYSTEM
RunAs User: DOMAIN\SYSTEM
[...]
Import-GPO : Access is denied. (Exception from HRESULT: 0x80070005
(E_ACCESSDENIED))
At C:\Windows\Temp\install_gpo.ps1:2 char:1
+ Import-GPO -BackupGpoName LogonBanner -TargetName LogonBanner -Path C ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Import-GPO], UnauthorizedAcce
ssException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.Gro
upPolicy.Commands.ImportGpoCommand
So it seems that the 'System' user doesn't have access to do what I want/need! Not sure why that is, I specify the highest RunLevel and Unrestricted execution policy..
Running the Import-GPO command in an elevated PS shell works just fine!
I can't run it as Administrator, because that would require a password (that doesn't work anyway, Register-ScheduledTask refuses to accept that on the command line), I can't specify both -UserID and -GroupID (...\Administrator for example) at the same time.
I've tried using the RunOnce registry key, but that seem to work even less. Also, if I understand the docs for that correctly, it is only run when a/any user logs in, which might never happen! This is (supposed to be) a "headless server" so no-one should ever login to it..
I'm at a loss to what to try next.
I'm automating builds of windows servers in AWS (via packer and terraform). I have a userdata script that changes the hostname when host is started and reboots after.
My problem is that, after the system reboots, I need a software installation to happen (because it relies on the changed name.)
I've tried something like this:
$RunOnceKey = "HKLM:\Software\Microsoft\Windows\CurrentVersion\RunOnce"
set-itemproperty $RunOnceKey "NextRun" ('C:\Windows\System32\WindowsPowerShell\v1.0\Powershell.exe -executionPolicy Unrestricted -File ' + "C:\mydir\after-boot\install_mysoftware.ps1")
The problem with this is that it only runs after a user login, which is unacceptable.
So I read about RunServiceOnce, but when I try to use that in place of RunOnce, I get an error:
set-itemproperty : Cannot find path 'C:\Users\Administrator\HKLM\Software\Microsoft\Windows\CurrentVersion\RunServicesOnce'
because it does not exist
How can I ensure my program runs once on system boot without waiting for a user login? Point/click won't work. I need a powershell solution to set this up.
Since it is windows server, you can also schedule task in Windows Task Scheduler.
EXAMPLE:
$destination = "C:\Windows\Tasks\InstallSoftware.ps1"
$action = New-ScheduledTaskAction -Execute 'Powershell.exe' -Argument $destination
$trigger = New-ScheduledTaskTrigger -AtStartup
$principal = New-ScheduledTaskPrincipal -UserID "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount -RunLevel Highest
Register-ScheduledTask -TaskName 'RemoveAppLogs' -TaskPath '\CustomTasks\' -Action $action -Trigger $trigger -Principal $principal -Description 'The task will run script to install software.' -ErrorAction Stop
I thought I had this issue entirely solved but not. Dug into it a bit more and learned a few more things.
Goal
Create Log File on startup to a file share using a UNC path. Uses Add-Content.
Use Start-Transcript to create a local log of the PS Script that is running.
Remove files once complete using Remove-Item.
Issue - Only some of the time. Some times everything works perfectly
Logs are not being created, and files are not being removed
If one of these things are not working, then they are all failing. I have no seen in my testing where only one of these actions is complete.
I do not have any error to show or help me identify the issue. The script is being run by a task via Task Scheduler using the SYSTEM Account
Unsure where to turn without an error or something.
This is how Task is Created
$Task_Action = New-ScheduledTaskAction -Execute 'PowerShell.exe' -Argument '-File C:\Script.ps1'
$Task_Principal = New-ScheduledTaskPrincipal -UserId SYSTEM -RunLevel Highest
$Task_Settings = New-ScheduledTaskSettingsSet -Hidden
$Task_Trigger = New-ScheduledTaskTrigger -AtStartup
Register-ScheduledTask `
-TaskName "This is Task" `
-Action $Task_Action `
-Principal $Task_Principal `
-Trigger $Task_Trigger `
-Settings $Task_Settings `
-Force
This is how transcript is created
Start-Transcript -Path "C:\Logs\Transcript.txt"
This is how log via UNC Path is added
Function WriteTo-LogFile($Text_For_Log) {
$Log_DateTime = (Get-Date).ToFileTimeUtc()
Add-Content -Path $Log_File -Value ($Log_DateTime + ",$Text_For_Log")
}
WriteTo-LogFile ("Adding Stuff to Log.")
I've been looking into Group Managed Service Accounts (gmsa) accounts and I've been using them to run scheduled tasks on Server 2012R2 and PowerShell 5.0.10586.117.
After I've been using them a while I've encountered some very weird behavior.
The problem seem to be some kind of timing issue/race condition somewhere when a task is run as a gmsa account. Some core commands might not exists/be loaded while running the script.
Example:
Script called in the task C:\temp\broken-task\test.cmd
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy "ByPass" -File "C:\temp\broken-task\test.ps1" > "C:\temp\broken-task\test.cmd.txt"
The actual script with weird behavior C:\temp\broken-task\test.ps1
<#
.SYNOPSIS
Broken task.
.DESCRIPTION
Broken task.
#>
[CmdletBinding()] Param ()
Process {
$ErrorActionPreference
Set-Variable -Name "ErrorActionPreference" -Scope "Script" -Value "Stop"
Set-Variable -Name "ErrorActionPreference" -Scope "Script" -Value "Stop"
$ErrorActionPreference
}
I then create and run a task in C:\temp\broken-task\task.ps1
$Action = New-ScheduledTaskAction -Execute "C:\Windows\System32\cmd.exe" -Argument "/C C:\temp\broken-task\test.cmd"
$Principal = New-ScheduledTaskPrincipal -UserID "my-gmsa-user$" -LogonType "Password"
New-ScheduledTask -Action $Action -Principal $Principal | Register-ScheduledTask -TaskPath "\test\" -TaskName "test123" | Out-Null
Start-ScheduledTask -TaskPath "\test\" -TaskName "test123"
After task completion the content of C:\temp\broken-task\test.cmd.txt is the following:
Continue
Set-Variable : The term 'Set-Variable' is not recognized as the name of a cmdle
t, function, script file, or operable program. Check the spelling of the name,
or if a path was included, verify that the path is correct and try again.
At C:\temp\broken-task\test.ps1:15 char:5
+ Set-Variable -Name "ErrorActionPreference" -Scope "Script" -Value ...
+ ~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Set-Variable:String) [], Comman
dNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Stop
What is happening above is that Set-Variable doesn't exist on line 2 of the process block in test.ps1, but exist on line 3 (we can see that $ErrorActionPreference has changed).
If I run either the cmd script or the ps1 as myself (a normal user) I will get the expected output with no errors:
Continue
Stop
So what's going on here? The Set-Variable command is in the Microsoft.PowerShell.Utility module. Is the module somehow loaded in between the first and second call? This also happen with other commands like Get-Item "C:\".
What might be even worse is that this does not always happen. I've seen a task work properly in one run and fail in the other.
Also note that I find it hard to create good examples and this does not always yield the same weird results (but the above example has currently failed without exception in my tests).
Is the combination of powershell, gmsa and task scheduler broken somehow?
I can't really trust the system to do as I which when it has this inconsistent behavior.
A workaround might be explicit loading of the Microsoft.PowerShell.Utility module before calling Set-Variable, but I'm not sure if this is due to timing or something else..