Powershell – Scheduling a one-time task to run on Windows Server 2012R2 boot

powershellscheduled-taskwindows-server-2008-r2

As part of a system build automation script (that I'm using to create AWS AMIs), I want the system to reboot and then run additional post-boot setup tasks – but only once (so that when the system is imaged and then the image used to start a new instance, it will not run the post-boot setup tasks again).

The way I started to implement this is that the initial setup script (written in Powershell) uses Register-ScheduleJob -Trigger (New-JobTrigger -AtStartup) ... -Name PostBootSetup to setup another Powershell script run immediately after boot. In the post-boot script, I have:

Get-JobTrigger -Name PostBootSetup | ?{$_.Enabled} | Disable-JobTrigger

But when it is run I get this error (I'm logging all output of the post-boot script to a file):

Powershell : A scheduled job definition with Name PostBootSetup could not be found.

Which is weird because that is the output from the job that is currently running. I've also added just plain calls to Get-ScheduledJob and Get-JobTrigger -Name PostBootSetup that should output the relevant records, but there is absolutely no output from these – even though if I run these commands on a Powershell console after the machine started, I get the expected output.

Is it possible that a job can't access its own scheduled job record while running? If so, is there a workaround? or am I missing something? If this is not a good method to go about doing a one-time post-boot job, what would you suggest?

As a further note, I'm not very comfortable in batch, so I'd appreciate solutions that use Powershell or .Net or something that is more expressive than batch.

Best Answer

Use one of the RunOnce registry keys, they were designed for exactly this kind of task.
They run once, and then disappear.

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce

Make a new string value key where the name is whatever, and the data is the CLI EXE and switches to what you want run.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa376977%28v=vs.85%29.aspx

PS C:\> new-itemproperty -path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce -name "myInstall" -value '"c:\temp\borland\setup.exe" /this /that /other'