Answered by:
Scheduled Task that Any User can run

Question
-
Good Morning!
I've been in IT for quite some time, but this one question has me banging my head agains the wall...
Simply put, I'm trying to create a task in Task Scheduler that any user can run.
I have created a task using a regular user account, but only that user and administrators can see it.
I have also created a task as an administrator, but only administrators can see it.
I've checked the permissions for the \Windows\System32\Tasks folder
and it lists the default permissions which includes Authenticated Users having special read access.
If I give all users access to the one task created by a specific general user, they still don't see it.
I know that this can be done, because I see one task created by Adobe Flash that all users see and can run on demand.
I'm at a loss as to how this was done.
Any help would be appreciated.Monday, August 26, 2019 1:43 PM
Answers
-
I was investigating this a while back and was unable to get file permission changes to work as you discovered.
This time I dug a little deeper and discovered the SD registry value. See the comments in the code. I have built a Powershell script that I named UnlockScheduledTask.ps1. This worked for me on Win10Pro. Just create a task and then unlock it.
Give it a try and see if it works for you.
<# .SYNOPSIS This Powershell script updates the security descriptor for scheduled tasks so that any user can run the task. Version 1.0 of this script only displays tasks in the root folder. I want to make sure that works first. .DESCRIPTION Earlier versions of Windows apparently used file permissions on C:\Windows\System32\Tasks files to manage security. Windows now uses the SD value on tasks under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree to accomplish that. By default, this script will display the SDDL on all tasks. If a taskname is passed as a parameter, this script will grant Authenticated users read and execute permissions to the task. This script accepts 1 parameters. -taskname The name of a scheduled task. .EXAMPLE ./UnlockScheduledTask.ps1 ./UnlockScheduledTask.ps1 -taskname "My task" .NOTES Author: Dave K. aka MotoX80 on the MS Technet forums. (I do not profess to be an expert in anything. I do claim to be dangerous with everything.) .LINK http://www.google.com #> param ( [string]$taskname = "" ) 'UnlockScheduledTask.ps1 Version 1.0' if ($taskname -eq '') { '' 'No task name specified.' 'SDDL for all tasks will be displayed.' '' } else { $batFile = "$env:TEMP\Set-A-Task-Free.bat" # if you don't like my names, you can change them here. $updateTaskName = 'Set-A-Task-Free' '' "SDDL for $taskname will be updated via $batfile" '' } $wmisdh = new-object system.management.ManagementClass Win32_SecurityDescriptorHelper $subkeys = Get-childitem "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree" foreach ($key in $subkeys) { if ($taskname -eq '') { # if blank, show SDDL for all tasks '' $key.PSChildName $task = Get-ItemProperty $($key.name).replace("HKEY_LOCAL_MACHINE","HKLM:") $sddl = $wmisdh.BinarySDToSDDL( $task.SD ) $sddl['SDDL'] } else { if ($key.PSChildName -eq $taskname) { "" $key.PSChildName $task = Get-ItemProperty $($key.name).replace("HKEY_LOCAL_MACHINE","HKLM:") $sddl = $wmisdh.BinarySDToSDDL( $task.SD ) $sddl['SDDL'] '' 'New SDDL' $newSD = $sddl['SDDL'] + '(A;ID;0x1301bf;;;AU)' # add authenticated users read and execute $newSD # Note: cacls /s will display the SDDL for a file. $newBin = $wmisdh.SDDLToBinarySD( $newsd ) [string]$newBinStr = $([System.BitConverter]::ToString($newBin['BinarySD'])).replace('-','') # Administrators only have read permissions to the registry vlaue that needs to be updated. # We will create a bat file with a reg.exe command to set the new SD. # The bat file will be invoked by a scheduled task that runs as the system account. # The bat file can also be reused if the task is deployed to other machines. '' "reg add ""HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\{0}"" /f /v SD /t REG_BINARY /d {1}" -f $key.PSChildName, $newBinStr "reg add ""HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\{0}"" /f /v SD /t REG_BINARY /d {1}" -f $key.PSChildName, $newBinStr | out-file -Encoding ascii $batfile '' SCHTASKS /Create /f /tn "$updateTaskName" /sc onstart /tr "cmd.exe /c $batfile" /ru system SCHTASKS /run /tn "$updateTaskName" $count = 0 while ($count -lt 5) { start-sleep 5 $count++ $(Get-ScheduledTask -TaskName $updateTaskName).State if ($(Get-ScheduledTask -TaskName $updateTaskName).State -eq 'Ready') { $count = 99 # it's ok to procees } } if ($count -ne 99) { "Error! The $updateTaskName task is still running. " 'It should have ended by now.' 'Please investigate.' return } SCHTASKS /delete /f /tn "$updateTaskName" '' 'Security has been updated. Test it.' } } }
- Marked as answer by Joe Hanchey Friday, August 30, 2019 7:37 PM
Tuesday, August 27, 2019 6:20 PM
All replies
-
Clarification:
When I stated "If I gave all users access to the one task created by a specific general user, they still don't see it."
I gave all users read and execute to the "AllUsersTask" file in the "C:\Windows\System32\Tasks" folderMonday, August 26, 2019 3:17 PM -
Hi Joe.
You could configure the scheduled task to run on LocalSystem Account: in this way the task will run at every user logon but on LocalSystem account; also note that if you configure a task to run under LocalSystem, the GUI of the application launched by the task will be hidden.
Another method would be to avoid using the Windows Task Scheduler and to add a shortcut of the file to be executed in the alluser start-up folder (C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup).Bye.
Luigi Bruno
MCP, MOS, MTA, MCTS, MCSA, MCSE
- Edited by Luigi BrunoMVP Monday, August 26, 2019 3:50 PM
Monday, August 26, 2019 3:49 PM -
What account will the task run as? The logged on user? System? A specific user? Run only when the user is logged on?Tuesday, August 27, 2019 1:30 AM
-
That's normal, A limited user can't see everything in the Task Manager list because elevation is required on UAC systems. But anyway, that task runs and a limited user can't see it.
As Luigi Bruno said, you could configure the scheduled task to run on LocalSystem Account
Or add a shortcut of the file launched by the scheduled task in the all user startup folder which is located in C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup.
Regards
Please remember to mark the replies as answers if they help.
If you have feedback for TechNet Subscriber Support, contact tnmff@microsoft.com.- Edited by Teemo TangMicrosoft contingent staff Wednesday, August 28, 2019 9:30 AM
Tuesday, August 27, 2019 6:16 AM -
I was investigating this a while back and was unable to get file permission changes to work as you discovered.
This time I dug a little deeper and discovered the SD registry value. See the comments in the code. I have built a Powershell script that I named UnlockScheduledTask.ps1. This worked for me on Win10Pro. Just create a task and then unlock it.
Give it a try and see if it works for you.
<# .SYNOPSIS This Powershell script updates the security descriptor for scheduled tasks so that any user can run the task. Version 1.0 of this script only displays tasks in the root folder. I want to make sure that works first. .DESCRIPTION Earlier versions of Windows apparently used file permissions on C:\Windows\System32\Tasks files to manage security. Windows now uses the SD value on tasks under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree to accomplish that. By default, this script will display the SDDL on all tasks. If a taskname is passed as a parameter, this script will grant Authenticated users read and execute permissions to the task. This script accepts 1 parameters. -taskname The name of a scheduled task. .EXAMPLE ./UnlockScheduledTask.ps1 ./UnlockScheduledTask.ps1 -taskname "My task" .NOTES Author: Dave K. aka MotoX80 on the MS Technet forums. (I do not profess to be an expert in anything. I do claim to be dangerous with everything.) .LINK http://www.google.com #> param ( [string]$taskname = "" ) 'UnlockScheduledTask.ps1 Version 1.0' if ($taskname -eq '') { '' 'No task name specified.' 'SDDL for all tasks will be displayed.' '' } else { $batFile = "$env:TEMP\Set-A-Task-Free.bat" # if you don't like my names, you can change them here. $updateTaskName = 'Set-A-Task-Free' '' "SDDL for $taskname will be updated via $batfile" '' } $wmisdh = new-object system.management.ManagementClass Win32_SecurityDescriptorHelper $subkeys = Get-childitem "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree" foreach ($key in $subkeys) { if ($taskname -eq '') { # if blank, show SDDL for all tasks '' $key.PSChildName $task = Get-ItemProperty $($key.name).replace("HKEY_LOCAL_MACHINE","HKLM:") $sddl = $wmisdh.BinarySDToSDDL( $task.SD ) $sddl['SDDL'] } else { if ($key.PSChildName -eq $taskname) { "" $key.PSChildName $task = Get-ItemProperty $($key.name).replace("HKEY_LOCAL_MACHINE","HKLM:") $sddl = $wmisdh.BinarySDToSDDL( $task.SD ) $sddl['SDDL'] '' 'New SDDL' $newSD = $sddl['SDDL'] + '(A;ID;0x1301bf;;;AU)' # add authenticated users read and execute $newSD # Note: cacls /s will display the SDDL for a file. $newBin = $wmisdh.SDDLToBinarySD( $newsd ) [string]$newBinStr = $([System.BitConverter]::ToString($newBin['BinarySD'])).replace('-','') # Administrators only have read permissions to the registry vlaue that needs to be updated. # We will create a bat file with a reg.exe command to set the new SD. # The bat file will be invoked by a scheduled task that runs as the system account. # The bat file can also be reused if the task is deployed to other machines. '' "reg add ""HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\{0}"" /f /v SD /t REG_BINARY /d {1}" -f $key.PSChildName, $newBinStr "reg add ""HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\{0}"" /f /v SD /t REG_BINARY /d {1}" -f $key.PSChildName, $newBinStr | out-file -Encoding ascii $batfile '' SCHTASKS /Create /f /tn "$updateTaskName" /sc onstart /tr "cmd.exe /c $batfile" /ru system SCHTASKS /run /tn "$updateTaskName" $count = 0 while ($count -lt 5) { start-sleep 5 $count++ $(Get-ScheduledTask -TaskName $updateTaskName).State if ($(Get-ScheduledTask -TaskName $updateTaskName).State -eq 'Ready') { $count = 99 # it's ok to procees } } if ($count -ne 99) { "Error! The $updateTaskName task is still running. " 'It should have ended by now.' 'Please investigate.' return } SCHTASKS /delete /f /tn "$updateTaskName" '' 'Security has been updated. Test it.' } } }
- Marked as answer by Joe Hanchey Friday, August 30, 2019 7:37 PM
Tuesday, August 27, 2019 6:20 PM -
MotoX80,
Thank you for your response. I was able to use the PS1 info and used the SDDL information it gathered in order to modify the registry entries and give my users the permissions they needed to run the task as needed.
Thank you!!
Joe
Friday, August 30, 2019 7:38 PM -
Great thanks for your script. You made my day. 👍Monday, September 9, 2019 1:47 PM
-
Thank you for the script :)Friday, January 3, 2020 1:18 PM