generating batch file to back up enabled/disabled state of Scheduled Tasks - powershell

From a batch file I am trying to:
Capture the task name and enabled/disabled state of all scheduled tasks in Windows 10 x64
Export these to a second batch file with TASKNAME and SCHEDULED_TASK_STATE populated in the following command for each task:
schtasks /Change /TN "\TASKNAME" /SCHEDULED_TASK_STATE
The idea is for this second batch file to serve as a one-click backup/restore of the enabled/disabled state of all existing tasks. This way, the cumbersome process of selectively enabling/disabling tasks one-by-one via a GUI tool (e.g., Task Scheduler, Autoruns, taskschedulerview-x64, etc.) can be easily undone (or redone).
For the source batch file, the command
SCHTASKS /Query /FO LIST /v
... will retrieve a list of all tasks and the two values I am interested in -- 'TaskName' and 'Scheduled Task State.'
With info gleaned from other stackoverflow-ers, below is as far as I have gotten using a temp files approach, but it's only half done and I'm in way over my head :)
echo
:: Get list and parameters of all tasks; find values for TaskName; save values to temp file 1
SCHTASKS /Query /FO LIST /v| findstr /r /C:"TaskName: " >"%USERPROFILE%\Desktop\1-SCHTASKS_LIST_QUERY_NAMES.TXT"
:: Re-get list and parameters of all tasks; find values for Scheduled Task State; save values to temp file 2
SCHTASKS /Query /FO LIST /v| findstr /r /C:"Scheduled Task State: " >"%USERPROFILE%\Desktop\2-SCHTASKS_LIST_QUERY_STATES.TXT"
:: Set delimiter/assign variable to TaskName values in temp file 1; populate schtasks/change command with value; (missing steps to get/populate task state); save to target batch file
for /f "tokens=2 delims=: " %%n in (%USERPROFILE%\Desktop\1-SCHTASKS_LIST_QUERY_NAMES.TXT) do #echo schtasks /Change /TN "%%n">>"%USERPROFILE%\Desktop\BACKUPS\BACKEDUP_scheduled_tasks_state.bat"
pause
Rather than the above, I would prefer if the source batch file:
Executes the command SCHTASKS /Query /FO LIST /v
Does all processing/parsing in-place, i.e., assign variables to the two values I need for each task - 'TaskName' and 'Scheduled Task State' -- without creating temp files, and
Inserts these values to 'schtasks /Change' commands for all tasks and export to the target batch file.
Any help will be much appreciated.

As you need only taskname and status, you don't need /v (verbose)
schtasks will then output taskname, next run time and status.
Get a format of csv instead of list, so each task is on only one line (much easier to parse).
Use find to exclude the header lines.
use a for loop around to get the desired tokens (1=taskname, 3=status) and set them into variables.
#echo off
setlocal enabledelayedexpansion
set n=0
for /f "tokens=1,3 delims=," %%a in ('schtasks /query /fo csv^|find "\"') do (
set /a n+=1
set name[!n!]=%%~na
set state[!n!]=%%~b
)
echo ----- %n% tasks found -----
rem set name
rem set state
set /a num=%random% %% %n% +1
echo example: !name[%num%]! has status of !state[%num%]!
delayed expansion is used, because variables (n) are changed and used within a code block.

In regards to #Stephan's answer below....
COMMENTS
The task 'Status' value (as used by Stephan) is a little different than 'Scheduled Task State.' In order to export the command 'schtasks /Change /TN' in the backup batch file I'm trying to create, I need the 'Scheduled Task State' at the end of the line.
The task state is only available with verbose results; as such I've changed line 4 of Stephan's code to be:
:: Added /v (verbose); changed tokens to "2" (for task name in CSV) and "12" (for task state in CSV)
for /f "tokens=2,12 delims=," %%a in ('schtasks /query /fo csv /v^|find "\"') do (
PENDING
I am still unsure of how to append Stephan's modified code in order to:
Reference his variables to populate the command 'schtasks /Change /TN "\TASKNAME" /SCHEDULED_TASK_STATE,' and
Export a batch file with this command for every scheduled task in the current system (as a backup/restore file). Example of how this exported batch file would look:
schtasks /Change /TN "GoogleUpdateTaskMachineUA" /DISABLE
schtasks /Change /TN "GoogleUpdateTaskMachineCore" /DISABLE
schtasks /Change /TN "DropboxUpdateTaskMachineCore" /DISABLE
schtasks /Change /TN "DropboxUpdateTaskMachineUA" /DISABLE
schtasks /Change /TN "\Microsoft\Windows\Application Experience\ProgramDataUpdater" /DISABLE
...but including all tasks on the current system.
***** UPDATE *****
I've realized another issue: the command to get task states uses the language "Enabled" or "Disabled" (with "d" at the end); but the command to set a task's state needs the language "ENABLE" or "DISABLE" (neither with "d" at the end). So, the plot thickens: how to also delete the unnecessary end-of-value "d" when outputting to the target batch file?

Related

Robocopy script that takes ownership and gives it back

I am currently migrating from a Unix FS to a Windows FS and i need to copy user folders.
I have created a robocopy script that is very simple with a few kinks here and there.
My script:
#echo off
set /p username=Enter Username to start copying files:
echo %username%
takeown /f \UNIXFS\users$%username%* /r /D N
timeout /t 3
robocopy \UNIXFS\users$%username% \WINDOWSFS\Production$%username% /S /E /B /Z /ZB /MT:64 /V /TEE /ETA /TS /R:5 /W:1 /BYTES /X /DEBUG /LOG:C:\Robocopy%username%.log
timeout /t 3
icacls \WINDOWSFS\Production$%username%* /grant:r domain%username%:(OI)(CI)F /T
pause
I have an input section asking me which user i would like to start copying files from and too.
i take owner ship from the user as the current domain admin, copy the files and give the user full permissions on the folder.
But the ownership is still for the domain admin and not the user chosen by the inputted user.
Therefor i have created a separate single command line bat file that will take the ownership of the folder when i log in to the users account.
Take ownership script to run on for the migrated user:
takeown /F \WindowsFS\Production$%username%* /r /D Y
is there a way i can combine these two script as one and just run this as a single script.
I have tried to just combine them both together but the last takeown command like just give the user that runs the script ownership, when you have to do this for a lot of users you don't want to manually input or run the takeown script one by one on all machines.

How to set task scheduler's arguments from Power Shell [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I want to set "Add arguments" in the task scheduler.
Because we have a lot of windows servers and have to set add arguments on each server.
I know it has to manage command for task scheduler "tasks" but I don't know how to add only "Add arguments".
I want to know the command that can do what I want to do (first sentence).
Please ask me anything what you want to know about this problem. Thank you.
Learn by example (copied & pasted from an open elevated cmd window; note that ^^> is my admin command prompt):
^^> schtasks /query /TN SO_31969962 /V /FO LIST | findstr /R /C:"^Task To Run:" /C:"Start In"
Task To Run: D:\bat\SO\31969962.bat "1 st" second
Start In: D:\bat\SO\files
^^> schtasks /change /TN "\SO_31969962" /TR "D:\bat\SO\31969962.bat \"first\" second"
SUCCESS: The parameters of scheduled task "\SO_31969962" have been changed.
^^> schtasks /query /TN SO_31969962 /V /FO LIST | findstr /R /C:"^Task To Run:" /C:"Start In"
Task To Run: D:\bat\SO\31969962.bat "first" second
Start In: N/A
^^>
Here the Task To Run: … line corresponds to
Unfortunately, schtasks.exe fails in specifying “start-in” directory as you can see in above example (read entire thread of this link, google for schtasks start in directory).
Following PowerShell code snippet changes both Arguments and WorkingDirectory:
$Task = Get-ScheduledTask -TaskPath '\' -TaskName 'SO_31969962'
$Task.Actions[0].Arguments = 'bubu "foo bar"'
$Task.Actions[0].WorkingDirectory = '"D:\bat\Unusual Names"'
Set-ScheduledTask -InputObject $Task | Out-Null
Edit: following commented batch script shows possible approach of how-to construct a valid PowerShell one-line command (no need to run an existing .ps1 script):
#ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
rem related to D:\PShell\SO\41677069_ScheduledTask_Admin.ps1
rem show current parameters of a task (before change)
schtasks /query /TN "\SO_31969962" /V /FO LIST | findstr /R /C:"^Task To Run:" /C:"^Start In"
rem set auxiliary variables (note properly escaped inner double quotes)
set "_taskGet=$Task = Get-ScheduledTask -TaskPath '\' -TaskName 'SO_31969962'"
set "_taskArg=$Task.Actions[0].Arguments = '\""foo bar\"" bubu'"
set "_taskDir=$Task.Actions[0].WorkingDirectory = '\""D:\odds and ends\""'"
set "_taskSet=Set-ScheduledTask -InputObject $Task"
rem apply auxiliary variables (used merely to keep next line readable)
PowerShell -ExecutionPolicy Bypass -command "%_taskGet%;%_taskArg%;%_taskDir%;%_taskSet%"
rem show current parameters of a task (after change)
schtasks /query /TN "\SO_31969962" /V /FO LIST | findstr /R /C:"^Task To Run:" /C:"^Start In"
Result (read powershell /? or Get-Help 'about_powershell.exe' -ShowWindow; read also about_Execution_Policies):
^^> powershell -ExecutionPolicy Bypass -File "D:\PShell\SO\41677069_ScheduledTask_Admin.ps1"
^^> D:\bat\SO\41677069_ScheduledTask_Admin.bat
Task To Run: D:\bat\SO\31969962.bat bubu "foo bar"
Start In: "D:\bat\Unusual Names"
TaskPath TaskName State
-------- -------- -----
\ SO_31969962 Disabled
Task To Run: D:\bat\SO\31969962.bat "foo bar" bubu
Start In: "D:\odds and ends"
^^>
You'll need to modify the task action, not the task itself:
# Retrieve task
$Task = Get-ScheduledTask -TaskName "myScheduledTask"
# Retrieve action, modify argument
$Task.Actions[0] = "new arguments string go here"
# Update task
Set-ScheduledTask $Task

Obtaining exit code from schtasks

I'm trying to start a scheduled task from a Powershell script, like this:
schtasks /Run /TN "Test" > nul
I'm testing as I go, so I've set up the task to call a batch file that intentionally does not exist.
Once this happens, I see on the next line of code that the error level was 0, despite seeing 0x1 in the Task Scheduler's Last Run Result column.
In the console, I see
SUCCESS: Attempted to run the scheduled task "Test"
This looks to me as though it's considering the launch successful, and not waiting around to capture the error reported to Task Scheduler. (0x1)
How can I detect this error in Powershell?
I seem to remember that schtasks.exe just instructs the the task scheduler to go run a job and immediately exists without waiting around. Hence it always returning 0 unless the task itself can't be found (exit code: 1) or something catastrophic happens (exit code: no idea).
If you want to get the "Last Run Result" you'll need to query the task, for example:
schtasks.exe /v /query /tn "A Real Task" /fo list
This will return the task details including its run status as a list of fields and values which will include the "Last Run Result".
To see more formatting options run:
schtasks.exe /query /?
So you could capture data about a task (in this case CSV formatted) by doing:
$taskinfo = schtasks.exe /query /tn "A Real Task" /FO CSV /V
...then process it in some way. Obviously you'd need to check the task's run status to make sure it's completed before reading the "Last Run Result".

How to execute a scheduled task with "schtasks" without opening a new command line window?

I have a batch file that creates a scheduled task using schtasks like this:
schtasks /create /tn my_task_name
/tr "...\my_path\my_task.bat"
/sc daily
/st 10:00:00
/s \\my_computer_name
/u my_username
/p my_password
It works OK except the fact that when my_task.bat is executed - a new command line window is opened (and closed after execution).
I would like to avoid opening this new window (i.e. to run the task in quiet mode, in the background).
I thought to use
start /b ...\my_path\my_task.bat
but I don't know how, because since I have to call start from the batch file I need to precede it with cmd /c, which again causes the new window to open.
How could I solve this problem ?
You can do this by specifying /RU option for schtasks. This option
specifies the user account (user
context) under which the task runs.
For the system account, valid values
are "", "NT AUTHORITY\SYSTEM" or
"SYSTEM".
And thus, try this
schtasks /create /tn my_task_name
....
/st 10:00:00
/ru "SYSTEM"
....
You can use the Windows Shell Scripting extensions to execute a batch file in invisible mode.
Create a plain text file and name it <scriptname>.vbs
Paste the following code in the .vbs file
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run chr(34) & "C:\Batch Files\syncfiles.bat" & Chr(34), 0
Set WshShell = Nothing
Change the name and path of you batch file according to your need
Save the .vbs file and schedule the same in schtasks

Why "schtasks" does not run my job?

I scheduled a task on Windows-XP using schtasks utility, but the task does not run. Here is what I see in the SchedLgU.Txt log file:
"MySQL Automatic Backup.job" (WampServer) 10/2/2010 6:36:43 PM ** ERROR **
Unable to start task.
The specific error is:
0x800700c1: (Unable to find an error message)
Try using the Task page Browse button to locate the application.
I found out that the reason for this error is spaces in the path to my script. The command that I used to set up the task look like:
schtasks /create /tn "MySQL Automatic Backup"
/tr "d:\path with spaces to my script\my script.bat" /sc daily ...
If I replace the spaces with underscores, for example, the problem disappears.
How could I solve this problem ?
And another question: What does the Start In column means in the output for schtasks /query /v ?
Thanks !
I found the answer:
Spaces in file paths can be used by using two sets of quotes,
one set for CMD.EXE and one for SchTasks.exe.
The outer quotes for CMD need to be double quotes;
the inner quotes can be single quotes or escaped double quotes.
i.e. it should be like this:
schtasks /create /tn "MySQL Automatic Backup"
/tr "\"d:\path with spaces to my script\my script.bat\"" /sc daily ...