6

I have multiple scheduled jobs running in server. All i want is to change the credentials for all scheduled jobs using powershell.

The below is used to list the scheduled jobs in the machine. Now how can i change the credentials for all these jobs. How to use the Set-ScheduledJob command ?

# PowerShell script to get scheduled tasks from local computer
$schedule = New-Object -ComObject Schedule.Service
$schedule.Connect()
$tasks = $schedule.GetFolder(".").GetTasks(0)
$tasks | Format-Table Name
sodawillow
  • 12,497
  • 4
  • 34
  • 44
Ikruzzz
  • 228
  • 1
  • 4
  • 15
  • What have you tried ? Hint : you will find XML files in `C:\Windows\System32\Tasks`. You can edit your question and add code (Ctrl+K to format) – sodawillow Nov 26 '15 at 08:21
  • I have tried to change the service credentials for Task scheduler jobs running in a server – Ikruzzz Nov 26 '15 at 08:56
  • The below is used to list the scheduled jobs in the machine. Now how can i change the credentilas for all these jobs. How to use the set-scheduledjob comand # PowerShell script to get scheduled tasks from local computer $schedule = new-object -com("Schedule.Service") $schedule.connect() $tasks = $schedule.getfolder(".").gettasks(0) $tasks | Format-Table Name – Ikruzzz Nov 26 '15 at 08:58
  • Can you please **edit** your question and add the code in it (Ctrl+K to format) ? – sodawillow Nov 26 '15 at 09:51
  • @sodawillow: I have edited my question. Plaese checka nd let me know your thoughts – Ikruzzz Nov 26 '15 at 10:07
  • Anybody have any idea about these? – Ikruzzz Nov 30 '15 at 09:53

3 Answers3

11

Thankfully, PowerShell now has options for doing this with less hassle than having a separate script.

$NewTaskCreds = Get-Credential
Get-ScheduledTask |
  Set-ScheduledTask -User $NewTaskCreds.UserName -Password $NewTaskCreds.GetNetworkCredential().Password

Of course, that will update EVERY scheduled task, so if you're just updating the password for a specific user, I suggest this:

$NewTaskCreds = Get-Credential
Get-ScheduledTask | 
  Where-Object { $_.Principal.UserId -eq $NewTaskCreds.UserName } |
    Set-ScheduledTask -User $NewTaskCreds.UserName -Password $NewTaskCreds.GetNetworkCredential().Password
double-beep
  • 5,031
  • 17
  • 33
  • 41
baumgart
  • 263
  • 3
  • 6
  • 2
    Thank you for this, this is just what I needed. Just one modification: "$NewTaskCreds.GetNetworkCredentials().Password" will fail because GetNetworkCredentials is an invalid method. The correct method is: "$NewTaskCreds.GetNetworkCredential().Password" - this worked for me on a Server 2016. – Mikael Dyreborg Hansen Oct 24 '18 at 08:13
  • 1
    This worked for me. I think the accepted answer has too many complexity or maybe it is outdated (2015). Thanks. – OscarGarcia Oct 30 '20 at 16:39
2

With a little bit of research I found this article (by Bill Stewart, now archived) which provides a script to do exactly what you need.

I'll reproduce it here as-is :

# Set-ScheduledTaskCredential.ps1
# Written by Bill Stewart (bstewart@iname.com)

#requires -version 2

<#
.SYNOPSIS
Sets the credentials for one or more scheduled tasks on a computer.

.DESCRIPTION
Sets the credentials for one or more scheduled tasks on a computer.

.PARAMETER TaskName
One or more scheduled task names. Wildcard values are not accepted. This parameter accepts pipeline input.

.PARAMETER TaskCredential
The credentials for the scheduled task. If you don't specify this parameter, you will be prompted for credentials.

.PARAMETER ComputerName
The computer name where the scheduled task(s) reside.

.PARAMETER ConnectionCredential
The credentials to use when connecting to the computer.

.EXAMPLE
PS C:\>Set-ScheduledTaskCredential "My Scheduled Task"
This command will prompt for credentials and configure the specified task using those credentials.

.EXAMPLE
PS C:\>Set-ScheduledTaskCredential "Task 1","Task 2" -ComputerName server1
This command will prompt for credentials and configure the named scheduled tasks on the computer server1.

.EXAMPLE
PS C:\>Set-ScheduledTaskCredential "Task 1","Task 2" -ComputerName server1
This command will prompt for credentials and configure the named scheduled tasks on the computer server1.

.EXAMPLE
PS C:\>Get-Content TaskNames.txt | Set-ScheduledTaskCredential -ConnectionCredential (Get-Credential)
This command will set scheduled task credentials for all tasks named in the file TaskNames.txt. There will be two credential prompts. The first prompt is to specify credentials to connect to the Task Scheduler service, and the second prompt is to specify credentials to use for the scheduled tasks.
#>

[CmdletBinding(SupportsShouldProcess=$TRUE)]
param(
  [parameter(Mandatory=$TRUE,ValueFromPipeline=$TRUE)]
    [String[]] $TaskName,
    [System.Management.Automation.PSCredential] $TaskCredential,
    [String] $ComputerName=$ENV:COMPUTERNAME,
    [System.Management.Automation.PSCredential] $ConnectionCredential
)

begin {
  $PIPELINEINPUT = (-not $PSBOUNDPARAMETERS.ContainsKey("TaskName")) -and (-not $TaskName)
  $TASK_LOGON_PASSWORD = 1
  $TASK_LOGON_S4U = 2
  $TASK_UPDATE = 4
  $MIN_SCHEDULER_VERSION = 0x00010002

  # Try to create the TaskService object on the local computer; throw an error on failure
  try {
    $TaskService = new-object -comobject "Schedule.Service"
  }
  catch [System.Management.Automation.PSArgumentException] {
    throw $_
  }

  # Assume $NULL for the schedule service connection parameters unless -ConnectionCredential used
  $userName = $domainName = $connectPwd = $NULL
  if ($ConnectionCredential) {
    # Get user name, domain name, and plain-text copy of password from PSCredential object
    $userName = $ConnectionCredential.UserName.Split("\")[1]
    $domainName = $ConnectionCredential.UserName.Split("\")[0]
    $connectPwd = $ConnectionCredential.GetNetworkCredential().Password
  }
  try {
    $TaskService.Connect($ComputerName, $userName, $domainName, $connectPwd)
  }
  catch [System.Management.Automation.MethodInvocationException] {
    write-error "Error connecting to '$ComputerName' - '$_'"
    exit
  }

  # Returns a 32-bit unsigned value as a version number (x.y, where x is the
  # most-significant 16 bits and y is the least-significant 16 bits).
  function convertto-versionstr([UInt32] $version) {
    $major = [Math]::Truncate($version / [Math]::Pow(2, 0x10)) -band 0xFFFF
    $minor = $version -band 0xFFFF
    "$($major).$($minor)"
  }

  if ($TaskService.HighestVersion -lt $MIN_SCHEDULER_VERSION) {
    write-error ("Schedule service on '$ComputerName' is version $($TaskService.HighestVersion) " +
      "($(convertto-versionstr($TaskService.HighestVersion))). The Schedule service must " +
      "be version $MIN_SCHEDULER_VERSION ($(convertto-versionstr $MIN_SCHEDULER_VERSION)) " +
      "or higher.")
    exit
  }

  # This prevents a scoping problem--if the $TaskCredential variable
  # doesn't exist, it won't get created in the correct scope--create
  # new variable as a workaround
  $NewTaskCredential = $TaskCredential
  if (-not $NewTaskCredential) {
    $NewTaskCredential = $HOST.UI.PromptForCredential("Task Credentials",
      "Please specify credentials for the scheduled task.", "", "")
    if (-not $NewTaskCredential) {
      write-error "You must specify credentials."
      exit
    }
  }

  function set-scheduledtaskcredential2($taskName) {
    $rootFolder = $TaskService.GetFolder("\")
    try {
      $taskDefinition = $rootFolder.GetTask($taskName).Definition
    }
    catch [System.Management.Automation.MethodInvocationException] {
      write-error "Scheduled task '$taskName' not found on '$computerName'."
      return
    }
    $logonType = $taskDefinition.Principal.LogonType
    # No need to set credentials for tasks that don't have stored credentials.
    if (-not (($logonType -eq $TASK_LOGON_PASSWORD) -or ($logonType -eq $TASK_LOGON_S4U))) {
      write-error "Scheduled task '$taskName' on '$ComputerName' doesn't have stored credentials."
      return
    }
    if (-not $PSCMDLET.ShouldProcess("Task '$taskName' on computer '$ComputerName'",
      "Set scheduled task credentials")) { return }
    try {
      [Void] $rootFolder.RegisterTaskDefinition($taskName, $taskDefinition, $TASK_UPDATE,
        $NewTaskCredential.UserName, $NewTaskCredential.GetNetworkCredential().Password, $logonType)
    }
    catch [System.Management.Automation.MethodInvocationException] {
      write-error "Error updating scheduled task '$taskName' on '$computerName' - '$_'"
    }
  }
}

process {
  if ($PIPELINEINPUT) {
    set-scheduledtaskcredential2 $_
  }
  else {
    $TaskName | foreach-object {
      set-scheduledtaskcredential2 $_
    }
  }
}
smbear
  • 1,007
  • 9
  • 17
sodawillow
  • 12,497
  • 4
  • 34
  • 44
0

Here's a script I use to update the password for scheduled tasks in a specified folder that are configured to "Run whether the user is logged on or not". This ignores disabled tasks and tasks configured to "Run only when user is logged on". The script checks if it's running as an administrator because without that the Set-ScheduledTask command would fail with an "Access denied" error.

param(
    [string[]]$taskPaths = @('\Bill\'),
    [string]$userName = [System.Environment]::UserDomainName + "\" + [System.Environment]::UserName
)

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

$isAdmin = (new-object System.Security.Principal.WindowsPrincipal([System.Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole("Administrators")
if (!$isAdmin)
{
    Write-Host "You must run this script from an administrator PowerShell prompt."
}
else
{
    # Principal.LogonType mentioned at https://stackoverflow.com/a/60568865/1882616. We don't need to update when LogonType -eq 'Interactive'.
    $tasks = @(Get-ScheduledTask -TaskPath $taskPaths | Where-Object {$_.State -ne 'Disabled' -and $_.Principal.LogonType -eq 'Password'})
    if ($tasks)
    {
        $credential = Get-Credential -UserName $userName -Message "Enter the new password to use for scheduled tasks:"
        if ($credential)
        {
            $userName = $credential.UserName
            $password = $credential.GetNetworkCredential().Password

            foreach ($task in $tasks)
            {
                [void](Set-ScheduledTask -InputObject $task -User $userName -Password $password)
                Write-Host "Updated: $($task.TaskName)"
            }
        }
    }
}
Bill Menees
  • 2,124
  • 24
  • 25