diff --git a/CHANGELOG.md b/CHANGELOG.md
index 147f52b9..bddb9e06 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,6 +24,18 @@
- RemoteDesktopAdmin:
- New resource for configuring Remote Desktop for Administration - fixes
[Issue #224](https://github.com/PowerShell/ComputerManagementDsc/issues/224).
+- Updated common function `Test-DscParameterState` to support ordered comparison
+ of arrays by copying function and tests from `NetworkingDsc` - fixes [Issue #250](https://github.com/PowerShell/ComputerManagementDsc/issues/250).
+- BREAKING CHANGE: ScheduledTask:
+ - Correct output type of `DaysInterval`,`StartTime`,`WeeksDaysOfWeek`,
+ and `WeeksInterval` parameters from `Get-TargetResource` to match MOF.
+ - Refactored `Get-TargetResource` to remove parameters that
+ are not key or required - fixes [Issue #249](https://github.com/PowerShell/ComputerManagementDsc/issues/249).
+ - Added function `Test-DateStringContainsTimeZone` to determine if a string
+ containing a date time includes a time zone.
+ - Enable verbose preference to be passed through to `Test-DscParameterState`.
+ - Changed `Test-TargetResource` so that `StartTime` is only compared for
+ trigger types `Daily`,`Weekly` or `Once`.
## 6.5.0.0
diff --git a/DSCResources/MSFT_ScheduledTask/MSFT_ScheduledTask.psm1 b/DSCResources/MSFT_ScheduledTask/MSFT_ScheduledTask.psm1
index 7f644106..6374e1f4 100644
--- a/DSCResources/MSFT_ScheduledTask/MSFT_ScheduledTask.psm1
+++ b/DSCResources/MSFT_ScheduledTask/MSFT_ScheduledTask.psm1
@@ -26,548 +26,34 @@ $script:localizedData = Get-LocalizedData -ResourceName 'MSFT_ScheduledTask'
<#
.SYNOPSIS
- Tests if the current resource state matches the desired resource state.
+ Gets the current state of the resource.
.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 SynchronizeAcrossTimeZone
- Enable the scheduled task option to synchronize across time zones. This is enabled
- by including the timezone offset in the scheduled task trigger. Defaults to false
- which does not include the timezone offset.
-
- .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 BuiltInAccount
- Run the task as one of the built in service accounts.
- When set ExecuteAsCredential will be ignored and LogonType will be set to 'ServiceAccount'
-
- .PARAMETER ExecuteAsCredential
- The credential this task should execute as. If not specified defaults to running
- as the local system account. Cannot be used in combination with ExecuteAsGMSA.
- Not used in Get-TargetResource.
-
- .PARAMETER ExecuteAsGMSA
- The gMSA (Group Managed Service Account) this task should execute as. Cannot be
- used in combination with ExecuteAsCredential.
- 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.
-
- .PARAMETER EventSubscription
- The event subscription in a string that can be parsed as valid XML. This parameter is only
- valid in combination with the OnEvent Schedule Type. For the query schema please check:
- https://docs.microsoft.com/en-us/windows/desktop/WES/queryschema-schema
-
- .PARAMETER Delay
- The time to wait after an event based trigger was triggered. This parameter is only
- valid in combination with the OnEvent Schedule Type.
#>
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', 'OnEvent')]
- $ScheduleType,
-
- [Parameter()]
- [System.String]
- $RepeatInterval = '00:00:00',
-
- [Parameter()]
- [System.DateTime]
- $StartTime = [System.DateTime]::Today,
-
- [Parameter()]
- [System.Boolean]
- $SynchronizeAcrossTimeZone = $false,
-
- [Parameter()]
- [System.String]
- [ValidateSet('Present', 'Absent')]
- $Ensure = 'Present',
-
- [Parameter()]
- [System.Boolean]
- $Enable = $true,
-
- [Parameter()]
- [ValidateSet('SYSTEM', 'LOCAL SERVICE', 'NETWORK SERVICE')]
- [System.String]
- $BuiltInAccount,
-
- [Parameter()]
- [System.Management.Automation.PSCredential]
- $ExecuteAsCredential,
-
- [Parameter()]
- [System.String]
- $ExecuteAsGMSA,
-
- [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,
-
- [Parameter()]
- [System.String]
- $EventSubscription,
-
- [Parameter()]
- [System.String]
- $Delay = '00:00:00'
- )
-
- $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
- }
-
- 'MSFT_TaskEventTrigger'
- {
- $returnScheduleType = 'OnEvent'
- break
- }
-
- default
- {
- $returnScheduleType = ''
- Write-Verbose -Message ($script:localizedData.TriggerTypeUnknown -f $trigger.CimClass.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 += [ScheduledTask.DaysOfWeek] $day
- }
- }
-
- $startAt = $trigger.StartBoundary
+ (
+ [Parameter(Mandatory = $true)]
+ [System.String]
+ $TaskName,
- if ($startAt)
- {
- $stringSynchronizeAcrossTimeZone = Get-DateTimeString -Date $startAt -SynchronizeAcrossTimeZone $true
- $returnSynchronizeAcrossTimeZone = $startAt -eq $stringSynchronizeAcrossTimeZone
- }
- else
- {
- $startAt = $StartTime
- $returnSynchronizeAcrossTimeZone = $false
- }
+ [Parameter()]
+ [System.String]
+ $TaskPath = '\'
+ )
- $result = @{
- TaskName = $task.TaskName
- TaskPath = $task.TaskPath
- StartTime = $startAt
- SynchronizeAcrossTimeZone = $returnSynchronizeAcrossTimeZone
- 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
- ExecuteAsGMSA = $task.Principal.UserId -replace '^.+\\|@.+', $null
- 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.WaitTimeout
- 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
- EventSubscription = $trigger.Subscription
- Delay = ConvertTo-TimeSpanStringFromScheduledTaskString -TimeSpan $trigger.Delay
- }
+ $TaskPath = ConvertTo-NormalizedTaskPath -TaskPath $TaskPath
- if (($result.ContainsKey('LogonType')) -and ($result['LogonType'] -ieq 'ServiceAccount'))
- {
- $result.Add('BuiltInAccount', $task.Principal.UserId)
- }
+ Write-Verbose -Message ($script:localizedData.GetScheduledTaskMessage -f $TaskName, $TaskPath)
- return $result
- }
+ return Get-CurrentResource @PSBoundParameters
}
<#
@@ -954,7 +440,7 @@ function Set-TargetResource
[System.TimeSpan] $ExecutionTimeLimit = ConvertTo-TimeSpanFromTimeSpanString -TimeSpanString $ExecutionTimeLimit
[System.TimeSpan] $RestartInterval = ConvertTo-TimeSpanFromTimeSpanString -TimeSpanString $RestartInterval
- $currentValues = Get-TargetResource @PSBoundParameters
+ $currentValues = Get-CurrentResource -TaskName $TaskName -TaskPath $TaskPath
if ($Ensure -eq 'Present')
{
@@ -1805,6 +1291,8 @@ function Test-TargetResource
Write-Verbose -Message ($script:localizedData.TestScheduledTaskMessage -f $TaskName, $TaskPath)
+ $currentValues = Get-CurrentResource -TaskName $TaskName -TaskPath $TaskPath
+
# Convert the strings containing time spans to TimeSpan Objects
if ($PSBoundParameters.ContainsKey('RepeatInterval'))
{
@@ -1861,11 +1349,30 @@ function Test-TargetResource
if ($ScheduleType -in @('Once', 'Daily', 'Weekly'))
{
$PSBoundParameters['StartTime'] = Get-DateTimeString -Date $StartTime -SynchronizeAcrossTimeZone $SynchronizeAcrossTimeZone
+ <#
+ If the current StartTime is null then we need to set it to
+ the desired StartTime (which defaults to Today if not passed)
+ so that the test does not fail.
+ #>
+ if ($currentValues['StartTime'])
+ {
+ $currentValues['StartTime'] = Get-DateTimeString `
+ -Date $currentValues['StartTime'] `
+ -SynchronizeAcrossTimeZone $currentValues['SynchronizeAcrossTimeZone']
+ }
+ else
+ {
+ $currentValues['StartTime'] = Get-DateTimeString `
+ -Date $StartTime `
+ -SynchronizeAcrossTimeZone $SynchronizeAcrossTimeZone
+ }
+ }
+ else
+ {
+ # Do not compare StartTime for triggers that aren't Once, Daily or Weekly.
+ $null = $PSBoundParameters.Remove('StartTime')
+ $null = $currentValues.Remove('StartTime')
}
-
- $currentValues = Get-TargetResource @PSBoundParameters
-
- Write-Verbose -Message ($script:localizedData.GetCurrentTaskValuesMessage)
if ($Ensure -eq 'Absent' -and $currentValues.Ensure -eq 'Absent')
{
@@ -1947,7 +1454,10 @@ function Test-TargetResource
Write-Verbose -Message ($script:localizedData.TestingDscParameterStateMessage)
- return Test-DscParameterState -CurrentValues $currentValues -DesiredValues $desiredValues
+ return Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$VerbosePreference
}
<#
@@ -2143,3 +1653,211 @@ Function Get-DateTimeString
return $returnDate
}
+
+<#
+ .SYNOPSIS
+ Returns the current values of the resource.
+
+ .PARAMETER TaskName
+ The name of the task.
+
+ .PARAMETER TaskPath
+ The path to the task - defaults to the root directory.
+#>
+function Get-CurrentResource
+{
+ [CmdletBinding()]
+ [OutputType([System.Collections.Hashtable])]
+ param
+ (
+ [Parameter(Mandatory = $true)]
+ [System.String]
+ $TaskName,
+
+ [Parameter()]
+ [System.String]
+ $TaskPath = '\'
+ )
+
+ $TaskPath = ConvertTo-NormalizedTaskPath -TaskPath $TaskPath
+
+ Write-Verbose -Message ($script:localizedData.GettingCurrentTaskValuesMessage -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)
+
+ $result = @{
+ 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
+ }
+
+ 'MSFT_TaskEventTrigger'
+ {
+ $returnScheduleType = 'OnEvent'
+ break
+ }
+
+ default
+ {
+ $returnScheduleType = ''
+ Write-Verbose -Message ($script:localizedData.TriggerTypeUnknown -f $trigger.CimClass.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 += [System.String][ScheduledTask.DaysOfWeek] $day
+ }
+ }
+
+ $startAt = $trigger.StartBoundary
+
+ if ($startAt)
+ {
+ $synchronizeAcrossTimeZone = Test-DateStringContainsTimeZone -DateString $startAt
+ $startTime = [System.DateTime] $startAt
+ }
+ else
+ {
+ $startTime = $null
+ $synchronizeAcrossTimeZone = $false
+ }
+
+ $result = @{
+ TaskName = $task.TaskName
+ TaskPath = $task.TaskPath
+ StartTime = $startTime
+ SynchronizeAcrossTimeZone = $synchronizeAcrossTimeZone
+ 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
+ ExecuteAsGMSA = $task.Principal.UserId -replace '^.+\\|@.+', $null
+ Enable = $settings.Enabled
+ DaysInterval = [System.Uint32] $trigger.DaysInterval
+ RandomDelay = ConvertTo-TimeSpanStringFromScheduledTaskString -TimeSpan $trigger.RandomDelay
+ RepetitionDuration = ConvertTo-TimeSpanStringFromScheduledTaskString -TimeSpan $trigger.Repetition.Duration -AllowIndefinitely
+ DaysOfWeek = [System.String[]] $daysOfWeek
+ WeeksInterval = [System.Uint32] $trigger.WeeksInterval
+ User = $task.Principal.UserId
+ DisallowDemandStart = -not $settings.AllowDemandStart
+ DisallowHardTerminate = -not $settings.AllowHardTerminate
+ Compatibility = [System.String] $settings.Compatibility
+ AllowStartIfOnBatteries = -not $settings.DisallowStartIfOnBatteries
+ Hidden = $settings.Hidden
+ RunOnlyIfIdle = $settings.RunOnlyIfIdle
+ IdleWaitTimeout = ConvertTo-TimeSpanStringFromScheduledTaskString -TimeSpan $settings.IdleSettings.WaitTimeout
+ 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
+ EventSubscription = $trigger.Subscription
+ Delay = ConvertTo-TimeSpanStringFromScheduledTaskString -TimeSpan $trigger.Delay
+ }
+
+ if (($result.ContainsKey('LogonType')) -and ($result['LogonType'] -ieq 'ServiceAccount'))
+ {
+ $result.Add('BuiltInAccount', $task.Principal.UserId)
+ }
+ }
+
+ Write-Verbose -Message ($script:localizedData.CurrentTaskValuesRetrievedMessage -f $TaskName, $TaskPath)
+
+ return $result
+}
+
+<#
+ .SYNOPSIS
+ Test if a date string contains a time zone.
+
+ .DESCRIPTION
+ This function returns true if the string contains a time
+ zone appended to it. This is used to determine if the
+ SynchronizeAcrossTimeZone parameter has been set in a
+ trigger.
+
+ .PARAMETER DateString
+ The date string to test.
+#>
+function Test-DateStringContainsTimeZone
+{
+ [CmdletBinding()]
+ [OutputType([System.Boolean])]
+ param
+ (
+ [Parameter(Mandatory = $true)]
+ [System.String]
+ $DateString
+ )
+
+ return $DateString.Contains('+')
+}
diff --git a/DSCResources/MSFT_ScheduledTask/en-US/MSFT_ScheduledTask.strings.psd1 b/DSCResources/MSFT_ScheduledTask/en-US/MSFT_ScheduledTask.strings.psd1
index e9cd9ad5..8e6ef841 100644
--- a/DSCResources/MSFT_ScheduledTask/en-US/MSFT_ScheduledTask.strings.psd1
+++ b/DSCResources/MSFT_ScheduledTask/en-US/MSFT_ScheduledTask.strings.psd1
@@ -29,7 +29,8 @@ ConvertFrom-StringData @'
RemoveScheduledTaskMessage = Removing scheduled task '{0}' from '{1}'.
UpdateScheduledTaskMessage = Updating scheduled task '{0}' in '{1}'.
TestScheduledTaskMessage = Testing scheduled task '{0}' in '{1}'.
- GetCurrentTaskValuesMessage = Current scheduled task values retrieved.
+ GettingCurrentTaskValuesMessage = Getting current scheduled task values for task '{0}' in '{1}'.
+ CurrentTaskValuesRetrievedMessage = Current scheduled task values for task '{0}' in '{1}' retrieved.
CurrentTaskValuesNullMessage = Current scheduled values were null.
TestingDscParameterStateMessage = Testing DSC parameter state.
'@
diff --git a/Modules/ComputerManagementDsc.Common/ComputerManagementDsc.Common.psm1 b/Modules/ComputerManagementDsc.Common/ComputerManagementDsc.Common.psm1
index 6454a886..ebad769f 100644
--- a/Modules/ComputerManagementDsc.Common/ComputerManagementDsc.Common.psm1
+++ b/Modules/ComputerManagementDsc.Common/ComputerManagementDsc.Common.psm1
@@ -209,22 +209,28 @@ function Remove-CommonParameter
<#
.SYNOPSIS
- Tests the status of DSC resource parameters
+ Tests the status of DSC resource parameters.
.DESCRIPTION
- This function tests the parameter status of DSC resource parameters against the current values present on the system
+ This function tests the parameter status of DSC resource parameters against the current values present on the system.
.PARAMETER CurrentValues
- A hashtable with the current values on the system, obtained by e.g. Get-TargetResource
+ A hashtable with the current values on the system, obtained by e.g. Get-TargetResource.
.PARAMETER DesiredValues
- The hashtable of desired values
+ The hashtable of desired values.
.PARAMETER ValuesToCheck
- The values to check if not all values should be checked
+ The values to check if not all values should be checked.
.PARAMETER TurnOffTypeChecking
- Indicates that the type of the parameter should not be checked
+ Indicates that the type of the parameter should not be checked.
+
+ .PARAMETER ReverseCheck
+ Indicates that a reverse check should be done. The current and desired state are swapped for another test.
+
+ .PARAMETER SortArrayValues
+ If the sorting of array values does not matter, values are sorted internally before doing the comparison.
#>
function Test-DscParameterState
{
@@ -232,7 +238,7 @@ function Test-DscParameterState
param
(
[Parameter(Mandatory = $true)]
- [System.Collections.Hashtable]
+ [System.Object]
$CurrentValues,
[Parameter(Mandatory = $true)]
@@ -245,11 +251,31 @@ function Test-DscParameterState
[Parameter()]
[switch]
- $TurnOffTypeChecking
+ $TurnOffTypeChecking,
+
+ [Parameter()]
+ [switch]
+ $ReverseCheck,
+
+ [Parameter()]
+ [switch]
+ $SortArrayValues
)
$returnValue = $true
+ if ($CurrentValues -is [Microsoft.Management.Infrastructure.CimInstance] -or
+ $CurrentValues -is [Microsoft.Management.Infrastructure.CimInstance[]])
+ {
+ $CurrentValues = ConvertTo-HashTable -CimInstance $CurrentValues
+ }
+
+ if ($DesiredValues -is [Microsoft.Management.Infrastructure.CimInstance] -or
+ $DesiredValues -is [Microsoft.Management.Infrastructure.CimInstance[]])
+ {
+ $DesiredValues = ConvertTo-HashTable -CimInstance $DesiredValues
+ }
+
$types = 'System.Management.Automation.PSBoundParametersDictionary', 'System.Collections.Hashtable', 'Microsoft.Management.Infrastructure.CimInstance'
if ($DesiredValues.GetType().FullName -notin $types)
@@ -259,6 +285,13 @@ function Test-DscParameterState
-ArgumentName 'DesiredValues'
}
+ if ($CurrentValues.GetType().FullName -notin $types)
+ {
+ New-InvalidArgumentException `
+ -Message ($script:localizedData.InvalidCurrentValuesError -f $CurrentValues.GetType().FullName) `
+ -ArgumentName 'CurrentValues'
+ }
+
if ($DesiredValues -is [Microsoft.Management.Infrastructure.CimInstance] -and -not $ValuesToCheck)
{
New-InvalidArgumentException `
@@ -279,24 +312,38 @@ function Test-DscParameterState
foreach ($key in $keyList)
{
- if ($null -ne $desiredValuesClean.$key)
+ $desiredValue = $desiredValuesClean.$key
+ $currentValue = $CurrentValues.$key
+
+ if ($desiredValue -is [Microsoft.Management.Infrastructure.CimInstance] -or
+ $desiredValue -is [Microsoft.Management.Infrastructure.CimInstance[]])
+ {
+ $desiredValue = ConvertTo-HashTable -CimInstance $desiredValue
+ }
+ if ($currentValue -is [Microsoft.Management.Infrastructure.CimInstance] -or
+ $currentValue -is [Microsoft.Management.Infrastructure.CimInstance[]])
+ {
+ $currentValue = ConvertTo-HashTable -CimInstance $currentValue
+ }
+
+ if ($null -ne $desiredValue)
{
- $desiredType = $desiredValuesClean.$key.GetType()
+ $desiredType = $desiredValue.GetType()
}
else
{
- $desiredType = [PSObject] @{
+ $desiredType = @{
Name = 'Unknown'
}
}
- if ($null -ne $CurrentValues.$key)
+ if ($null -ne $currentValue)
{
- $currentType = $CurrentValues.$key.GetType()
+ $currentType = $currentValue.GetType()
}
else
{
- $currentType = [PSObject] @{
+ $currentType = @{
Name = 'Unknown'
}
}
@@ -304,26 +351,26 @@ function Test-DscParameterState
if ($currentType.Name -ne 'Unknown' -and $desiredType.Name -eq 'PSCredential')
{
# This is a credential object. Compare only the user name
- if ($currentType.Name -eq 'PSCredential' -and $CurrentValues.$key.UserName -eq $desiredValuesClean.$key.UserName)
+ if ($currentType.Name -eq 'PSCredential' -and $currentValue.UserName -eq $desiredValue.UserName)
{
- Write-Verbose -Message ($script:localizedData.MatchPsCredentialUsernameMessage -f $CurrentValues.$key.UserName, $desiredValuesClean.$key.UserName)
+ Write-Verbose -Message ($script:localizedData.MatchPsCredentialUsernameMessage -f $currentValue.UserName, $desiredValue.UserName)
continue
}
else
{
- Write-Verbose -Message ($script:localizedData.NoMatchPsCredentialUsernameMessage -f $CurrentValues.$key.UserName, $desiredValuesClean.$key.UserName)
+ Write-Verbose -Message ($script:localizedData.NoMatchPsCredentialUsernameMessage -f $currentValue.UserName, $desiredValue.UserName)
$returnValue = $false
}
# Assume the string is our username when the matching desired value is actually a credential
- if ($currentType.Name -eq 'string' -and $CurrentValues.$key -eq $desiredValuesClean.$key.UserName)
+ if ($currentType.Name -eq 'string' -and $currentValue -eq $desiredValue.UserName)
{
- Write-Verbose -Message ($script:localizedData.MatchPsCredentialUsernameMessage -f $CurrentValues.$key, $desiredValuesClean.$key.UserName)
+ Write-Verbose -Message ($script:localizedData.MatchPsCredentialUsernameMessage -f $currentValue, $desiredValue.UserName)
continue
}
else
{
- Write-Verbose -Message ($script:localizedData.NoMatchPsCredentialUsernameMessage -f $CurrentValues.$key, $desiredValuesClean.$key.UserName)
+ Write-Verbose -Message ($script:localizedData.NoMatchPsCredentialUsernameMessage -f $currentValue, $desiredValue.UserName)
$returnValue = $false
}
}
@@ -333,14 +380,15 @@ function Test-DscParameterState
if (($desiredType.Name -ne 'Unknown' -and $currentType.Name -ne 'Unknown') -and
$desiredType.FullName -ne $currentType.FullName)
{
- Write-Verbose -Message ($script:localizedData.NoMatchTypeMismatchMessage -f $key, $currentType.Name, $desiredType.Name)
+ Write-Verbose -Message ($script:localizedData.NoMatchTypeMismatchMessage -f $key, $currentType.FullName, $desiredType.FullName)
+ $returnValue = $false
continue
}
}
- if ($CurrentValues.$key -eq $desiredValuesClean.$key -and -not $desiredType.IsArray)
+ if ($currentValue -eq $desiredValue -and -not $desiredType.IsArray)
{
- Write-Verbose -Message ($script:localizedData.MatchValueMessage -f $desiredType.Name, $key, $CurrentValues.$key, $desiredValuesClean.$key)
+ Write-Verbose -Message ($script:localizedData.MatchValueMessage -f $desiredType.FullName, $key, $currentValue, $desiredValue)
continue
}
@@ -355,41 +403,41 @@ function Test-DscParameterState
if (-not $checkDesiredValue)
{
- Write-Verbose -Message ($script:localizedData.MatchValueMessage -f $desiredType.Name, $key, $CurrentValues.$key, $desiredValuesClean.$key)
+ Write-Verbose -Message ($script:localizedData.MatchValueMessage -f $desiredType.FullName, $key, $currentValue, $desiredValue)
continue
}
if ($desiredType.IsArray)
{
- Write-Verbose -Message ($script:localizedData.TestDscParameterCompareMessage -f $key)
+ Write-Verbose -Message ($script:localizedData.TestDscParameterCompareMessage -f $key, $desiredType.FullName)
- if ($CurrentValues.$key.Count -eq 0 -and $DesiredValues.$key.Count -eq 0)
+ if (-not $currentValue -and -not $desiredValue)
{
- Write-Verbose -Message ($script:localizedData.MatchEmptyCollectionMessage -f $desiredType.Name, $key)
+ Write-Verbose -Message ($script:localizedData.MatchValueMessage -f $desiredType.FullName, $key, 'empty array', 'empty array')
continue
}
- <#
- This evaluation needs to be performed before the next evaluation,
- because we need to be able to handle when the current value
- is a zero item collection, meaning `-not $CurrentValues.$key`
- would otherwise return $true in the next evaluation.
- #>
- elseif ($CurrentValues.$key.Count -ne $DesiredValues.$key.Count)
+ elseif (-not $currentValue)
{
- Write-Verbose -Message ($script:localizedData.NoMatchValueDifferentCountMessage -f $desiredType.Name, $key, $CurrentValues.$key.Count, $desiredValuesClean.$key.Count)
+ Write-Verbose -Message ($script:localizedData.NoMatchValueMessage -f $desiredType.FullName, $key, $currentValue, $desiredValue)
$returnValue = $false
continue
}
- elseif (-not $CurrentValues.ContainsKey($key) -or -not $CurrentValues.$key)
+ elseif ($currentValue.Count -ne $desiredValue.Count)
{
- Write-Verbose -Message ($script:localizedData.NoMatchValueMessage -f $desiredType.Name, $key, $CurrentValues.$key, $desiredValuesClean.$key)
+ Write-Verbose -Message ($script:localizedData.NoMatchValueDifferentCountMessage -f $desiredType.FullName, $key, $currentValue.Count, $desiredValue.Count)
$returnValue = $false
continue
}
else
{
- $desiredArrayValues = $DesiredValues.$key
- $currentArrayValues = $CurrentValues.$key
+ $desiredArrayValues = $desiredValue
+ $currentArrayValues = $currentValue
+
+ if ($SortArrayValues)
+ {
+ $desiredArrayValues = $desiredArrayValues | Sort-Object
+ $currentArrayValues = $currentArrayValues | Sort-Object
+ }
for ($i = 0; $i -lt $desiredArrayValues.Count; $i++)
{
@@ -399,7 +447,7 @@ function Test-DscParameterState
}
else
{
- $desiredType = [PSObject]@{
+ $desiredType = @{
Name = 'Unknown'
}
}
@@ -410,7 +458,7 @@ function Test-DscParameterState
}
else
{
- $currentType = [PSObject]@{
+ $currentType = @{
Name = 'Unknown'
}
}
@@ -420,7 +468,7 @@ function Test-DscParameterState
if (($desiredType.Name -ne 'Unknown' -and $currentType.Name -ne 'Unknown') -and
$desiredType.FullName -ne $currentType.FullName)
{
- Write-Verbose -Message ($script:localizedData.NoMatchElementTypeMismatchMessage -f $key, $i, $currentType.Name, $desiredType.Name)
+ Write-Verbose -Message ($script:localizedData.NoMatchElementTypeMismatchMessage -f $key, $i, $currentType.FullName, $desiredType.FullName)
$returnValue = $false
continue
}
@@ -428,29 +476,64 @@ function Test-DscParameterState
if ($desiredArrayValues[$i] -ne $currentArrayValues[$i])
{
- Write-Verbose -Message ($script:localizedData.NoMatchElementValueMismatchMessage -f $i, $desiredType.Name, $key, $currentArrayValues[$i], $desiredArrayValues[$i])
+ Write-Verbose -Message ($script:localizedData.NoMatchElementValueMismatchMessage -f $i, $desiredType.FullName, $key, $currentArrayValues[$i], $desiredArrayValues[$i])
$returnValue = $false
continue
}
else
{
- Write-Verbose -Message ($script:localizedData.MatchElementValueMessage -f $i, $desiredType.Name, $key, $currentArrayValues[$i], $desiredArrayValues[$i])
+ Write-Verbose -Message ($script:localizedData.MatchElementValueMessage -f $i, $desiredType.FullName, $key, $currentArrayValues[$i], $desiredArrayValues[$i])
continue
}
}
}
}
+ elseif ($desiredType -eq [System.Collections.Hashtable] -and $currentType -eq [System.Collections.Hashtable])
+ {
+ $param = $PSBoundParameters
+ $param.CurrentValues = $currentValue
+ $param.DesiredValues = $desiredValue
+ $null = $param.Remove('ValuesToCheck')
+
+ if ($returnValue)
+ {
+ $returnValue = Test-DscParameterState @param
+ }
+ else
+ {
+ Test-DscParameterState @param | Out-Null
+ }
+ continue
+ }
else
{
- if ($desiredValuesClean.$key -ne $CurrentValues.$key)
+ if ($desiredValue -ne $currentValue)
{
- Write-Verbose -Message ($script:localizedData.NoMatchValueMessage -f $desiredType.Name, $key, $CurrentValues.$key, $desiredValuesClean.$key)
+ Write-Verbose -Message ($script:localizedData.NoMatchValueMessage -f $desiredType.FullName, $key, $currentValue, $desiredValue)
$returnValue = $false
}
}
}
+ if ($ReverseCheck)
+ {
+ Write-Verbose -Message $script:localizedData.StartingReverseCheck
+ $reverseCheckParameters = $PSBoundParameters
+ $reverseCheckParameters.CurrentValues = $DesiredValues
+ $reverseCheckParameters.DesiredValues = $CurrentValues
+ $null = $reverseCheckParameters.Remove('ReverseCheck')
+
+ if ($returnValue)
+ {
+ $returnValue = Test-DscParameterState @reverseCheckParameters
+ }
+ else
+ {
+ $null = Test-DscParameterState @reverseCheckParameters
+ }
+ }
+
Write-Verbose -Message ($script:localizedData.TestDscParameterResultMessage -f $returnValue)
return $returnValue
}
@@ -488,6 +571,94 @@ function Test-DscObjectHasProperty
return $false
}
+<#
+ .SYNOPSIS
+ Converts a hashtable into a CimInstance array.
+
+ .DESCRIPTION
+ This function is used to convert a hashtable into MSFT_KeyValuePair objects. These are stored as an CimInstance array.
+ DSC cannot handle hashtables but CimInstances arrays storing MSFT_KeyValuePair.
+
+ .PARAMETER Hashtable
+ A hashtable with the values to convert.
+
+ .OUTPUTS
+ An object array with CimInstance objects.
+#>
+function ConvertTo-CimInstance
+{
+ [CmdletBinding()]
+ [OutputType([System.Object[]])]
+ param
+ (
+ [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
+ [System.Collections.Hashtable]
+ $Hashtable
+ )
+
+ process
+ {
+ foreach ($item in $Hashtable.GetEnumerator())
+ {
+ New-CimInstance -ClassName MSFT_KeyValuePair -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{
+ Key = $item.Key
+ Value = if ($item.Value -is [array])
+ {
+ $item.Value -join ','
+ }
+ else
+ {
+ $item.Value
+ }
+ } -ClientOnly
+ }
+ }
+}
+
+<#
+ .SYNOPSIS
+ Converts CimInstances into a hashtable.
+
+ .DESCRIPTION
+ This function is used to convert a CimInstance array containing MSFT_KeyValuePair objects into a hashtable.
+
+ .PARAMETER CimInstance
+ An array of CimInstances or a single CimInstance object to convert.
+
+ .OUTPUTS
+ Hashtable
+#>
+function ConvertTo-HashTable
+{
+ [CmdletBinding()]
+ [OutputType([System.Collections.Hashtable])]
+ param
+ (
+ [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
+ [AllowEmptyCollection()]
+ [Microsoft.Management.Infrastructure.CimInstance[]]
+ $CimInstance
+ )
+
+ begin
+ {
+ $result = @{ }
+ }
+
+ process
+ {
+ foreach ($ci in $CimInstance)
+ {
+ $result.Add($ci.Key, $ci.Value)
+ }
+ }
+
+ end
+ {
+ $result
+ }
+}
+
<#
.SYNOPSIS
This function tests if a cmdlet exists.
diff --git a/Modules/ComputerManagementDsc.Common/en-US/ComputerManagementDsc.Common.strings.psd1 b/Modules/ComputerManagementDsc.Common/en-US/ComputerManagementDsc.Common.strings.psd1
index 9ebf9b09..8521aad6 100644
--- a/Modules/ComputerManagementDsc.Common/en-US/ComputerManagementDsc.Common.strings.psd1
+++ b/Modules/ComputerManagementDsc.Common/en-US/ComputerManagementDsc.Common.strings.psd1
@@ -1,18 +1,19 @@
ConvertFrom-StringData @'
- InvalidDesiredValuesError = Property 'DesiredValues' in Test-DscParameterState must be either a Hashtable or CimInstance. Type detected was '{0}'.
- InvalidValuesToCheckError = If 'DesiredValues' is a CimInstance then property 'ValuesToCheck' must contain a value.
- TestDscParameterCompareMessage = Comparing values in property '{0}'.
- MatchPsCredentialUsernameMessage = MATCH: PSCredential username match. Current state is '{0}' and desired state is '{1}'.
- NoMatchPsCredentialUsernameMessage = NOTMATCH: PSCredential username mismatch. Current state is '{0}' and desired state is '{1}'.
- NoMatchTypeMismatchMessage = NOTMATCH: Type mismatch for property '{0}' Current state type is '{1}' and desired type is '{2}'.
- MatchValueMessage = MATCH: Value (type '{0}') for property '{1}' does match. Current state is '{2}' and desired state is '{3}'.
- MatchEmptyCollectionMessage = MATCH: Value (type '{0}') for property '{1}' does match. Current state and desired state both have zero items in the collection.
- NoMatchValueMessage = NOTMATCH: Value (type '{0}') for property '{1}' does not match. Current state is '{2}' and desired state is '{3}'.
- NoMatchValueDifferentCountMessage = NOTMATCH: Value (type '{0}') for property '{1}' does have a different count. Current state count is '{2}' and desired state count is '{3}'.
- NoMatchElementTypeMismatchMessage = NOTMATCH: Type mismatch for property '{0}' Current state type of element [{1}] is '{2}' and desired type is '{3}'.
- NoMatchElementValueMismatchMessage = NOTMATCH: Value [{0}] (type '{1}') for property '{2}' does match. Current state is '{3}' and desired state is '{4}'.
- MatchElementValueMessage = MATCH: Value [{0}] (type '{1}') for property '{2}' does match. Current state is '{3}' and desired state is '{4}'.
- TestDscParameterResultMessage = Test-DscParameter result is '{0}'.
+ InvalidCurrentValuesError = Property 'CurrentValues' in Test-DscParameterState must be either a Hashtable, CimInstance or CimIntance[]. Type detected was '{0}'.
+ InvalidDesiredValuesError = Property 'DesiredValues' in Test-DscParameterState must be either a Hashtable or CimInstance. Type detected was '{0}'.
+ InvalidValuesToCheckError = If 'DesiredValues' is a CimInstance then property 'ValuesToCheck' must contain a value.
+ TestDscParameterCompareMessage = Comparing values in property '{0}' of type '{1}'.
+ MatchPsCredentialUsernameMessage = MATCH: PSCredential username match. Current state is '{0}' and desired state is '{1}'.
+ NoMatchPsCredentialUsernameMessage = NOTMATCH: PSCredential username mismatch. Current state is '{0}' and desired state is '{1}'.
+ NoMatchTypeMismatchMessage = NOTMATCH: Type mismatch for property '{0}' Current state type is '{1}' and desired type is '{2}'.
+ MatchValueMessage = MATCH: Value (type '{0}') for property '{1}' does match. Current state is '{2}' and desired state is '{3}'.
+ NoMatchValueMessage = NOTMATCH: Value (type '{0}') for property '{1}' does not match. Current state is '{2}' and desired state is '{3}'.
+ NoMatchValueDifferentCountMessage = NOTMATCH: Value (type '{0}') for property '{1}' does have a different count. Current state count is '{2}' and desired state count is '{3}'.
+ NoMatchElementTypeMismatchMessage = NOTMATCH: Type mismatch for property '{0}' Current state type of element [{1}] is '{2}' and desired type is '{3}'.
+ NoMatchElementValueMismatchMessage = NOTMATCH: Value [{0}] (type '{1}') for property '{2}' does match. Current state is '{3}' and desired state is '{4}'.
+ MatchElementValueMessage = MATCH: Value [{0}] (type '{1}') for property '{2}' does match. Current state is '{3}' and desired state is '{4}'.
+ TestDscParameterResultMessage = Test-DscParameter result is '{0}'.
+ StartingReverseCheck = Starting with a reverse check.
CurrentTimeZoneMessage = Current time zone is set to '{0}'.
GettingTimeZoneMessage = Getting current time zone using '{0}'.
SettingTimeZoneMessage = Setting time zone to '{0}' using '{1}'.
diff --git a/Tests/Integration/MSFT_SmbShare.Integration.Tests.ps1 b/Tests/Integration/MSFT_SmbShare.Integration.Tests.ps1
index 707ace10..c7fc4a2b 100644
--- a/Tests/Integration/MSFT_SmbShare.Integration.Tests.ps1
+++ b/Tests/Integration/MSFT_SmbShare.Integration.Tests.ps1
@@ -123,7 +123,7 @@ Describe "$($script:dcsResourceName)_Integration" {
}
It 'Should return $true when Test-DscConfiguration is run' {
- Test-DscConfiguration -Verbose | Should -Be 'True'
+ Test-DscConfiguration -Verbose | Should -BeTrue
}
}
@@ -190,7 +190,7 @@ Describe "$($script:dcsResourceName)_Integration" {
}
It 'Should return $true when Test-DscConfiguration is run' {
- Test-DscConfiguration -Verbose | Should -Be 'True'
+ Test-DscConfiguration -Verbose | Should -BeTrue
}
}
@@ -259,7 +259,7 @@ Describe "$($script:dcsResourceName)_Integration" {
}
It 'Should return $true when Test-DscConfiguration is run' {
- Test-DscConfiguration -Verbose | Should -Be 'True'
+ Test-DscConfiguration -Verbose | Should -BeTrue
}
}
@@ -311,7 +311,7 @@ Describe "$($script:dcsResourceName)_Integration" {
}
It 'Should return $true when Test-DscConfiguration is run' {
- Test-DscConfiguration -Verbose | Should -Be 'True'
+ Test-DscConfiguration -Verbose | Should -BeTrue
}
}
@@ -357,7 +357,7 @@ Describe "$($script:dcsResourceName)_Integration" {
}
It 'Should return $true when Test-DscConfiguration is run' {
- Test-DscConfiguration -Verbose | Should -Be 'True'
+ Test-DscConfiguration -Verbose | Should -BeTrue
}
}
@@ -403,7 +403,7 @@ Describe "$($script:dcsResourceName)_Integration" {
}
It 'Should return $true when Test-DscConfiguration is run' {
- Test-DscConfiguration -Verbose | Should -Be 'True'
+ Test-DscConfiguration -Verbose | Should -BeTrue
}
}
diff --git a/Tests/Unit/ComputerManagementDsc.Common.Tests.ps1 b/Tests/Unit/ComputerManagementDsc.Common.Tests.ps1
index 178a04cd..144b3f50 100644
--- a/Tests/Unit/ComputerManagementDsc.Common.Tests.ps1
+++ b/Tests/Unit/ComputerManagementDsc.Common.Tests.ps1
@@ -69,350 +69,907 @@ try
}
Describe 'ComputerManagementDsc.Common\Test-DscParameterState' {
- Context 'All current parameters match desired parameters' {
+ $verbose = $true
+
+ Context 'When testing single values' {
$currentValues = @{
- parameterString = 'a string'
- parameterBool = $true
- parameterInt = 99
- parameterArray = @( 'a', 'b', 'c' )
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a', 'b', 'c'
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v1', 'v2', 'v3'
+ }
}
- $desiredValues = [PSObject] @{
- parameterString = 'a string'
- parameterBool = $true
- parameterInt = 99
- parameterArray = @( 'a', 'b', 'c' )
+ Context 'When all values match' {
+ $desiredValues = [PSObject] @{
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a', 'b', 'c'
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v1', 'v2', 'v3'
+ }
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $true' {
+ $script:result | Should -Be $true
+ }
}
- $valuesToCheck = @(
- 'parameterString'
- 'parameterBool'
- 'ParameterInt'
- 'ParameterArray'
- )
+ Context 'When a string is mismatched' {
+ $desiredValues = [PSObject] @{
+ String = 'different string'
+ Bool = $true
+ Int = 99
+ Array = 'a', 'b', 'c'
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v1', 'v2', 'v3'
+ }
+ }
- It 'Should not throw exception' {
- { $script:result = Test-DscParameterState `
- -CurrentValues $currentValues `
- -DesiredValues $desiredValues `
- -ValuesToCheck $valuesToCheck `
- -Verbose } | Should -Not -Throw
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $false' {
+ $script:result | Should -Be $false
+ }
}
- It 'Should return $true' {
- $script:result | Should -BeTrue
+ Context 'When a boolean is mismatched' {
+ $desiredValues = [PSObject] @{
+ String = 'a string'
+ Bool = $false
+ Int = 99
+ Array = 'a', 'b', 'c'
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v1', 'v2', 'v3'
+ }
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $false' {
+ $script:result | Should -Be $false
+ }
}
- }
- Context 'The current parameters do not match desired parameters because a string mismatches' {
- $currentValues = @{
- parameterString = 'a string'
- parameterBool = $true
- parameterInt = 99
- parameterArray = @( 'a', 'b', 'c' )
+ Context 'When an int is mismatched' {
+ $desiredValues = [PSObject] @{
+ String = 'a string'
+ Bool = $true
+ Int = 1
+ Array = 'a', 'b', 'c'
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v1', 'v2', 'v3'
+ }
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $false' {
+ $script:result | Should -Be $false
+ }
}
- $desiredValues = [PSObject] @{
- parameterString = 'different string'
- parameterBool = $true
- parameterInt = 99
- parameterArray = @( 'a', 'b', 'c' )
+ Context 'When a type is mismatched' {
+ $desiredValues = [PSObject] @{
+ String = 'a string'
+ Bool = $true
+ Int = '99'
+ Array = 'a', 'b', 'c'
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $false' {
+ $script:result | Should -Be $false
+ }
}
- $valuesToCheck = @(
- 'parameterString'
- 'parameterBool'
- 'ParameterInt'
- 'ParameterArray'
- )
+ Context 'When a type is mismatched but TurnOffTypeChecking is used' {
+ $desiredValues = [PSObject] @{
+ String = 'a string'
+ Bool = $true
+ Int = '99'
+ Array = 'a', 'b', 'c'
+ }
- It 'Should not throw exception' {
- { $script:result = Test-DscParameterState `
- -CurrentValues $currentValues `
- -DesiredValues $desiredValues `
- -ValuesToCheck $valuesToCheck `
- -Verbose } | Should -Not -Throw
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -TurnOffTypeChecking `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $true' {
+ $script:result | Should -Be $true
+ }
}
- It 'Should return $false' {
- $script:result | Should -BeFalse
+ Context 'When a value is mismatched but valuesToCheck is used to exclude them' {
+ $desiredValues = [PSObject] @{
+ String = 'a string'
+ Bool = $false
+ Int = 1
+ Array = @( 'a', 'b' )
+ }
+
+ $valuesToCheck = @(
+ 'String'
+ )
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -ValuesToCheck $valuesToCheck `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $true' {
+ $script:result | Should -Be $true
+ }
}
}
- Context 'The current parameters do not match desired parameters because a boolean mismatches' {
- $currentValues = @{
- parameterString = 'a string'
- parameterBool = $true
- parameterInt = 99
- parameterArray = @( 'a', 'b', 'c' )
+ Context 'When testing array values' {
+ BeforeAll {
+ $currentValues = @{
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a', 'b', 'c', 1
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v1', 'v2', 'v3'
+ }
+ }
}
- $desiredValues = [PSObject] @{
- parameterString = 'a string'
- parameterBool = $false
- parameterInt = 99
- parameterArray = @( 'a', 'b', 'c' )
+ Context 'When array is missing a value' {
+ $desiredValues = [PSObject]@{
+ String = 'a string'
+ Bool = $true
+ Int = 1
+ Array = 'a', 'b', 'c'
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v1', 'v2', 'v3'
+ }
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $false' {
+ $script:result | Should -Be $false
+ }
}
- $valuesToCheck = @(
- 'parameterString'
- 'parameterBool'
- 'ParameterInt'
- 'ParameterArray'
- )
+ Context 'When array has an additional value' {
+ $desiredValues = [PSObject] @{
+ String = 'a string'
+ Bool = $true
+ Int = 1
+ Array = 'a', 'b', 'c', 1, 2
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
- It 'Should not throw exception' {
- { $script:result = Test-DscParameterState `
- -CurrentValues $currentValues `
- -DesiredValues $desiredValues `
- -ValuesToCheck $valuesToCheck `
- -Verbose } | Should -Not -Throw
+ It 'Should return $false' {
+ $script:result | Should -Be $false
+ }
}
- It 'Should return $false' {
- $script:result | Should -BeFalse
+ Context 'When array has a different value' {
+ $desiredValues = [PSObject] @{
+ String = 'a string'
+ Bool = $true
+ Int = 1
+ Array = 'a', 'x', 'c', 1
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $false' {
+ $script:result | Should -Be $false
+ }
}
- }
- Context 'The current parameters do not match desired parameters because a int mismatches' {
- $currentValues = @{
- parameterString = 'a string'
- parameterBool = $true
- parameterInt = 99
- parameterArray = @( 'a', 'b', 'c' )
+ Context 'When array has different order' {
+ $desiredValues = [PSObject] @{
+ String = 'a string'
+ Bool = $true
+ Int = 1
+ Array = 'c', 'b', 'a', 1
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $false' {
+ $script:result | Should -Be $false
+ }
}
- $desiredValues = [PSObject] @{
- parameterString = 'a string'
- parameterBool = $true
- parameterInt = 1
- parameterArray = @( 'a', 'b', 'c' )
+ Context 'When array has different order but SortArrayValues is used' {
+ $desiredValues = [PSObject] @{
+ String = 'a string'
+ Bool = $true
+ Int = 1
+ Array = 'c', 'b', 'a', 1
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -SortArrayValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $false' {
+ $script:result | Should -Be $false
+ }
}
- $valuesToCheck = @(
- 'parameterString'
- 'parameterBool'
- 'ParameterInt'
- 'ParameterArray'
- )
- It 'Should not throw exception' {
- { $script:result = Test-DscParameterState `
- -CurrentValues $currentValues `
- -DesiredValues $desiredValues `
- -ValuesToCheck $valuesToCheck `
- -Verbose } | Should -Not -Throw
+ Context 'When array has a value with a different type' {
+ $desiredValues = [PSObject] @{
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a', 'b', 'c', '1'
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $false' {
+ $script:result | Should -Be $false
+ }
}
- It 'Should return $false' {
- $script:result | Should -BeFalse
+ Context 'When array has a value with a different type but TurnOffTypeChecking is used' {
+ $desiredValues = [PSObject] @{
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a', 'b', 'c', '1'
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -TurnOffTypeChecking `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $true' {
+ $script:result | Should -Be $true
+ }
+ }
+
+ Context 'When both arrays are empty' {
+ $currentValues = @{
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = @()
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = @()
+ }
+ }
+
+ $desiredValues = [PSObject]@{
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = @()
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = @()
+ }
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $true' {
+ $script:result | Should -Be $true
+ }
}
}
- Context 'The current parameters do not match desired parameters because an array is missing a value' {
+ Context 'When testing hashtables' {
$currentValues = @{
- parameterString = 'a string'
- parameterBool = $true
- parameterInt = 99
- parameterArray = @( 'a', 'b', 'c' )
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a', 'b', 'c'
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v1', 'v2', 'v3', 99
+ }
}
- $desiredValues = [PSObject] @{
- parameterString = 'a string'
- parameterBool = $true
- parameterInt = 1
- parameterArray = @( 'a', 'b' )
+ Context 'When hashtable is missing a value' {
+ $desiredValues = [PSObject]@{
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a', 'b', 'c'
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v1', 'v2', 'v3'
+ }
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $false' {
+ $script:result | Should -Be $false
+ }
}
- $valuesToCheck = @(
- 'parameterString'
- 'parameterBool'
- 'ParameterInt'
- 'ParameterArray'
- )
+ Context 'When hashtable has an additional value' {
+ $desiredValues = [PSObject]@{
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a', 'b', 'c'
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v1', 'v2', 'v3', 99, 100
+ }
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
- It 'Should not throw exception' {
- { $script:result = Test-DscParameterState `
- -CurrentValues $currentValues `
- -DesiredValues $desiredValues `
- -ValuesToCheck $valuesToCheck `
- -Verbose } | Should -Not -Throw
+ It 'Should return $false' {
+ $script:result | Should -Be $false
+ }
}
- It 'Should return $false' {
- $script:result | Should -BeFalse
+ Context 'When hashtable has a different value' {
+ $desiredValues = [PSObject]@{
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a', 'b', 'c'
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'xx', 'v2', 'v3', 99
+ }
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $false' {
+ $script:result | Should -Be $false
+ }
}
- }
- Context 'The current parameters do not match desired parameters because an array has an additional value' {
- $currentValues = @{
- parameterString = 'a string'
- parameterBool = $true
- parameterInt = 99
- parameterArray = @( 'a', 'b', 'c' )
+ Context 'When an array in hashtable has different order' {
+ $desiredValues = [PSObject]@{
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a', 'b', 'c'
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v3', 'v2', 'v1', 99
+ }
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $false' {
+ $script:result | Should -Be $false
+ }
}
- $desiredValues = [PSObject] @{
- parameterString = 'a string'
- parameterBool = $true
- parameterInt = 1
- parameterArray = @( 'a', 'b', 'c', 'd' )
+ Context 'When an array in hashtable has different order but SortArrayValues is used' {
+ $desiredValues = [PSObject]@{
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a', 'b', 'c'
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v3', 'v2', 'v1', 99
+ }
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -SortArrayValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $true' {
+ $script:result | Should -Be $true
+ }
}
- $valuesToCheck = @(
- 'parameterString'
- 'parameterBool'
- 'ParameterInt'
- 'ParameterArray'
- )
- It 'Should not throw exception' {
- { $script:result = Test-DscParameterState `
- -CurrentValues $currentValues `
- -DesiredValues $desiredValues `
- -ValuesToCheck $valuesToCheck `
- -Verbose } | Should -Not -Throw
+ Context 'When hashtable has a value with a different type' {
+ $desiredValues = [PSObject]@{
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a', 'b', 'c'
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v1', 'v2', 'v3', '99'
+ }
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $false' {
+ $script:result | Should -Be $false
+ }
}
- It 'Should return $false' {
- $script:result | Should -BeFalse
+ Context 'When hashtable has a value with a different type but TurnOffTypeChecking is used' {
+ $desiredValues = [PSObject]@{
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a', 'b', 'c'
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v1', 'v2', 'v3', 99
+ }
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -TurnOffTypeChecking `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $true' {
+ $script:result | Should -Be $true
+ }
}
}
- Context 'The current parameters do not match desired parameters because an array has a different value' {
+ Context 'When testing CimInstances / hashtables' {
$currentValues = @{
- parameterString = 'a string'
- parameterBool = $true
- parameterInt = 99
- parameterArray = @( 'a', 'b', 'c' )
- }
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a', 'b', 'c'
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v1', 'v2', 'v3', 99
+ }
+ CimInstances = [CimInstance[]](ConvertTo-CimInstance -Hashtable @{
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a, b, c'
+ })
+ }
+
+ Context 'When everything matches' {
+ $desiredValues = [PSObject]@{
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a', 'b', 'c'
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v1', 'v2', 'v3', 99
+ }
+ CimInstances = [CimInstance[]](ConvertTo-CimInstance -Hashtable @{
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a, b, c'
+ })
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
- $desiredValues = [PSObject] @{
- parameterString = 'a string'
- parameterBool = $true
- parameterInt = 1
- parameterArray = @( 'a', 'd', 'c' )
+ It 'Should return $true' {
+ $script:result | Should -Be $true
+ }
}
- $valuesToCheck = @(
- 'parameterString'
- 'parameterBool'
- 'ParameterInt'
- 'ParameterArray'
- )
+ Context 'When CimInstances missing a value in the desired state (not recognized)' {
+ $desiredValues = [PSObject]@{
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a', 'b', 'c'
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v1', 'v2', 'v3', 99
+ }
+ CimInstances = @{
+ String = 'a string'
+ Bool = $true
+ Array = 'a, b, c'
+ }
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
- It 'Should not throw exception' {
- { $script:result = Test-DscParameterState `
- -CurrentValues $currentValues `
- -DesiredValues $desiredValues `
- -ValuesToCheck $valuesToCheck `
- -Verbose } | Should -Not -Throw
+ It 'Should return $true' {
+ $script:result | Should -Be $true
+ }
}
- It 'Should return $false' {
- $script:result | Should -BeFalse
+ Context 'When CimInstances missing a value in the desired state (recognized using ReverseCheck)' {
+ $desiredValues = [PSObject]@{
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a', 'b', 'c'
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v1', 'v2', 'v3', 99
+ }
+ CimInstances = @{
+ String = 'a string'
+ Bool = $true
+ Array = 'a, b, c'
+ }
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -ReverseCheck `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $false' {
+ $script:result | Should -Be $false
+ }
}
- }
- Context 'The current parameters do not match desired parameters because an array has a different type' {
- $currentValues = @{
- parameterString = 'a string'
- parameterBool = $true
- parameterInt = 99
- parameterArray = @( 'a', 'b', 'c' )
+ Context 'When CimInstances have an additional value' {
+ $desiredValues = [PSObject]@{
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a', 'b', 'c'
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v1', 'v2', 'v3', 99
+ }
+ CimInstances = @{
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a, b, c'
+ Test = 'Some string'
+ }
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $false' {
+ $script:result | Should -Be $false
+ }
}
- $desiredValues = [PSObject] @{
- parameterString = 'a string'
- parameterBool = $true
- parameterInt = 1
- parameterArray = @( 'a', 1, 'c' )
+ Context 'When CimInstances have a different value' {
+ $desiredValues = [PSObject]@{
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a', 'b', 'c'
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v1', 'v2', 'v3', 99
+ }
+ CimInstances = @{
+ String = 'some other string'
+ Bool = $true
+ Int = 99
+ Array = 'a, b, c'
+ }
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $false' {
+ $script:result | Should -Be $false
+ }
}
- $valuesToCheck = @(
- 'parameterString'
- 'parameterBool'
- 'ParameterInt'
- 'ParameterArray'
- )
+ Context 'When CimInstances have a value with a different type' {
+ $desiredValues = [PSObject]@{
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a', 'b', 'c'
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v1', 'v2', 'v3', 99
+ }
+ CimInstances = @{
+ String = 'a string'
+ Bool = $true
+ Int = '99'
+ Array = 'a, b, c'
+ }
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
- It 'Should not throw exception' {
- { $script:result = Test-DscParameterState `
- -CurrentValues $currentValues `
- -DesiredValues $desiredValues `
- -ValuesToCheck $valuesToCheck `
- -Verbose } | Should -Not -Throw
+ It 'Should return $false' {
+ $script:result | Should -Be $false
+ }
}
- It 'Should return $false' {
- $script:result | Should -BeFalse
+ Context 'When CimInstances have a value with a different type but TurnOffTypeChecking is used' {
+ $desiredValues = [PSObject]@{
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a', 'b', 'c'
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v1', 'v2', 'v3', 99
+ }
+ CimInstances = @{
+ String = 'a string'
+ Bool = $true
+ Int = '99'
+ Array = 'a, b, c'
+ }
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -TurnOffTypeChecking `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $true' {
+ $script:result | Should -Be $true
+ }
}
}
- Context 'The current parameters do not match desired parameters because a parameter has a different type' {
+ Context 'When reverse checking' {
$currentValues = @{
- parameterString = 'a string'
- parameterBool = $true
- parameterInt = 99
- parameterArray = @( 'a', 'b', 'c' )
+ String = 'a string'
+ Bool = $true
+ Int = 99
+ Array = 'a', 'b', 'c', 1
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v1', 'v2', 'v3'
+ }
}
- $desiredValues = [PSObject] @{
- parameterString = $false
- parameterBool = $true
- parameterInt = 1
- parameterArray = @( 'a', 'b', 'c' )
- }
+ Context 'When even if missing property in the desired state' {
+ $desiredValues = [PSObject] @{
+ Array = 'a', 'b', 'c', 1
+ Hashtable = @{
+ k1 = 'Test'
+ k2 = 123
+ k3 = 'v1', 'v2', 'v3'
+ }
+ }
- $valuesToCheck = @(
- 'parameterString'
- 'parameterBool'
- 'ParameterInt'
- 'ParameterArray'
- )
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
- It 'Should not throw exception' {
- { $script:result = Test-DscParameterState `
- -CurrentValues $currentValues `
- -DesiredValues $desiredValues `
- -ValuesToCheck $valuesToCheck `
- -Verbose } | Should -Not -Throw
+ It 'Should return $true' {
+ $script:result | Should -Be $true
+ }
}
- It 'Should return $false' {
- $script:result | Should -BeFalse
+ Context 'When missing property in the desired state' {
+ $currentValues = @{
+ String = 'a string'
+ Bool = $true
+ }
+
+ $desiredValues = [PSObject] @{
+ String = 'a string'
+ }
+
+ It 'Should not throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -ReverseCheck `
+ -Verbose:$verbose } | Should -Not -Throw
+ }
+
+ It 'Should return $false' {
+ $script:result | Should -Be $false
+ }
}
}
- Context 'Some of the current parameters do not match desired parameters but only matching parameter is compared' {
- $currentValues = @{
- parameterString = 'a string'
- parameterBool = $true
- parameterInt = 99
- parameterArray = @( 'a', 'b', 'c' )
- }
+ Context 'When testing parameter types' {
+ Context 'When desired value is of the wrong type' {
+ $currentValues = @{
+ String = 'a string'
+ }
+
+ $desiredValues = 1, 2, 3
- $desiredValues = [PSObject] @{
- parameterString = 'a string'
- parameterBool = $false
- parameterInt = 1
- parameterArray = @( 'a', 'b' )
+ It 'Should throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Throw
+ }
}
- $valuesToCheck = @(
- 'parameterString'
- )
+ Context 'When current value is of the wrong type' {
+ $currentValues = 1, 2, 3
- It 'Should not throw exception' {
- { $script:result = Test-DscParameterState `
- -CurrentValues $currentValues `
- -DesiredValues $desiredValues `
- -ValuesToCheck $valuesToCheck `
- -Verbose } | Should -Not -Throw
- }
+ $desiredValues = @{
+ String = 'a string'
+ }
- It 'Should return $true' {
- $script:result | Should -BeTrue
+ It 'Should throw exception' {
+ { $script:result = Test-DscParameterState `
+ -CurrentValues $currentValues `
+ -DesiredValues $desiredValues `
+ -Verbose:$verbose } | Should -Throw
+ }
}
}
}
@@ -421,23 +978,91 @@ try
# Use the Get-Verb cmdlet to just get a simple object fast
$testDscObject = (Get-Verb)[0]
- Context 'The object contains the expected property' {
+ Context 'When the object contains the expected property' {
It 'Should not throw exception' {
{ $script:result = Test-DscObjectHasProperty -Object $testDscObject -PropertyName 'Verb' -Verbose } | Should -Not -Throw
}
It 'Should return $true' {
- $script:result | Should -BeTrue
+ $script:result | Should -Be $true
}
}
- Context 'The object does not contain the expected property' {
+ Context 'When the object does not contain the expected property' {
It 'Should not throw exception' {
{ $script:result = Test-DscObjectHasProperty -Object $testDscObject -PropertyName 'Missing' -Verbose } | Should -Not -Throw
}
It 'Should return $false' {
- $script:result | Should -BeFalse
+ $script:result | Should -Be $false
+ }
+ }
+ }
+
+ Describe 'ComputerManagementDsc.Common\ConvertTo-CimInstance' {
+ $hashtable = @{
+ k1 = 'v1'
+ k2 = 100
+ k3 = 1, 2, 3
+ }
+
+ Context 'When the array contains the expected record count' {
+ It 'Should not throw exception' {
+ { $script:result = [CimInstance[]]($hashtable | ConvertTo-CimInstance) } | Should -Not -Throw
+ }
+
+ It "Should record count should be $($hashTable.Count)" {
+ $script:result.Count | Should -Be $hashtable.Count
+ }
+
+ It 'Should return result of type CimInstance[]' {
+ $script:result.GetType().Name | Should -Be 'CimInstance[]'
+ }
+
+ It 'Should return value "k1" in the CimInstance array should be "v1"' {
+ ($script:result | Where-Object Key -eq k1).Value | Should -Be 'v1'
+ }
+
+ It 'Should return value "k2" in the CimInstance array should be "100"' {
+ ($script:result | Where-Object Key -eq k2).Value | Should -Be 100
+ }
+
+ It 'Should return value "k3" in the CimInstance array should be "1,2,3"' {
+ ($script:result | Where-Object Key -eq k3).Value | Should -Be '1,2,3'
+ }
+ }
+ }
+
+ Describe 'ComputerManagementDsc.Common\ConvertTo-HashTable' {
+ [CimInstance[]]$cimInstances = ConvertTo-CimInstance -Hashtable @{
+ k1 = 'v1'
+ k2 = 100
+ k3 = 1, 2, 3
+ }
+
+ Context 'When the array contains the expected record count' {
+ It 'Should not throw exception' {
+ { $script:result = $cimInstances | ConvertTo-HashTable } | Should -Not -Throw
+ }
+
+ It "Should return record count of $($cimInstances.Count)" {
+ $script:result.Count | Should -Be $cimInstances.Count
+ }
+
+ It 'Should return result of type [System.Collections.Hashtable]' {
+ $script:result | Should -BeOfType [System.Collections.Hashtable]
+ }
+
+ It 'Should return value "k1" in the hashtable should be "v1"' {
+ $script:result.k1 | Should -Be 'v1'
+ }
+
+ It 'Should return value "k2" in the hashtable should be "100"' {
+ $script:result.k2 | Should -Be 100
+ }
+
+ It 'Should return value "k3" in the hashtable should be "1,2,3"' {
+ $script:result.k3 | Should -Be '1,2,3'
}
}
}
diff --git a/Tests/Unit/MSFT_ScheduledTask.Tests.ps1 b/Tests/Unit/MSFT_ScheduledTask.Tests.ps1
index fa625afe..da422210 100644
--- a/Tests/Unit/MSFT_ScheduledTask.Tests.ps1
+++ b/Tests/Unit/MSFT_ScheduledTask.Tests.ps1
@@ -94,12 +94,15 @@ try
Mock -CommandName Register-ScheduledTask
Mock -CommandName Set-ScheduledTask
Mock -CommandName Unregister-ScheduledTask
- }
- Context 'No scheduled task exists, but it should' {
- $testParameters = @{
+ $getTargetResourceParameters = @{
TaskName = 'Test task'
TaskPath = '\Test\'
+ }
+ }
+
+ Context 'No scheduled task exists, but it should' {
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
RepeatInterval = (New-TimeSpan -Minutes 15).ToString()
@@ -110,7 +113,7 @@ try
Mock -CommandName Get-ScheduledTask -MockWith { return $null }
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Absent'
}
@@ -124,9 +127,7 @@ try
}
Context 'A scheduled task exists, but it should not' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
RepeatInterval = (New-TimeSpan -Minutes 15).ToString()
@@ -157,7 +158,7 @@ try
} }
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Present'
}
@@ -172,9 +173,7 @@ try
}
Context 'A built-in scheduled task exists and is enabled, but it should be disabled' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
Enable = $false
Verbose = $true
}
@@ -201,7 +200,7 @@ try
} }
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Enable | Should -BeTrue
$result.Ensure | Should -Be 'Present'
}
@@ -217,9 +216,7 @@ try
}
Context 'A built-in scheduled task exists, but it should be absent' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
Ensure = 'Absent'
Verbose = $true
}
@@ -251,7 +248,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Enable | Should -BeTrue
$result.Ensure | Should -Be 'Present'
}
@@ -267,9 +264,7 @@ try
}
Context 'A scheduled task doesnt exist, and it should not' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
Ensure = 'Absent'
@@ -279,7 +274,7 @@ try
Mock -CommandName Get-ScheduledTask
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Absent'
}
@@ -289,9 +284,7 @@ try
}
Context 'A scheduled task with Once based repetition exists, but has the wrong settings' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
RepeatInterval = (New-TimeSpan -Minutes 15).ToString()
@@ -326,7 +319,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Present'
}
@@ -341,9 +334,7 @@ try
}
Context 'A scheduled task with minutes based repetition exists and has the correct settings' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
RepeatInterval = (New-TimeSpan -Minutes 15).ToString()
@@ -378,7 +369,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Present'
}
@@ -388,9 +379,7 @@ try
}
Context 'A scheduled task with hourly based repetition exists, but has the wrong settings' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
RepeatInterval = (New-TimeSpan -Hours 4).ToString()
@@ -425,7 +414,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Present'
}
@@ -440,9 +429,7 @@ try
}
Context 'A scheduled task with hourly based repetition exists and has the correct settings' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
RepeatInterval = (New-TimeSpan -Hours 4).ToString()
@@ -477,7 +464,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Present'
}
@@ -487,9 +474,7 @@ try
}
Context 'A scheduled task with daily based repetition exists, but has the wrong settings' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Daily'
DaysInterval = 3
@@ -523,7 +508,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Present'
}
@@ -538,9 +523,7 @@ try
}
Context 'A scheduled task with daily based repetition exists and has the correct settings' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Daily'
DaysInterval = 3
@@ -571,7 +554,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Present'
}
@@ -581,9 +564,7 @@ try
}
Context 'A scheduled task exists and is configured with the wrong execution account' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
RepeatInterval = (New-TimeSpan -Minutes 15).ToString()
@@ -619,7 +600,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Present'
}
@@ -634,9 +615,7 @@ try
}
Context 'A scheduled task exists and is configured with the wrong logon type' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
RepeatInterval = (New-TimeSpan -Minutes 15).ToString()
@@ -674,7 +653,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Present'
$result.LogonType | Should -Be 'Password'
}
@@ -690,9 +669,7 @@ try
}
Context 'A scheduled task exists and is configured with the wrong run level' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
RepeatInterval = (New-TimeSpan -Minutes 15).ToString()
@@ -730,7 +707,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Present'
$result.RunLevel | Should -Be 'Limited'
}
@@ -746,9 +723,7 @@ try
}
Context 'A scheduled task exists and is configured with the wrong working directory' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ActionWorkingPath = 'C:\Example'
ScheduleType = 'Once'
@@ -785,7 +760,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Present'
}
@@ -800,9 +775,7 @@ try
}
Context 'A scheduled task exists and is configured with the wrong executable arguments' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ActionArguments = '-File "C:\something\right.ps1"'
ScheduleType = 'Once'
@@ -839,7 +812,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Present'
}
@@ -854,9 +827,7 @@ try
}
Context 'A scheduled task is enabled and should be disabled' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
RepeatInterval = (New-TimeSpan -Minutes 15).ToString()
@@ -896,7 +867,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Present'
}
@@ -912,9 +883,7 @@ try
}
Context 'A scheduled task is enabled without an execution time limit and but has an execution time limit set' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
RepeatInterval = (New-TimeSpan -Minutes 15).ToString()
@@ -956,7 +925,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Present'
}
@@ -971,9 +940,7 @@ try
}
Context 'A scheduled task is enabled and has the correct settings' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
RepeatInterval = (New-TimeSpan -Minutes 15).ToString()
@@ -1025,7 +992,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Present'
}
@@ -1035,9 +1002,7 @@ try
}
Context 'A scheduled task is disabled and has the correct settings' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
RepeatInterval = (New-TimeSpan -Minutes 15).ToString()
@@ -1077,7 +1042,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Present'
}
@@ -1087,9 +1052,7 @@ try
}
Context 'A scheduled task is disabled but should be enabled' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
RepeatInterval = (New-TimeSpan -Minutes 15).ToString()
@@ -1129,7 +1092,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Present'
}
@@ -1144,9 +1107,7 @@ try
}
Context 'A Scheduled task exists, is disabled, and the optional parameter enable is not specified' -Fixture {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
RepeatInterval = (New-TimeSpan -Minutes 15).ToString()
@@ -1185,7 +1146,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Present'
}
@@ -1217,9 +1178,7 @@ try
}
Context 'A scheduled task exists and is configured with the wrong interval, duration & random delay parameters' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
RepeatInterval = (New-TimeSpan -Minutes 20).ToString()
@@ -1269,7 +1228,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Present'
}
@@ -1283,9 +1242,7 @@ try
}
Context 'A scheduled task exists and is configured with the wrong idle timeout & idle duration parameters' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
RepeatInterval = (New-TimeSpan -Minutes 20).ToString()
@@ -1335,7 +1292,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Present'
}
@@ -1350,9 +1307,7 @@ try
}
Context 'A scheduled task exists and is configured with the wrong duration parameter for an indefinite trigger' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
RepeatInterval = (New-TimeSpan -Minutes 20).ToString()
@@ -1388,7 +1343,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Present'
}
@@ -1403,9 +1358,7 @@ try
}
Context 'A scheduled task exists and is configured with indefinite repetition duration for a trigger but should be fixed' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
RepeatInterval = (New-TimeSpan -Minutes 20).ToString()
@@ -1441,7 +1394,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Present'
}
@@ -1456,9 +1409,7 @@ try
}
Context 'A scheduled task exists and is configured with correctly with an indefinite duration trigger' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
RepeatInterval = (New-TimeSpan -Minutes 20).ToString()
@@ -1494,7 +1445,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Present'
}
@@ -1504,9 +1455,7 @@ try
}
Context 'When a built-in scheduled task exists and is enabled, but it should be disabled and the trigger type is not recognized' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
Enable = $false
Verbose = $true
}
@@ -1534,7 +1483,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Enable | Should -BeTrue
$result.Ensure | Should -Be 'Present'
$result.ScheduleType | Should -BeNullOrEmpty
@@ -1551,9 +1500,7 @@ try
}
Context 'When a scheduled task with an OnEvent scheduletype is in desired state' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ScheduleType = 'OnEvent'
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
EventSubscription = ''
@@ -1583,7 +1530,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Enable | Should -BeTrue
$result.Ensure | Should -Be 'Present'
$result.ScheduleType | Should -Be 'OnEvent'
@@ -1597,9 +1544,7 @@ try
}
Context 'When a scheduled task with an OnEvent scheduletype needs to be created' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ScheduleType = 'OnEvent'
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
EventSubscription = ''
@@ -1611,7 +1556,7 @@ try
Mock -CommandName Get-ScheduledTask
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Ensure | Should -Be 'Absent'
}
@@ -1626,9 +1571,7 @@ try
}
Context 'When a scheduled task with an OnEvent scheduletype needs to be updated' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ScheduleType = 'OnEvent'
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
EventSubscription = ''
@@ -1658,7 +1601,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Enable | Should -BeTrue
$result.Ensure | Should -Be 'Present'
$result.ScheduleType | Should -Be 'OnEvent'
@@ -1680,9 +1623,7 @@ try
}
Context 'When a scheduled task with an OnEvent scheduletype is used on combination with unsupported parameters for this scheduletype' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ScheduleType = 'OnEvent'
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
EventSubscription = ''
@@ -1713,7 +1654,7 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Enable | Should -BeTrue
$result.Ensure | Should -Be 'Present'
$result.ScheduleType | Should -Be 'OnEvent'
@@ -1732,9 +1673,7 @@ try
}
Context 'When a scheduled task is created using a Built In Service Account' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
RepeatInterval = (New-TimeSpan -Minutes 15).ToString()
@@ -1795,9 +1734,7 @@ try
}
Context 'When a scheduled task is created using a Group Managed Service Account' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
RepeatInterval = (New-TimeSpan -Minutes 15).ToString()
@@ -1870,9 +1807,7 @@ try
}
Context 'When a scheduled task Group Managed Service Account is changed' {
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ScheduleType = 'Once'
RepeatInterval = (New-TimeSpan -Minutes 15).ToString()
@@ -1929,9 +1864,7 @@ try
Context 'When a scheduled task is created and synchronize across time zone is disabled' {
$startTimeString = '2018-10-01T01:00:00'
$startTimeStringWithOffset = '2018-10-01T01:00:00' + (Get-Date -Format 'zzz')
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
StartTime = Get-Date -Date $startTimeString
SynchronizeAcrossTimeZone = $false
@@ -1959,9 +1892,9 @@ try
}
}
- It 'Should return the time in string format and SynchronizeAcrossTimeZone with value false' {
- $result = Get-TargetResource @testParameters
- $result.StartTime | Should -Be $startTimeString
+ It 'Should return the start time in DateTime format and SynchronizeAcrossTimeZone with value false' {
+ $result = Get-TargetResource @getTargetResourceParameters
+ $result.StartTime | Should -Be (Get-Date -Date $startTimeString)
$result.SynchronizeAcrossTimeZone | Should -BeFalse
}
@@ -2005,9 +1938,7 @@ try
Context 'When a scheduled task is created and synchronize across time zone is enabled' {
$startTimeString = '2018-10-01T01:00:00'
$startTimeStringWithOffset = '2018-10-01T01:00:00' + (Get-Date -Format 'zzz')
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
StartTime = Get-Date -Date $startTimeString
SynchronizeAcrossTimeZone = $true
@@ -2035,9 +1966,9 @@ try
}
}
- It 'Should return the time in string format and SynchronizeAcrossTimeZone with value true' {
- $result = Get-TargetResource @testParameters
- $result.StartTime | Should -Be $startTimeStringWithOffset
+ It 'Should return the start time in DateTime format and SynchronizeAcrossTimeZone with value true' {
+ $result = Get-TargetResource @getTargetResourceParameters
+ $result.StartTime | Should -Be (Get-Date -Date $startTimeStringWithOffset)
$result.SynchronizeAcrossTimeZone | Should -BeTrue
}
@@ -2080,9 +2011,7 @@ try
Context 'When a scheduled task is configured to SynchronizeAcrossTimeZone and the ScheduleType is not Once, Daily or Weekly' {
$startTimeString = '2018-10-01T01:00:00'
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
StartTime = Get-Date -Date $startTimeString
SynchronizeAcrossTimeZone = $true
@@ -2097,9 +2026,7 @@ try
Context 'When a scheduled task is configured with the ScheduleType AtLogon and is in desired state' {
$startTimeString = '2018-10-01T01:00:00'
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
StartTime = Get-Date -Date $startTimeString
ScheduleType = 'AtLogon'
@@ -2133,10 +2060,10 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Enable | Should -Be $testParameters.Enable
$result.Ensure | Should -Be 'Present'
- $result.StartTime | Should -Be $startTimeString
+ $result.StartTime | Should -Be (Get-Date -Date $startTimeString)
$result.ScheduleType | Should -Be 'AtLogon'
$result.Delay | Should -Be $testParameters.Delay
}
@@ -2147,12 +2074,8 @@ try
}
Context 'When a scheduled task is configured with the ScheduleType AtStartup and is in desired state' {
- $startTimeString = '2018-10-01T01:00:00'
- $testParameters = @{
- TaskName = 'Test task'
- TaskPath = '\Test\'
+ $testParameters = $getTargetResourceParameters + @{
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
- StartTime = Get-Date -Date $startTimeString
ScheduleType = 'AtStartup'
Delay = '00:01:00'
Enable = $true
@@ -2171,7 +2094,7 @@ try
Triggers = @(
[pscustomobject] @{
Delay = 'PT1M'
- StartBoundary = $startTimeString
+ StartBoundary = ''
CimClass = @{
CimClassName = 'MSFT_TaskBootTrigger'
}
@@ -2184,10 +2107,9 @@ try
}
It 'Should return the correct values from Get-TargetResource' {
- $result = Get-TargetResource @testParameters
+ $result = Get-TargetResource @getTargetResourceParameters
$result.Enable | Should -Be $testParameters.Enable
$result.Ensure | Should -Be 'Present'
- $result.StartTime | Should -Be $startTimeString
$result.ScheduleType | Should -Be 'AtStartup'
$result.Delay | Should -Be $testParameters.Delay
}
@@ -2197,6 +2119,20 @@ try
}
}
}
+
+ Describe 'MSFT_ScheduledTask\Test-DateStringContainsTimeZone' {
+ Context 'When the date string contains a date without a timezone' {
+ It 'Should return $false' {
+ Test-DateStringContainsTimeZone -DateString '2018-10-01T01:00:00' | Should -BeFalse
+ }
+ }
+
+ Context 'When the date string contains a date with a timezone' {
+ It 'Should return $true' {
+ Test-DateStringContainsTimeZone -DateString ('2018-10-01T01:00:00' + (Get-Date -Format 'zzz')) | Should -BeTrue
+ }
+ }
+ }
}
#endregion
}