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
Related
I have a script which launches an app on the VM and logs some data for the app. As Powershell script does not allow me to run the app in foreground I decided to schedule a task after 2 mins and then keep polling for the task completion.
I was using this command to register my task
$password= "password" | ConvertTo-SecureString -asPlainText -Force;
$username = "name";
$credential = New-Object System.Management.Automation.PSCredential($username,$password);
Invoke-Command -VMName INSTANCE_ID -Credential $credential -ScriptBlock
{
$gettime = (Get-Date).AddMinutes(2);
$run = $gettime.ToString('HH:mm');
$action = New-ScheduledTaskAction -Execute 'C:\logging.bat';
$trigger = New-ScheduledTaskTrigger -Once -At $run;
$principal = New-ScheduledTaskPrincipal -GroupID "BUILTIN\Administrators" -RunLevel Highest;
Register-ScheduledTask -Action $action -Trigger $trigger -Principal $principal -TaskName "ID_Logging_Task" -Description "my description"
}
It was working fine but it had a problem that it ran well only when the user was logged in. More context - https://learn.microsoft.com/en-us/powershell/module/scheduledtasks/new-scheduledtaskprincipal?view=windowsserver2022-ps (Example 2)
So I looked at the documentation of Register-ScheduledTask and saw that I can provide username and password to the command while registering the task. So I took the username of the account with Administrator privileges and ran the new command:
$password= "password" | ConvertTo-SecureString -asPlainText -Force;
$username = "name";
$credential = New-Object System.Management.Automation.PSCredential($username,$password);
Invoke-Command -VMName INSTANCE_ID -Credential $credential -ScriptBlock
{
$gettime = (Get-Date).AddMinutes(2);
$run = $gettime.ToString('HH:mm');
$action = New-ScheduledTaskAction -Execute 'C:\logging.bat';
$trigger = New-ScheduledTaskTrigger -Once -At $run;
Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "ID_Logging_Task" -RunLevel Highest -User "myUser" -Password "myPassword" -Description "my description"
}
"myUser" is an administrator on this machine. This solved the problem of running the task without manually logging in but now my app is getting launched in the background instead of foreground which was the whole point of running these scheduled tasks.
My question is what is the difference between BUILTIN\Administrators and an Administrator account. And how do I solve my problem? I want to run my task with the privilege of -GroupID "BUILTIN\Administrators" without actually logging into the machine.
Difference between the group and account
BuiltIn\Administrators is a group you can be a member of.
Administrator is a default account that comes, normally disabled, on new Windows installations.
There is a way of fixing this problem, maybe easier than it seems.
Achieving what you want
I have a script which launches an app on the VM and logs some data for the app
Let's break doing this into three pieces
Launching the VM
If you want your VM to always be running, you can set it to 'Always Start'. This option is great because it will start the VM with the host, and you can even specify a startup delay, which is great because this lessens the pressure on disk and cpu, as starting a vm will incur a spike to both those resources.
If you do this, this takes care of starting the VM.
Launching the app
For the next piece this is as simple as the syntax you already have for running a scheduled task. If you want to run as a domain account and run as an administrator, just make the domain account a member of the 'Administrators' group on the system.
Running in Foreground
Here is the wrinkle, but I don't understand why this is an issue. Scheduled Tasks will only run in the Foreground when a user is logged into the machine.
This option is there so that you can make an app appear in the user's session when they log onto a computer, for things like Kiosk apps, or Point-Of-sale systems, dashboard displays and that sort of thing.
If you set an app to run whether or not a user is logged in, then it always will run in the background.
Are you sure this matters?
Making an app run in the foreground on boot
If you want an app to run without having to login, it will run in the background.
If you really want it to run in the foreground, then just set the machine to automatically log in. If it automatically log's in, then it will login and show the desktop, and then the scheduled task can be changed to 'Run only when a user is logged in', which will make it run in the foreground.
But why would someone need an App within a VM, which is by nature headless to run in the foreground?
I'm trying to create a Scheduled Task on a Windows Server Core 2012 so I don't have the UI of the scheduler task on the server, I've created the task with the following ps command:
Register-ScheduledTask -TaskName $jobname -Action $action -Trigger $trigger -RunLevel Highest -User $username -Password $password
I'm trying to execute a C# executable with the following action command:
$action = New-ScheduledTaskAction -Execute "D:\Apps\DeleteReadsDuplicates\DeleteReadsDuplicates.exe"
but it's not finding the file.
Do you think I have to execute the .exe with powershell and the file location as a parameter?
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 use a script to create a windows scheduled task to call a powershell script in elevated mode to run windows update by using boxstarter (a tool could automatically continue running code even there is reboot during the execution) when system startup. But not sure why, the task could be called after startup, but nothing has been done. If I manually start the scheduled task in task manager, it will run as expected.
Script to register a scheduled task:
$TaskActionArgument ="-noprofile -command "&{start-process powershell -argumentList '-File C:\users\administrator\updatescript\boxstarter.ps1 -verb runas'}""
$TaskAction = New-ScheduledTaskAction -Execute "C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe" -argument $TaskActionArgument
$TaskTrigger = New-ScheduledTaskTrigger -AtStartup
Register-ScheduledTask -TaskName boxstarter -Action $TaskAction -Trigger $TaskTrigger -User administrator -Password Vmc12svt -RunLevel Highest
I checked the event log viewer and see following error message for the scheduled job:
System
Provider
[ Name] PowerShell
EventID 403
[ Qualifiers] 0
Level 4
Task 4
Keywords 0x80000000000000
TimeCreated
[ SystemTime] 2018-01-10T18:21:12.000000000Z
EventRecordID 267
Channel Windows PowerShell
Computer WIN-6HSHKOKP31E
Security
EventData
Stopped Available NewEngineState=Stopped
PreviousEngineState=Available SequenceNumber=16 HostName=ConsoleHost
HostVersion=4.0 HostId=13ece112-b027-4051-9ddf-1a195d3aa30f
HostApplication=C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
-File C:\users\administrator\updatescript\boxstarter.ps1 -verb runas EngineVersion=4.0 RunspaceId=d158a216-18e3-4e86-9ade-b232201c9cdc
PipelineId= CommandName= CommandType= ScriptName= CommandPath=
CommandLine=
For the error message, I googled and found explain of error code here
In general, the page says such issue could be caused by following error:
The Task Scheduler service is disabled
The COM service is disabled
The Windows Event Log service is disabled
The RPC service is disabled
There is not enough free memory
Non of above is true for my system.
So what's error with my scheduled task? How could I make it work?
It looks like all your services are not setup. It's a common problem on things that run on startup/login. There's a -RandomDelay parameter to New-ScheduledTaskTrigger. I recommend you tinker with that if its your own machine you are testing this with. My example uses 1 minute.
$TaskTrigger = New-ScheduledTaskTrigger -AtStartup -Delay (New-TimeSpan -Minutes 1)
If you want a minute or so, all the services needed should be started up by then.
Another thing you'll want to do is have the your code in a try/catch, so the error is being written out to a log file, so you can see the error in the context of PowerShell, which might provide a more detailed message than what you are getting in the event log.
You can troubleshoot this by creating the scheduled task manually and then trying to run it.
Try changing the TaskActionArgument property to only the following string:
-NoProfile -ExecutionPolicy Bypass -File C:\users\administrator\updatescript\boxstarter.ps1
You don't need Start-Process or -Verb runas. In fact, -Verb runas will actually keep things from working, because it provokes a UAC prompt, which you don't want when trying to automate.
I want to write a powershell workflow that will run scripts, reboot and continue execute where it left off. Not when a user logs on, but when the computer reboots (so non-interactively).
The challenge is that it needs to run locally. Windows makes this infuriatingly difficult.
What I have done so far is create a workflow that runs as a job (PSWorkflowJob).
In the middle of the workflow it runs restart-computer with the -wait switch
Then I create a scheduled task that runs at startup which resumes that workflow
The problem is that tasks cannot run at startup unless they store credentials or run as the local system. I don't want to pass admin creds at all in this script so I run the task as the local system.
When the computer reboots that task fires, but it can't find the job because the job was created by the local admin.
workflow Resume_Workflow
{
PowerShell.exe -Noninteractive -ExecutionPolicy Bypass -File 'C:\somescript.ps1'
Restart-Computer -Wait
PowerShell.exe -Noninteractive -ExecutionPolicy Bypass -File 'C:\someotherscript.ps1'
}
$taskName = 'Continue_Workflow'
#Pass code directly to powershell.exe to avoid creating another .ps1 file
$PSCode = #'
-NoProfile -command "& powershell.exe {
Import-Module PSWorkflow;
Resume-Job -Name new_resume_workflow_job -Wait;
}"
'#
$action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument $PSCode
$trigger = New-ScheduledTaskTrigger -AtStartup -RandomDelay 00:00:30
$settings = New-ScheduledTaskSettingsSet -Compatibility Win8
$principal = New-ScheduledTaskPrincipal -UserId SYSTEM `
-LogonType ServiceAccount -RunLevel Highest
$definition = New-ScheduledTask -Action $action -Principal $principal `
-Settings $settings -Description "Run $($taskName) at startup" `
-Trigger $trigger
Register-ScheduledTask -TaskName $taskName -InputObject $definition
# Execute the workflow as a PS job (PSWorkflowJob)
Resume_Workflow -AsJob -JobName new_resume_workflow_job