Created
June 15, 2023 16:54
-
-
Save aeveltstra/e879f680438f5e75a9104030acfd10ff to your computer and use it in GitHub Desktop.
Powershell: updating actions of MS Windows scheduled tasks that run on remote servers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
# Updating actions of existing, known scheduled tasks to the newest known application version. | |
# The script assumes that each task has exactly 1 action. Other actions will get deleted. | |
# | |
# Author: A.E.Veltstra | |
# Version: 2.23.607.1200 | |
#> | |
# List all remote servers to be processed. | |
$hosts = @{ | |
"host-name" = @( | |
"\scheduled\task\path\*" | |
) | |
}; | |
# Buffer to collect any errors during processing. | |
$errors = @(); | |
# determine what part of the task action needs to be updated | |
$old_date = "2.23.530.1550"; | |
$new_date = "2.23.615.1213"; | |
<# | |
NOTE: Merely asking for the credential input WILL FAIL. | |
For whatever reason, the UserName and Password of the regular credential object WILL CAUSE lock-out. | |
Instead, we MUST elevate to the NetworkCredential. | |
#> | |
# (Tech note: we cannot use the variable name 'pwd' as that already is used by Powershell as the present working directory.) | |
$cred = (Get-Credential -Message "What network user name and pwd should the updated tasks run as?").GetNetworkCredential(); | |
# Processing each host | |
# (Tech note: we cannot use the variable name 'host' as that is reserved by Powershell.) | |
foreach($h in $hosts.Keys) { | |
if (Test-Connection -ComputerName $h -Quiet -ErrorAction SilentlyContinue) { | |
$c = New-CimSession -ComputerName $h -ErrorAction SilentlyContinue; | |
$hosts[$h] | %{ | |
$taskpath = $_; | |
$tasks = Get-ScheduledTask -CimSession $c -TaskPath $taskpath; | |
$tasks | %{ | |
$old_action = $_.Actions[0]; | |
if ($old_action.Execute.Contains($old_date) -or $old_action.WorkingDirectory.Contains($old_date)) { | |
#$old_action | echo; | |
$new_action = New-ScheduledTaskAction ` | |
-Argument $old_action.Arguments ` | |
-WorkingDirectory $old_action.WorkingDirectory.replace($old_date, $new_date) ` | |
-Execute $old_action.Execute.replace($old_date, $new_date); | |
#$new_action | echo; | |
if ($_.Triggers) { | |
Set-ScheduledTask -CimSession $c ` | |
-TaskPath $_.TaskPath ` | |
-TaskName $_.TaskName ` | |
-Action $new_action ` | |
-Trigger $_.Triggers ` | |
-User $cred.UserName ` | |
-Password $cred.Password; | |
} else { | |
Set-ScheduledTask -CimSession $c ` | |
-TaskPath $_.TaskPath ` | |
-TaskName $_.TaskName ` | |
-Action $new_action ` | |
-User $cred.UserName ` | |
-Password $cred.Password; | |
} | |
} else { | |
"Not updating: no date match." | echo; | |
$_.TaskName | echo; | |
$old_action.Execute | echo; | |
$old_action.WorkingDirectory | echo; | |
} | |
} | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Part of the challenge with updating actions in existing scheduled tasks, is that the way Microsoft lets us do this, is less of an update and more of a full replace. That will result in losing some information if it isn't copied explicitly to the new task.