DSCResources/MSFT_xScheduledTask/MSFT_xScheduledTask.psm1
Add-Type -TypeDefinition @'
namespace xScheduledTask { public enum DaysOfWeek { Sunday = 1, Monday = 2, Tuesday = 4, Wednesday = 8, Thursday = 16, Friday = 32, Saturday = 64 } } '@ $modulePath = Join-Path -Path (Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent) -ChildPath 'Modules' # Import the ComputerManagementDsc Common Modules Import-Module -Name (Join-Path -Path $modulePath ` -ChildPath (Join-Path -Path 'ComputerManagementDsc.Common' ` -ChildPath 'ComputerManagementDsc.Common.psm1')) # Import the ComputerManagementDsc Resource Helper Module Import-Module -Name (Join-Path -Path $modulePath ` -ChildPath (Join-Path -Path 'ComputerManagementDsc.ResourceHelper' ` -ChildPath 'ComputerManagementDsc.ResourceHelper.psm1')) # Import Localization Strings $script:localizedData = Get-LocalizedData ` -ResourceName 'MSFT_xScheduledTask' ` -ResourcePath (Split-Path -Parent $Script:MyInvocation.MyCommand.Path) <# .SYNOPSIS Tests if the current resource state matches the desired resource state. .PARAMETER TaskName The name of the task. .PARAMETER TaskPath The path to the task - defaults to the root directory. .PARAMETER Description The task description. Not used in Get-TargetResource. .PARAMETER ActionExecutable The path to the .exe for this task. .PARAMETER ActionArguments The arguments to pass the executable. Not used in Get-TargetResource. .PARAMETER ActionWorkingPath The working path to specify for the executable. Not used in Get-TargetResource. .PARAMETER ScheduleType When should the task be executed. .PARAMETER RepeatInterval How many units (minutes, hours, days) between each run of this task? Not used in Get-TargetResource. .PARAMETER StartTime The time of day this task should start at - defaults to 12:00 AM. Not valid for AtLogon and AtStartup tasks. Not used in Get-TargetResource. .PARAMETER Ensure Present if the task should exist, Absent if it should be removed. .PARAMETER Enable True if the task should be enabled, false if it should be disabled. Not used in Get-TargetResource. .PARAMETER ExecuteAsCredential The credential this task should execute as. If not specified defaults to running as the local system account. Not used in Get-TargetResource. .PARAMETER DaysInterval Specifies the interval between the days in the schedule. An interval of 1 produces a daily schedule. An interval of 2 produces an every-other day schedule. Not used in Get-TargetResource. .PARAMETER RandomDelay Specifies a random amount of time to delay the start time of the trigger. The delay time is a random time between the time the task triggers and the time that you specify in this setting. Not used in Get-TargetResource. .PARAMETER RepetitionDuration Specifies how long the repetition pattern repeats after the task starts. Not used in Get-TargetResource. .PARAMETER DaysOfWeek Specifies an array of the days of the week on which Task Scheduler runs the task. Not used in Get-TargetResource. .PARAMETER WeeksInterval Specifies the interval between the weeks in the schedule. An interval of 1 produces a weekly schedule. An interval of 2 produces an every-other week schedule. Not used in Get-TargetResource. .PARAMETER User Specifies the identifier of the user for a trigger that starts a task when a user logs on. Not used in Get-TargetResource. .PARAMETER DisallowDemandStart Indicates whether the task is prohibited to run on demand or not. Defaults to $false. Not used in Get-TargetResource. .PARAMETER DisallowHardTerminate Indicates whether the task is prohibited to be terminated or not. Defaults to $false .PARAMETER Compatibility The task compatibility level. Defaults to Vista. Not used in Get-TargetResource. .PARAMETER AllowStartIfOnBatteries Indicates whether the task should start if the machine is on batteries or not. Defaults to $false. Not used in Get-TargetResource. .PARAMETER Hidden Indicates that the task is hidden in the Task Scheduler UI. Not used in Get-TargetResource. .PARAMETER RunOnlyIfIdle Indicates that Task Scheduler runs the task only when the computer is idle. Not used in Get-TargetResource. .PARAMETER IdleWaitTimeout Specifies the amount of time that Task Scheduler waits for an idle condition to occur. Not used in Get-TargetResource. .PARAMETER NetworkName Specifies the name of a network profile that Task Scheduler uses to determine if the task can run. The Task Scheduler UI uses this setting for display purposes. Specify a network name if you specify the RunOnlyIfNetworkAvailable parameter. Not used in Get-TargetResource. .PARAMETER DisallowStartOnRemoteAppSession Indicates that the task does not start if the task is triggered to run in a Remote Applications Integrated Locally (RAIL) session. Not used in Get-TargetResource. .PARAMETER StartWhenAvailable Indicates that Task Scheduler can start the task at any time after its scheduled time has passed. Not used in Get-TargetResource. .PARAMETER DontStopIfGoingOnBatteries Indicates that the task does not stop if the computer switches to battery power. Not used in Get-TargetResource. .PARAMETER WakeToRun Indicates that Task Scheduler wakes the computer before it runs the task. Not used in Get-TargetResource. .PARAMETER IdleDuration Specifies the amount of time that the computer must be in an idle state before Task Scheduler runs the task. Not used in Get-TargetResource. .PARAMETER RestartOnIdle Indicates that Task Scheduler restarts the task when the computer cycles into an idle condition more than once. Not used in Get-TargetResource. .PARAMETER DontStopOnIdleEnd Indicates that Task Scheduler does not terminate the task if the idle condition ends before the task is completed. Not used in Get-TargetResource. .PARAMETER ExecutionTimeLimit Specifies the amount of time that Task Scheduler is allowed to complete the task. Not used in Get-TargetResource. .PARAMETER MultipleInstances Specifies the policy that defines how Task Scheduler handles multiple instances of the task. Not used in Get-TargetResource. .PARAMETER Priority Specifies the priority level of the task. Priority must be an integer from 0 (highest priority) to 10 (lowest priority). The default value is 7. Priority levels 7 and 8 are used for background tasks. Priority levels 4, 5, and 6 are used for interactive tasks. Not used in Get-TargetResource. .PARAMETER RestartCount Specifies the number of times that Task Scheduler attempts to restart the task. Not used in Get-TargetResource. .PARAMETER RestartInterval Specifies the amount of time that Task Scheduler attempts to restart the task. Not used in Get-TargetResource. .PARAMETER RunOnlyIfNetworkAvailable Indicates that Task Scheduler runs the task only when a network is available. Task Scheduler uses the NetworkID parameter and NetworkName parameter that you specify in this cmdlet to determine if the network is available. Not used in Get-TargetResource. .PARAMETER RunLevel Specifies the level of user rights that Task Scheduler uses to run the tasks that are associated with the principal. Defaults to 'Limited'. Not used in Get-TargetResource. .PARAMETER LogonType Specifies the security logon method that Task Scheduler uses to run the tasks that are associated with the principal. Not used in Get-TargetResource. #> function Get-TargetResource { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [Parameter(Mandatory = $true)] [System.String] $TaskName, [Parameter()] [System.String] $TaskPath = '\', [Parameter()] [System.String] $Description, [Parameter()] [System.String] $ActionExecutable, [Parameter()] [System.String] $ActionArguments, [Parameter()] [System.String] $ActionWorkingPath, [Parameter()] [System.String] [ValidateSet('Once', 'Daily', 'Weekly', 'AtStartup', 'AtLogOn')] $ScheduleType, [Parameter()] [System.String] $RepeatInterval = '00:00:00', [Parameter()] [System.DateTime] $StartTime = [System.DateTime]::Today, [Parameter()] [System.String] [ValidateSet('Present', 'Absent')] $Ensure = 'Present', [Parameter()] [System.Boolean] $Enable = $true, [Parameter()] [System.Management.Automation.PSCredential] $ExecuteAsCredential, [Parameter()] [System.UInt32] $DaysInterval = 1, [Parameter()] [System.String] $RandomDelay = '00:00:00', [Parameter()] [System.String] $RepetitionDuration = '00:00:00', [Parameter()] [System.String[]] $DaysOfWeek, [Parameter()] [System.UInt32] $WeeksInterval = 1, [Parameter()] [System.String] $User, [Parameter()] [System.Boolean] $DisallowDemandStart = $false, [Parameter()] [System.Boolean] $DisallowHardTerminate = $false, [Parameter()] [ValidateSet('AT', 'V1', 'Vista', 'Win7', 'Win8')] [System.String] $Compatibility = 'Vista', [Parameter()] [System.Boolean] $AllowStartIfOnBatteries = $false, [Parameter()] [System.Boolean] $Hidden = $false, [Parameter()] [System.Boolean] $RunOnlyIfIdle = $false, [Parameter()] [System.String] $IdleWaitTimeout = '02:00:00', [Parameter()] [System.String] $NetworkName, [Parameter()] [System.Boolean] $DisallowStartOnRemoteAppSession = $false, [Parameter()] [System.Boolean] $StartWhenAvailable = $false, [Parameter()] [System.Boolean] $DontStopIfGoingOnBatteries = $false, [Parameter()] [System.Boolean] $WakeToRun = $false, [Parameter()] [System.String] $IdleDuration = '01:00:00', [Parameter()] [System.Boolean] $RestartOnIdle = $false, [Parameter()] [System.Boolean] $DontStopOnIdleEnd = $false, [Parameter()] [System.String] $ExecutionTimeLimit = '08:00:00', [Parameter()] [ValidateSet('IgnoreNew', 'Parallel', 'Queue')] [System.String] $MultipleInstances = 'Queue', [Parameter()] [System.UInt32] $Priority = 7, [Parameter()] [System.UInt32] $RestartCount = 0, [Parameter()] [System.String] $RestartInterval = '00:00:00', [Parameter()] [System.Boolean] $RunOnlyIfNetworkAvailable = $false, [Parameter()] [ValidateSet('Limited', 'Highest')] [System.String] $RunLevel = 'Limited', [Parameter()] [ValidateSet('Group', 'Interactive', 'InteractiveOrPassword', 'None', 'Password', 'S4U', 'ServiceAccount')] [System.String] $LogonType ) $TaskPath = ConvertTo-NormalizedTaskPath -TaskPath $TaskPath Write-Verbose -Message ($script:localizedData.GetScheduledTaskMessage -f $TaskName, $TaskPath) $task = Get-ScheduledTask -TaskName $TaskName -TaskPath $TaskPath -ErrorAction SilentlyContinue if ($null -eq $task) { Write-Verbose -Message ($script:localizedData.TaskNotFoundMessage -f $TaskName, $TaskPath) return @{ TaskName = $TaskName TaskPath = $TaskPath Ensure = 'Absent' } } else { Write-Verbose -Message ($script:localizedData.TaskFoundMessage -f $TaskName, $TaskPath) $action = $task.Actions | Select-Object -First 1 $trigger = $task.Triggers | Select-Object -First 1 $settings = $task.Settings $returnScheduleType = 'Unknown' switch ($trigger.CimClass.CimClassName) { 'MSFT_TaskTimeTrigger' { $returnScheduleType = 'Once' break } 'MSFT_TaskDailyTrigger' { $returnScheduleType = 'Daily' break } 'MSFT_TaskWeeklyTrigger' { $returnScheduleType = 'Weekly' break } 'MSFT_TaskBootTrigger' { $returnScheduleType = 'AtStartup' break } 'MSFT_TaskLogonTrigger' { $returnScheduleType = 'AtLogon' break } default { New-InvalidArgumentException ` -Message ($script:localizedData.TriggerTypeError -f $trigger.CimClass.CimClassName) ` -ArgumentName CimClassName } } Write-Verbose -Message ($script:localizedData.DetectedScheduleTypeMessage -f $returnScheduleType) $daysOfWeek = @() foreach ($binaryAdductor in 1, 2, 4, 8, 16, 32, 64) { $day = $trigger.DaysOfWeek -band $binaryAdductor if ($day -ne 0) { $daysOfWeek += [xScheduledTask.DaysOfWeek] $day } } $startAt = $trigger.StartBoundary if ($startAt) { $startAt = [System.DateTime] $startAt } else { $startAt = $StartTime } return @{ TaskName = $task.TaskName TaskPath = $task.TaskPath StartTime = $startAt Ensure = 'Present' Description = $task.Description ActionExecutable = $action.Execute ActionArguments = $action.Arguments ActionWorkingPath = $action.WorkingDirectory ScheduleType = $returnScheduleType RepeatInterval = ConvertTo-TimeSpanStringFromScheduledTaskString -TimeSpan $trigger.Repetition.Interval ExecuteAsCredential = $task.Principal.UserId Enable = $settings.Enabled DaysInterval = $trigger.DaysInterval RandomDelay = ConvertTo-TimeSpanStringFromScheduledTaskString -TimeSpan $trigger.RandomDelay RepetitionDuration = ConvertTo-TimeSpanStringFromScheduledTaskString -TimeSpan $trigger.Repetition.Duration -AllowIndefinitely DaysOfWeek = $daysOfWeek WeeksInterval = $trigger.WeeksInterval User = $task.Principal.UserId DisallowDemandStart = -not $settings.AllowDemandStart DisallowHardTerminate = -not $settings.AllowHardTerminate Compatibility = $settings.Compatibility AllowStartIfOnBatteries = -not $settings.DisallowStartIfOnBatteries Hidden = $settings.Hidden RunOnlyIfIdle = $settings.RunOnlyIfIdle IdleWaitTimeout = ConvertTo-TimeSpanStringFromScheduledTaskString -TimeSpan $settings.IdleSettings.IdleWaitTimeout NetworkName = $settings.NetworkSettings.Name DisallowStartOnRemoteAppSession = $settings.DisallowStartOnRemoteAppSession StartWhenAvailable = $settings.StartWhenAvailable DontStopIfGoingOnBatteries = -not $settings.StopIfGoingOnBatteries WakeToRun = $settings.WakeToRun IdleDuration = ConvertTo-TimeSpanStringFromScheduledTaskString -TimeSpan $settings.IdleSettings.IdleDuration RestartOnIdle = $settings.IdleSettings.RestartOnIdle DontStopOnIdleEnd = -not $settings.IdleSettings.StopOnIdleEnd ExecutionTimeLimit = ConvertTo-TimeSpanStringFromScheduledTaskString -TimeSpan $settings.ExecutionTimeLimit MultipleInstances = $settings.MultipleInstances Priority = $settings.Priority RestartCount = $settings.RestartCount RestartInterval = ConvertTo-TimeSpanStringFromScheduledTaskString -TimeSpan $settings.RestartInterval RunOnlyIfNetworkAvailable = $settings.RunOnlyIfNetworkAvailable RunLevel = [System.String] $task.Principal.RunLevel LogonType = [System.String] $task.Principal.LogonType } } } <# .SYNOPSIS Tests if the current resource state matches the desired resource state. .PARAMETER TaskName The name of the task. .PARAMETER TaskPath The path to the task - defaults to the root directory. .PARAMETER Description The task description. .PARAMETER ActionExecutable The path to the .exe for this task. .PARAMETER ActionArguments The arguments to pass the executable. .PARAMETER ActionWorkingPath The working path to specify for the executable. .PARAMETER ScheduleType When should the task be executed. .PARAMETER RepeatInterval How many units (minutes, hours, days) between each run of this task? .PARAMETER StartTime The time of day this task should start at - defaults to 12:00 AM. Not valid for AtLogon and AtStartup tasks. .PARAMETER Ensure Present if the task should exist, Absent if it should be removed. .PARAMETER Enable True if the task should be enabled, false if it should be disabled. .PARAMETER ExecuteAsCredential The credential this task should execute as. If not specified defaults to running as the local system account. .PARAMETER DaysInterval Specifies the interval between the days in the schedule. An interval of 1 produces a daily schedule. An interval of 2 produces an every-other day schedule. .PARAMETER RandomDelay Specifies a random amount of time to delay the start time of the trigger. The delay time is a random time between the time the task triggers and the time that you specify in this setting. .PARAMETER RepetitionDuration Specifies how long the repetition pattern repeats after the task starts. .PARAMETER DaysOfWeek Specifies an array of the days of the week on which Task Scheduler runs the task. .PARAMETER WeeksInterval Specifies the interval between the weeks in the schedule. An interval of 1 produces a weekly schedule. An interval of 2 produces an every-other week schedule. .PARAMETER User Specifies the identifier of the user for a trigger that starts a task when a user logs on. .PARAMETER DisallowDemandStart Indicates whether the task is prohibited to run on demand or not. Defaults to $false. .PARAMETER DisallowHardTerminate Indicates whether the task is prohibited to be terminated or not. Defaults to $false. .PARAMETER Compatibility The task compatibility level. Defaults to Vista. .PARAMETER AllowStartIfOnBatteries Indicates whether the task should start if the machine is on batteries or not. Defaults to $false. .PARAMETER Hidden Indicates that the task is hidden in the Task Scheduler UI. .PARAMETER RunOnlyIfIdle Indicates that Task Scheduler runs the task only when the computer is idle. .PARAMETER IdleWaitTimeout Specifies the amount of time that Task Scheduler waits for an idle condition to occur. .PARAMETER NetworkName Specifies the name of a network profile that Task Scheduler uses to determine if the task can run. The Task Scheduler UI uses this setting for display purposes. Specify a network name if you specify the RunOnlyIfNetworkAvailable parameter. .PARAMETER DisallowStartOnRemoteAppSession Indicates that the task does not start if the task is triggered to run in a Remote Applications Integrated Locally (RAIL) session. .PARAMETER StartWhenAvailable Indicates that Task Scheduler can start the task at any time after its scheduled time has passed. .PARAMETER DontStopIfGoingOnBatteries Indicates that the task does not stop if the computer switches to battery power. .PARAMETER WakeToRun Indicates that Task Scheduler wakes the computer before it runs the task. .PARAMETER IdleDuration Specifies the amount of time that the computer must be in an idle state before Task Scheduler runs the task. .PARAMETER RestartOnIdle Indicates that Task Scheduler restarts the task when the computer cycles into an idle condition more than once. .PARAMETER DontStopOnIdleEnd Indicates that Task Scheduler does not terminate the task if the idle condition ends before the task is completed. .PARAMETER ExecutionTimeLimit Specifies the amount of time that Task Scheduler is allowed to complete the task. .PARAMETER MultipleInstances Specifies the policy that defines how Task Scheduler handles multiple instances of the task. .PARAMETER Priority Specifies the priority level of the task. Priority must be an integer from 0 (highest priority) to 10 (lowest priority). The default value is 7. Priority levels 7 and 8 are used for background tasks. Priority levels 4, 5, and 6 are used for interactive tasks. .PARAMETER RestartCount Specifies the number of times that Task Scheduler attempts to restart the task. .PARAMETER RestartInterval Specifies the amount of time that Task Scheduler attempts to restart the task. .PARAMETER RunOnlyIfNetworkAvailable Indicates that Task Scheduler runs the task only when a network is available. Task Scheduler uses the NetworkID parameter and NetworkName parameter that you specify in this cmdlet to determine if the network is available.\ .PARAMETER RunLevel Specifies the level of user rights that Task Scheduler uses to run the tasks that are associated with the principal. Defaults to 'Limited'. .PARAMETER LogonType Specifies the security logon method that Task Scheduler uses to run the tasks that are associated with the principal. #> function Set-TargetResource { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [System.String] $TaskName, [Parameter()] [System.String] $TaskPath = '\', [Parameter()] [System.String] $Description, [Parameter()] [System.String] $ActionExecutable, [Parameter()] [System.String] $ActionArguments, [Parameter()] [System.String] $ActionWorkingPath, [Parameter()] [System.String] [ValidateSet('Once', 'Daily', 'Weekly', 'AtStartup', 'AtLogOn')] $ScheduleType, [Parameter()] [System.String] $RepeatInterval = '00:00:00', [Parameter()] [System.DateTime] $StartTime = [System.DateTime]::Today, [Parameter()] [System.String] [ValidateSet('Present', 'Absent')] $Ensure = 'Present', [Parameter()] [System.Boolean] $Enable = $true, [Parameter()] [System.Management.Automation.PSCredential] $ExecuteAsCredential, [Parameter()] [System.UInt32] $DaysInterval = 1, [Parameter()] [System.String] $RandomDelay = '00:00:00', [Parameter()] [System.String] $RepetitionDuration = '00:00:00', [Parameter()] [System.String[]] $DaysOfWeek, [Parameter()] [System.UInt32] $WeeksInterval = 1, [Parameter()] [System.String] $User, [Parameter()] [System.Boolean] $DisallowDemandStart = $false, [Parameter()] [System.Boolean] $DisallowHardTerminate = $false, [Parameter()] [ValidateSet('AT', 'V1', 'Vista', 'Win7', 'Win8')] [System.String] $Compatibility = 'Vista', [Parameter()] [System.Boolean] $AllowStartIfOnBatteries = $false, [Parameter()] [System.Boolean] $Hidden = $false, [Parameter()] [System.Boolean] $RunOnlyIfIdle = $false, [Parameter()] [System.String] $IdleWaitTimeout = '02:00:00', [Parameter()] [System.String] $NetworkName, [Parameter()] [System.Boolean] $DisallowStartOnRemoteAppSession = $false, [Parameter()] [System.Boolean] $StartWhenAvailable = $false, [Parameter()] [System.Boolean] $DontStopIfGoingOnBatteries = $false, [Parameter()] [System.Boolean] $WakeToRun = $false, [Parameter()] [System.String] $IdleDuration = '01:00:00', [Parameter()] [System.Boolean] $RestartOnIdle = $false, [Parameter()] [System.Boolean] $DontStopOnIdleEnd = $false, [Parameter()] [System.String] $ExecutionTimeLimit = '08:00:00', [Parameter()] [ValidateSet('IgnoreNew', 'Parallel', 'Queue')] [System.String] $MultipleInstances = 'Queue', [Parameter()] [System.UInt32] $Priority = 7, [Parameter()] [System.UInt32] $RestartCount = 0, [Parameter()] [System.String] $RestartInterval = '00:00:00', [Parameter()] [System.Boolean] $RunOnlyIfNetworkAvailable = $false, [Parameter()] [ValidateSet('Limited', 'Highest')] [System.String] $RunLevel = 'Limited', [Parameter()] [ValidateSet('Group', 'Interactive', 'InteractiveOrPassword', 'None', 'Password', 'S4U', 'ServiceAccount')] [System.String] $LogonType ) $TaskPath = ConvertTo-NormalizedTaskPath -TaskPath $TaskPath Write-Verbose -Message ($script:localizedData.SetScheduledTaskMessage -f $TaskName, $TaskPath) # Convert the strings containing time spans to TimeSpan Objects [System.TimeSpan] $RepeatInterval = ConvertTo-TimeSpanFromTimeSpanString -TimeSpanString $RepeatInterval [System.TimeSpan] $RandomDelay = ConvertTo-TimeSpanFromTimeSpanString -TimeSpanString $RandomDelay [System.TimeSpan] $RepetitionDuration = ConvertTo-TimeSpanFromTimeSpanString -TimeSpanString $RepetitionDuration -AllowIndefinitely [System.TimeSpan] $IdleWaitTimeout = ConvertTo-TimeSpanFromTimeSpanString -TimeSpanString $IdleWaitTimeout [System.TimeSpan] $IdleDuration = ConvertTo-TimeSpanFromTimeSpanString -TimeSpanString $IdleDuration [System.TimeSpan] $ExecutionTimeLimit = ConvertTo-TimeSpanFromTimeSpanString -TimeSpanString $ExecutionTimeLimit [System.TimeSpan] $RestartInterval = ConvertTo-TimeSpanFromTimeSpanString -TimeSpanString $RestartInterval $currentValues = Get-TargetResource @PSBoundParameters if ($Ensure -eq 'Present') { <# If the scheduled task already exists and is enabled but it needs to be disabled and the action executable isn't specified then disable the task #> if ($currentValues.Ensure -eq 'Present' ` -and $currentValues.Enable ` -and -not $Enable ` -and -not $PSBoundParameters.ContainsKey('ActionExecutable')) { Write-Verbose -Message ($script:localizedData.DisablingExistingScheduledTask -f $TaskName, $TaskPath) Disable-ScheduledTask -TaskName $TaskName -TaskPath $TaskPath return } if ($RepetitionDuration -lt $RepeatInterval) { New-InvalidArgumentException ` -Message ($script:localizedData.RepetitionDurationLessThanIntervalError -f $RepetitionDuration, $RepeatInterval) ` -ArgumentName RepeatInterval } if ($ScheduleType -eq 'Daily' -and $DaysInterval -eq 0) { New-InvalidArgumentException ` -Message ($script:localizedData.DaysIntervalError -f $DaysInterval) ` -ArgumentName DaysInterval } if ($ScheduleType -eq 'Weekly' -and $WeeksInterval -eq 0) { New-InvalidArgumentException ` -Message ($script:localizedData.WeeksIntervalError -f $WeeksInterval) ` -ArgumentName WeeksInterval } if ($ScheduleType -eq 'Weekly' -and $DaysOfWeek.Count -eq 0) { New-InvalidArgumentException ` -Message ($script:localizedData.WeekDayMissingError) ` -ArgumentName DaysOfWeek } # Configure the action $actionParameters = @{ Execute = $ActionExecutable } if ($ActionArguments) { $actionParameters.Add('Argument', $ActionArguments) } if ($ActionWorkingPath) { $actionParameters.Add('WorkingDirectory', $ActionWorkingPath) } $action = New-ScheduledTaskAction @actionParameters $scheduledTaskArguments += @{ Action = $action } # Configure the settings $settingParameters = @{ DisallowDemandStart = $DisallowDemandStart DisallowHardTerminate = $DisallowHardTerminate Compatibility = $Compatibility AllowStartIfOnBatteries = $AllowStartIfOnBatteries Disable = -not $Enable Hidden = $Hidden RunOnlyIfIdle = $RunOnlyIfIdle DisallowStartOnRemoteAppSession = $DisallowStartOnRemoteAppSession StartWhenAvailable = $StartWhenAvailable DontStopIfGoingOnBatteries = $DontStopIfGoingOnBatteries WakeToRun = $WakeToRun RestartOnIdle = $RestartOnIdle DontStopOnIdleEnd = $DontStopOnIdleEnd MultipleInstances = $MultipleInstances Priority = $Priority RestartCount = $RestartCount RunOnlyIfNetworkAvailable = $RunOnlyIfNetworkAvailable } if ($IdleDuration -gt [System.TimeSpan] '00:00:00') { $settingParameters.Add('IdleDuration', $IdleDuration) } if ($IdleWaitTimeout -gt [System.TimeSpan] '00:00:00') { $settingParameters.Add('IdleWaitTimeout', $IdleWaitTimeout) } if ($PSBoundParameters.ContainsKey('ExecutionTimeLimit')) { $settingParameters.Add('ExecutionTimeLimit', $ExecutionTimeLimit) } if ($RestartInterval -gt [System.TimeSpan] '00:00:00') { $settingParameters.Add('RestartInterval', $RestartInterval) } if (-not [System.String]::IsNullOrWhiteSpace($NetworkName)) { $settingParameters.Add('NetworkName', $NetworkName) } $setting = New-ScheduledTaskSettingsSet @settingParameters $scheduledTaskArguments += @{ Settings = $setting } <# On Windows Server 2012 R2 setting a blank timespan for ExecutionTimeLimit does not result in the PT0S timespan value being set. So set this if it has not been set. #> if ($PSBoundParameters.ContainsKey('ExecutionTimeLimit') -and ` [System.String]::IsNullOrEmpty($setting.ExecutionTimeLimit)) { $setting.ExecutionTimeLimit = 'PT0S' } # Configure the trigger $triggerParameters = @{} if ($RandomDelay -gt [System.TimeSpan]::FromSeconds(0)) { $triggerParameters.Add('RandomDelay', $RandomDelay) } switch ($ScheduleType) { 'Once' { $triggerParameters.Add('Once', $true) $triggerParameters.Add('At', $StartTime) break } 'Daily' { $triggerParameters.Add('Daily', $true) $triggerParameters.Add('At', $StartTime) $triggerParameters.Add('DaysInterval', $DaysInterval) break } 'Weekly' { $triggerParameters.Add('Weekly', $true) $triggerParameters.Add('At', $StartTime) if ($DaysOfWeek.Count -gt 0) { $triggerParameters.Add('DaysOfWeek', $DaysOfWeek) } if ($WeeksInterval -gt 0) { $triggerParameters.Add('WeeksInterval', $WeeksInterval) } break } 'AtStartup' { $triggerParameters.Add('AtStartup', $true) break } 'AtLogOn' { $triggerParameters.Add('AtLogOn', $true) if (-not [System.String]::IsNullOrWhiteSpace($User)) { $triggerParameters.Add('User', $User) } break } } $trigger = New-ScheduledTaskTrigger @triggerParameters -ErrorAction SilentlyContinue if (-not $trigger) { New-InvalidOperationException ` -Message ($script:localizedData.TriggerCreationError) ` -ErrorRecord $_ } if ($RepeatInterval -gt [System.TimeSpan]::Parse('0:0:0')) { # A repetition pattern is required so create it and attach it to the trigger object Write-Verbose -Message ($script:localizedData.ConfigureTriggerRepetitionMessage) if ($RepetitionDuration -le $RepeatInterval) { New-InvalidArgumentException ` -Message ($script:localizedData.RepetitionIntervalError -f $RepeatInterval, $RepetitionDuration) ` -ArgumentName RepetitionDuration } $tempTriggerParameters = @{ Once = $true At = '6:6:6' RepetitionInterval = $RepeatInterval } Write-Verbose -Message ($script:localizedData.CreateRepetitionPatternMessage) switch ($trigger.GetType().FullName) { 'Microsoft.PowerShell.ScheduledJob.ScheduledJobTrigger' { # This is the type of trigger object returned in Windows Server 2012 R2/Windows 8.1 and below Write-Verbose -Message ($script:localizedData.CreateTemporaryTaskMessage) $tempTriggerParameters.Add('RepetitionDuration', $RepetitionDuration) # Create a temporary trigger and task and copy the repetition CIM object from the temporary task $tempTrigger = New-ScheduledTaskTrigger @tempTriggerParameters $tempTask = New-ScheduledTask -Action $action -Trigger $tempTrigger # Store the repetition settings $repetition = $tempTask.Triggers[0].Repetition } 'Microsoft.Management.Infrastructure.CimInstance' { # This is the type of trigger object returned in Windows Server 2016/Windows 10 and above Write-Verbose -Message ($script:localizedData.CreateTemporaryTriggerMessage) if ($RepetitionDuration -gt [System.TimeSpan]::Parse('0:0:0') -and $RepetitionDuration -lt [System.TimeSpan]::MaxValue) { $tempTriggerParameters.Add('RepetitionDuration', $RepetitionDuration) } # Create a temporary trigger and copy the repetition CIM object from it to the actual trigger $tempTrigger = New-ScheduledTaskTrigger @tempTriggerParameters # Store the repetition settings $repetition = $tempTrigger.Repetition } default { New-InvalidOperationException ` -Message ($script:localizedData.TriggerUnexpectedTypeError -f $trigger.GetType().FullName) } } } $scheduledTaskArguments += @{ Trigger = $trigger } # Prepare the register arguments $registerArguments = @{ TaskName = $TaskName TaskPath = $TaskPath } if ($PSBoundParameters.ContainsKey('ExecuteAsCredential')) { $username = $ExecuteAsCredential.UserName $registerArguments.Add('User', $username) # If the LogonType is not specified then set it to password if ([System.String]::IsNullOrEmpty($LogonType)) { $LogonType = 'Password' } if ($LogonType -notin ('Interactive', 'S4U')) { # Only set the password if the LogonType is not interactive or S4U $registerArguments.Add('Password', $ExecuteAsCredential.GetNetworkCredential().Password) } } else { $username = 'NT AUTHORITY\SYSTEM' $registerArguments.Add('User', $username) $LogonType = 'ServiceAccount' } # Prepare the principal arguments $principalArguments = @{ Id = 'Author' UserId = $username LogonType = $LogonType } # Set the Run Level if defined if ($PSBoundParameters.ContainsKey('RunLevel')) { $principalArguments.Add('RunLevel', $RunLevel) } # Create the principal object Write-Verbose -Message ($script:localizedData.CreateScheduledTaskPrincipalMessage -f $username, $LogonType) $principal = New-ScheduledTaskPrincipal @principalArguments $scheduledTaskArguments += @{ Principal = $principal } if ($currentValues.Ensure -eq 'Present') { Write-Verbose -Message ($script:localizedData.RemovePreviousScheduledTaskMessage -f $TaskName, $TaskPath) $null = Unregister-ScheduledTask -TaskName $TaskName -TaskPath $TaskPath -Confirm:$false -ErrorAction Stop } Write-Verbose -Message ($script:localizedData.CreateNewScheduledTaskMessage -f $TaskName, $TaskPath) # Create the scheduled task object $scheduledTask = New-ScheduledTask @scheduledTaskArguments -ErrorAction Stop if ($repetition) { Write-Verbose -Message ($script:localizedData.SetRepetitionTriggerMessage -f $TaskName, $TaskPath) $scheduledTask.Triggers[0].Repetition = $repetition } if (-not [System.String]::IsNullOrWhiteSpace($Description)) { $scheduledTask.Description = $Description } # Register the scheduled task $registerArguments.Add('InputObject', $scheduledTask) Write-Verbose -Message ($script:localizedData.RegisterScheduledTaskMessage -f $TaskName, $TaskPath) $null = Register-ScheduledTask @registerArguments -ErrorAction Stop } if ($Ensure -eq 'Absent') { Write-Verbose -Message ($script:localizedData.RemoveScheduledTaskMessage -f $TaskName, $TaskPath) Unregister-ScheduledTask -TaskName $TaskName -TaskPath $TaskPath -Confirm:$false -ErrorAction Stop } } <# .SYNOPSIS Tests if the current resource state matches the desired resource state. .PARAMETER TaskName The name of the task. .PARAMETER TaskPath The path to the task - defaults to the root directory. .PARAMETER Description The task description. .PARAMETER ActionExecutable The path to the .exe for this task. .PARAMETER ActionArguments The arguments to pass the executable. .PARAMETER ActionWorkingPath The working path to specify for the executable. .PARAMETER ScheduleType When should the task be executed. .PARAMETER RepeatInterval How many units (minutes, hours, days) between each run of this task? .PARAMETER StartTime The time of day this task should start at - defaults to 12:00 AM. Not valid for AtLogon and AtStartup tasks. .PARAMETER Ensure Present if the task should exist, Absent if it should be removed. .PARAMETER Enable True if the task should be enabled, false if it should be disabled. .PARAMETER ExecuteAsCredential The credential this task should execute as. If not specified defaults to running as the local system account. .PARAMETER DaysInterval Specifies the interval between the days in the schedule. An interval of 1 produces a daily schedule. An interval of 2 produces an every-other day schedule. .PARAMETER RandomDelay Specifies a random amount of time to delay the start time of the trigger. The delay time is a random time between the time the task triggers and the time that you specify in this setting. .PARAMETER RepetitionDuration Specifies how long the repetition pattern repeats after the task starts. .PARAMETER DaysOfWeek Specifies an array of the days of the week on which Task Scheduler runs the task. .PARAMETER WeeksInterval Specifies the interval between the weeks in the schedule. An interval of 1 produces a weekly schedule. An interval of 2 produces an every-other week schedule. .PARAMETER User Specifies the identifier of the user for a trigger that starts a task when a user logs on. .PARAMETER DisallowDemandStart Indicates whether the task is prohibited to run on demand or not. Defaults to $false. .PARAMETER DisallowHardTerminate Indicates whether the task is prohibited to be terminated or not. Defaults to $false. .PARAMETER Compatibility The task compatibility level. Defaults to Vista. .PARAMETER AllowStartIfOnBatteries Indicates whether the task should start if the machine is on batteries or not. Defaults to $false. .PARAMETER Hidden Indicates that the task is hidden in the Task Scheduler UI. .PARAMETER RunOnlyIfIdle Indicates that Task Scheduler runs the task only when the computer is idle. .PARAMETER IdleWaitTimeout Specifies the amount of time that Task Scheduler waits for an idle condition to occur. .PARAMETER NetworkName Specifies the name of a network profile that Task Scheduler uses to determine if the task can run. The Task Scheduler UI uses this setting for display purposes. Specify a network name if you specify the RunOnlyIfNetworkAvailable parameter. .PARAMETER DisallowStartOnRemoteAppSession Indicates that the task does not start if the task is triggered to run in a Remote Applications Integrated Locally (RAIL) session. .PARAMETER StartWhenAvailable Indicates that Task Scheduler can start the task at any time after its scheduled time has passed. .PARAMETER DontStopIfGoingOnBatteries Indicates that the task does not stop if the computer switches to battery power. .PARAMETER WakeToRun Indicates that Task Scheduler wakes the computer before it runs the task. .PARAMETER IdleDuration Specifies the amount of time that the computer must be in an idle state before Task Scheduler runs the task. .PARAMETER RestartOnIdle Indicates that Task Scheduler restarts the task when the computer cycles into an idle condition more than once. .PARAMETER DontStopOnIdleEnd Indicates that Task Scheduler does not terminate the task if the idle condition ends before the task is completed. .PARAMETER ExecutionTimeLimit Specifies the amount of time that Task Scheduler is allowed to complete the task. .PARAMETER MultipleInstances Specifies the policy that defines how Task Scheduler handles multiple instances of the task. .PARAMETER Priority Specifies the priority level of the task. Priority must be an integer from 0 (highest priority) to 10 (lowest priority). The default value is 7. Priority levels 7 and 8 are used for background tasks. Priority levels 4, 5, and 6 are used for interactive tasks. .PARAMETER RestartCount Specifies the number of times that Task Scheduler attempts to restart the task. .PARAMETER RestartInterval Specifies the amount of time that Task Scheduler attempts to restart the task. .PARAMETER RunOnlyIfNetworkAvailable Indicates that Task Scheduler runs the task only when a network is available. Task Scheduler uses the NetworkID parameter and NetworkName parameter that you specify in this cmdlet to determine if the network is available. .PARAMETER RunLevel Specifies the level of user rights that Task Scheduler uses to run the tasks that are associated with the principal. Defaults to 'Limited'. .PARAMETER LogonType Specifies the security logon method that Task Scheduler uses to run the tasks that are associated with the principal. #> function Test-TargetResource { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [System.String] $TaskName, [Parameter()] [System.String] $TaskPath = '\', [Parameter()] [System.String] $Description, [Parameter()] [System.String] $ActionExecutable, [Parameter()] [System.String] $ActionArguments, [Parameter()] [System.String] $ActionWorkingPath, [Parameter()] [System.String] [ValidateSet('Once', 'Daily', 'Weekly', 'AtStartup', 'AtLogOn')] $ScheduleType, [Parameter()] [System.String] $RepeatInterval = '00:00:00', [Parameter()] [System.DateTime] $StartTime = [System.DateTime]::Today, [Parameter()] [System.String] [ValidateSet('Present', 'Absent')] $Ensure = 'Present', [Parameter()] [System.Boolean] $Enable = $true, [Parameter()] [System.Management.Automation.PSCredential] $ExecuteAsCredential, [Parameter()] [System.UInt32] $DaysInterval = 1, [Parameter()] [System.String] $RandomDelay = '00:00:00', [Parameter()] [System.String] $RepetitionDuration = '00:00:00', [Parameter()] [System.String[]] $DaysOfWeek, [Parameter()] [System.UInt32] $WeeksInterval = 1, [Parameter()] [System.String] $User, [Parameter()] [System.Boolean] $DisallowDemandStart = $false, [Parameter()] [System.Boolean] $DisallowHardTerminate = $false, [Parameter()] [ValidateSet('AT', 'V1', 'Vista', 'Win7', 'Win8')] [System.String] $Compatibility = 'Vista', [Parameter()] [System.Boolean] $AllowStartIfOnBatteries = $false, [Parameter()] [System.Boolean] $Hidden = $false, [Parameter()] [System.Boolean] $RunOnlyIfIdle = $false, [Parameter()] [System.String] $IdleWaitTimeout = '02:00:00', [Parameter()] [System.String] $NetworkName, [Parameter()] [System.Boolean] $DisallowStartOnRemoteAppSession = $false, [Parameter()] [System.Boolean] $StartWhenAvailable = $false, [Parameter()] [System.Boolean] $DontStopIfGoingOnBatteries = $false, [Parameter()] [System.Boolean] $WakeToRun = $false, [Parameter()] [System.String] $IdleDuration = '01:00:00', [Parameter()] [System.Boolean] $RestartOnIdle = $false, [Parameter()] [System.Boolean] $DontStopOnIdleEnd = $false, [Parameter()] [System.String] $ExecutionTimeLimit = '08:00:00', [Parameter()] [ValidateSet('IgnoreNew', 'Parallel', 'Queue')] [System.String] $MultipleInstances = 'Queue', [Parameter()] [System.UInt32] $Priority = 7, [Parameter()] [System.UInt32] $RestartCount = 0, [Parameter()] [System.String] $RestartInterval = '00:00:00', [Parameter()] [System.Boolean] $RunOnlyIfNetworkAvailable = $false, [Parameter()] [ValidateSet('Limited', 'Highest')] [System.String] $RunLevel = 'Limited', [Parameter()] [ValidateSet('Group', 'Interactive', 'InteractiveOrPassword', 'None', 'Password', 'S4U', 'ServiceAccount')] [System.String] $LogonType ) $TaskPath = ConvertTo-NormalizedTaskPath -TaskPath $TaskPath Write-Verbose -Message ($script:localizedData.TestScheduledTaskMessage -f $TaskName, $TaskPath) # Convert the strings containing time spans to TimeSpan Objects if ($PSBoundParameters.ContainsKey('RepeatInterval')) { $PSBoundParameters['RepeatInterval'] = (ConvertTo-TimeSpanFromTimeSpanString -TimeSpanString $RepeatInterval).ToString() } if ($PSBoundParameters.ContainsKey('RandomDelay')) { $PSBoundParameters['RandomDelay'] = (ConvertTo-TimeSpanFromTimeSpanString -TimeSpanString $RandomDelay).ToString() } if ($PSBoundParameters.ContainsKey('RepetitionDuration')) { $RepetitionDuration = ConvertTo-TimeSpanFromTimeSpanString -TimeSpanString $RepetitionDuration -AllowIndefinitely if ($RepetitionDuration -eq [System.TimeSpan]::MaxValue) { $PSBoundParameters['RepetitionDuration'] = 'Indefinitely' } else { $PSBoundParameters['RepetitionDuration'] = $RepetitionDuration.ToString() } } if ($PSBoundParameters.ContainsKey('IdleWaitTimeout')) { $PSBoundParameters['IdleWaitTimeout'] = (ConvertTo-TimeSpanFromTimeSpanString -TimeSpanString $IdleWaitTimeout).ToString() } if ($PSBoundParameters.ContainsKey('IdleDuration')) { $PSBoundParameters['IdleDuration'] = (ConvertTo-TimeSpanFromTimeSpanString -TimeSpanString $IdleDuration).ToString() } if ($PSBoundParameters.ContainsKey('ExecutionTimeLimit')) { $PSBoundParameters['ExecutionTimeLimit'] = (ConvertTo-TimeSpanFromTimeSpanString -TimeSpanString $ExecutionTimeLimit).ToString() } if ($PSBoundParameters.ContainsKey('RestartInterval')) { $PSBoundParameters['RestartInterval'] = (ConvertTo-TimeSpanFromTimeSpanString -TimeSpanString $RestartInterval).ToString() } $currentValues = Get-TargetResource @PSBoundParameters Write-Verbose -Message ($script:localizedData.GetCurrentTaskValuesMessage) if ($Ensure -eq 'Absent' -and $currentValues.Ensure -eq 'Absent') { return $true } if ($null -eq $currentValues) { Write-Verbose -Message ($script:localizedData.CurrentTaskValuesNullMessage) return $false } if ($PSBoundParameters.ContainsKey('ExecuteAsCredential')) { # The password of the execution credential can not be compared $username = $ExecuteAsCredential.UserName $PSBoundParameters['ExecuteAsCredential'] = $username } $desiredValues = $PSBoundParameters $desiredValues.TaskPath = $TaskPath Write-Verbose -Message ($script:localizedData.TestingDscParameterStateMessage) return Test-DscParameterState -CurrentValues $currentValues -DesiredValues $desiredValues } <# .SYNOPSIS Helper function to convert TaskPath to the right form .PARAMETER TaskPath The path to the task #> function ConvertTo-NormalizedTaskPath { [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory = $true)] [System.String] $TaskPath ) $pathArray = $TaskPath.Split('\').Where( {$_}) if ($pathArray.Count -gt 0) { $TaskPath = "\$($pathArray -join '\')\" } return $TaskPath } <# .SYNOPSIS Helper function convert a standard timespan string into a TimeSpan object. It can support returning the maximum timespan if the AllowIndefinitely switch is set and the timespan is set to 'indefinte'. .PARAMETER TimeSpan The standard timespan string to convert to a TimeSpan object. .PARAMETER AllowIndefinitely Allow the keyword 'Indefinitely' to be translated into the maximum valid timespan. #> function ConvertTo-TimeSpanFromTimeSpanString { [CmdletBinding()] [OutputType([System.TimeSpan])] param ( [Parameter()] [System.String] $TimeSpanString = '00:00:00', [Parameter()] [Switch] $AllowIndefinitely ) if ($AllowIndefinitely -eq $True -and $TimeSpanString -eq 'Indefinitely') { return [System.TimeSpan]::MaxValue } return [System.TimeSpan]::Parse($TimeSpanString) } <# .SYNOPSIS Helper function convert a task schedule timespan string into a TimeSpan string. If AllowIndefinitely is set to true and the TimeSpan string is empty then return 'Indefinitely'. .PARAMETER TimeSpan The scheduled task timespan string to convert to a TimeSpan string. .PARAMETER AllowIndefinitely Allow an empty TimeSpan to return the keyword 'Indefinitely'. #> function ConvertTo-TimeSpanStringFromScheduledTaskString { [CmdletBinding()] [OutputType([System.String])] param ( [Parameter()] [System.String] $TimeSpan, [Parameter()] [Switch] $AllowIndefinitely ) # If AllowIndefinitely is true and the timespan is empty then return Indefinitely if ($AllowIndefinitely -eq $true -and [System.String]::IsNullOrEmpty($TimeSpan)) { return 'Indefinitely' } $days = $hours = $minutes = $seconds = 0 if ($TimeSpan -match 'P(?<Days>\d{0,3})D') { $days = $matches.Days } if ($TimeSpan -match '(?<Hours>\d{0,2})H') { $hours = $matches.Hours } if ($TimeSpan -match '(?<Minutes>\d{0,2})M') { $minutes = $matches.Minutes } if ($TimeSpan -match '(?<Seconds>\d{0,2})S') { $seconds = $matches.Seconds } return (New-TimeSpan -Days $days -Hours $hours -Minutes $minutes -Seconds $seconds).ToString() } <# .SYNOPSIS Helper function to disable an existing scheduled task. .PARAMETER TaskName The name of the task to disable. .PARAMETER TaskPath The path to the task to disable. #> function Disable-ScheduledTask { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [System.String] $TaskName, [Parameter()] [System.String] $TaskPath = '\' ) $existingTask = Get-ScheduledTask @PSBoundParameters $existingTask.Settings.Enabled = $false $null = $existingTask | Register-ScheduledTask @PSBoundParameters -Force } |