Skip to content

Instantly share code, notes, and snippets.

@Bill-Stewart
Created September 18, 2019 21:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save Bill-Stewart/363fdf761499a071439c8ac0c18dcd54 to your computer and use it in GitHub Desktop.
Save Bill-Stewart/363fdf761499a071439c8ac0c18dcd54 to your computer and use it in GitHub Desktop.
# Set-ScheduledTaskCredential.ps1
# Written by Bill Stewart (bstewart@iname.com)
#requires -version 2
# Version history:
#
# Version 1.1 (18 Sep 2019)
# * Correct ShouldProcess (move to main process loop).
#
# Version 1.0 (06 Mar 2012)
# * Initial version.
<#
.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,
[Management.Automation.PSCredential] $TaskCredential,
[String] $ComputerName = [Net.Dns]::GetHostName(),
[Management.Automation.PSCredential] $ConnectionCredential
)
begin {
$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 [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 {
Write-Error "Error connecting to '$ComputerName' - '$_'"
exit
}
# Returns a version number as a string (x.y); e.g. 65537 (10001 hex) returns "1.1"
function ConvertTo-VersionString {
param(
[Int] $version
)
$major = [Math]::Truncate($version / [Math]::Pow(2,16)) -band 65535
$minor = $version -band 65535
"{0}.{1}" -f $major,$minor
}
if ( $TaskService.HighestVersion -lt $MIN_SCHEDULER_VERSION ) {
Write-Error ("Schedule service on '$ComputerName' is version $($TaskService.HighestVersion) " +
"($(ConvertTo-VersionString($TaskService.HighestVersion))). The Schedule service must " +
"be version $MIN_SCHEDULER_VERSION ($(ConvertTo-VersionString $MIN_SCHEDULER_VERSION)) " +
"or higher.")
exit
}
# Avoid scope confusion (create new global)
$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-ScheduledTaskCredential {
param(
$taskName
)
$rootFolder = $TaskService.GetFolder("\")
try {
$taskDefinition = $rootFolder.GetTask($taskName).Definition
}
catch [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
}
try {
[Void] $rootFolder.RegisterTaskDefinition($taskName,$taskDefinition,$TASK_UPDATE,
$NewTaskCredential.UserName,$NewTaskCredential.GetNetworkCredential().Password,$logonType)
}
catch [Management.Automation.MethodInvocationException] {
Write-Error "Error updating scheduled task '$taskName' on '$computerName' - '$_'"
}
}
}
process {
foreach ( $TaskNameItem in $TaskName ) {
if ( $PSCmdlet.ShouldProcess("Task '$TaskNameItem' on computer '$ComputerName'","Set scheduled task credentials") ) {
Set-ScheduledTaskCredential $TaskNameItem
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment