Intune does not have a native way to create scheduled tasks, but we can still deploy them to machines by using a Win32 app. If you don’t have the licensing to use proactive remediations, we can use this as a workaround to get some similar results (but without any native reporting in Intune). So, for all the non-M365/Win365 E3/E5/A3/A5 licenses out there, maybe this will help. The first thing you need is an XML file of the scheduled task. Unless you’re familiar with scheduled task XML files, the easiest and fastest way is to create a scheduled task on your device, test it to verify it works as expected, and then export it. I’ll show how we can export a simple scheduled task that restarts the print spooler with a PowerShell script. Once its exported, we will look at the XML file, package everything the task needs as a Win32 app, and deploy it to a machine.
The scheduled task XML file
Open task scheduler, and create your task. Here we have a simple task that runs a restartspooler.ps1 script every hour. I have this set to run as system with the highest privileges. I’ll cover how to have the task run as the logged in user later on.
We have a trigger to start at a certain time and then run every hour indefinitely
Lastly, we have the action to run PowerShell, and execute our file. The arguments contain “-file c:\path to your file.
You can set any additional conditions or settings if you want to, but for this example I leave the defaults. Once your task is created, test it to make sure it runs as expected. I suggest turning on the task history before testing so you can get some additional information:
When you’ve tested the task and its running successfully, right click it and select export. Choose a location to export the file.
If we open the XML file, we can view the contents and see where out settings are. Most fields are self-explanatory and align with the settings options we have in the GUI. There are some key areas to point out that may make it faster to edit an XML for a similar task, instead of making a new task from scratch. I highlighted the areas most important for the task I created, but your XML may be busier if you have more parameters set:
- Author – you can make this any value
- Triggers > Calendar Triggers > Repetition > Interval – This is how often your task will run if its set to run on a schedule. The value PT1H means every hour. You can find more details on this representation and how to edit it here – https://docs.microsoft.com/en-us/windows/win32/taskschd/taskschedulerschema-interval-repetitiontype-element
- UserID – S-1-5-18 is the SID for the local system account. If we were running a task for the logged in user, this value would be S-1-5-32-545, which is the builtin Users group. More on that here if you want to learn more – https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/manage/understand-security-identifiers.
- Command – this is our action, which specifies the path to our script
Deploy the scheduled task as a Win32 app
Now that we have a basic understanding of the XML layout, lets deploy this to a machine with a Win32 app. Before we do that, we need a location for our action script on the target machines. This is your choice depending on the sensitivity of the script and if you want users to see it. In this example, it’s a script to restart a service, so I’ll use the C:\Temp directory as my location. Make sure your task is set to use this location for the action script. Next, we create a PowerShell script that creates c:\temp if it doesn’t exist, copy our restartspooler.ps1 script to that location, and then register a new scheduled task using our XML file. The syntax is below. You’ll need to specify a name for the scheduled task with the -Taskname parameter. All the files and scripts I used are available on my Github here.
$tempdir = "c:\temp"
New-Item $tempdir -ItemType Directory -Force
Copy-Item ".\restartspooler.ps1" -Destination $tempdir -Force
Register-ScheduledTask -xml (Get-Content '.\RestartPrintSpooler.xml' | Out-String) -TaskName "Restart-Spooler-hourly" -Force
We also make a separate script to remove the scheduled task. This will be used as the uninstall script if we want to remove the task from our target machines:
unregister-scheduledtask -taskname Restart-Spooler-hourly -confirm:$false
Move all four of the files (the action script, XML file, task registration script, task removal script) to the same directory. Wrap these files for use as a Win32app using IntuneWinAppUtil.exe like below:
Once you have your intunewin file, create a new Win32 App and provide a name/description:
For our install command, use the values below. We need to install as system to create a scheduled task since it requires admin privileges.
Add requirements and proceed to the detection rules. We will create two – one to detect if our action script it in the c:\temp directory, and another to see if the scheduled task exists. Both will need to exist for detection to pass. The scheduled task files get stored in c:\windows\system32\tasks as a file the same name as the task. There is no extension on the files in this directory, but they’re in XML format.
Complete the remainder of the app and assign to your target devices/users. Once you have some test deployments showing successful, we can check to make it looks correct and test on our target devices:
Since this is a system task, it won’t show in a standard user’s task scheduler library. If you run task scheduler as administrator, you will see it. Below you can see the standard user’s task scheduler view on bottom, and our task we created on top where it is opened as admin.
And here are our files for our detection rules:
Lastly, lets see if the task runs as scheduled. I changed the start time on this to be 7:25 AM since I am writing this the next morning:
Remember, if you want the task to run as the logged in user, you’ll need to change the user account on the task to use “Users” as the group, and uncheck the box to run with highest privileges before exporting your XML. Also, remember to make sure the logged in user has the rights to perform the actions of the task – they can’t restart services, but this screenshot is just showing you an example of what to change to run as the logged in user.