DSCResources/DSC_CMClientSettingsSoftwareUpdate/DSC_CMClientSettingsSoftwareUpdate.psm1

$script:dscResourceCommonPath = Join-Path -Path $PSScriptRoot -ChildPath '..\..\Modules\DscResource.Common'
$script:configMgrResourcehelper = Join-Path -Path $PSScriptRoot -ChildPath '..\..\Modules\ConfigMgrCBDsc.ResourceHelper'

Import-Module -Name $script:dscResourceCommonPath
Import-Module -Name $script:configMgrResourcehelper

$script:localizedData = Get-LocalizedData -DefaultUICulture 'en-US'

<#
    .SYNOPSIS
        This will return a hashtable of results.
 
    .PARAMETER SiteCode
        Specifies the site code for Configuration Manager site.
 
    .Parameter ClientSettingName
        Specifies which client settings policy to modify.
 
    .Parameter Enable
        Specifies if software update policy is enabled or disabled.
        Not Used in Get.
#>

function Get-TargetResource
{
    [CmdletBinding()]
    [OutputType([System.Collections.Hashtable])]
    param
    (
        [Parameter(Mandatory = $true)]
        [String]
        $SiteCode,

        [Parameter(Mandatory = $true)]
        [String]
        $ClientSettingName,

        [Parameter(Mandatory = $true)]
        [Boolean]
        $Enable
    )

    Write-Verbose -Message $script:localizedData.RetrieveSettingValue
    Import-ConfigMgrPowerShellModule -SiteCode $SiteCode
    Set-Location -Path "$($SiteCode):\"

    $clientSetting = Get-CMClientSetting -Name $ClientSettingName

    if ($clientSetting)
    {
        $type = @('Default','Device','User')[$clientSetting.Type]
        $settings = Get-CMClientSetting -Name $ClientSettingName -Setting SoftwareUpdates

        if ($settings)
        {
            $enabled = [System.Convert]::ToBoolean($settings.Enabled)

            if ($enabled -eq $true)
            {
                $scanSchedule = Get-CMSchedule -ScheduleString $settings.ScanSchedule
                $evalSchedule = Get-CMSchedule -ScheduleString $settings.EvaluationSchedule

                if ([UInt32]$settings.AssignmentBatchingTimeout -eq 0)
                {
                    $enforce = $false
                }
                elseif ([UInt32]$settings.AssignmentBatchingTimeout -ge 86400)
                {
                    $enforce = $true
                    $unitTime = 'Days'
                    $finalValue = $($settings.AssignmentBatchingTimeout)/86400
                }
                else
                {
                    $enforce = $true
                    $unitTime = 'Hours'
                    $finalValue = $settings.AssignmentBatchingTimeout/3600
                }

                $express = [System.Convert]::ToBoolean($settings.EnableExpressUpdates)
                $expressPort = [UInt32]$settings.ExpressUpdatesPort
                $office = @('NotConfigured','Yes','No')[$settings.O365Management]
                $thirdParty = [System.Convert]::ToBoolean($settings.EnableThirdPartyUpdates)
            }
        }

        $status = 'Present'
    }
    else
    {
        $status = 'Absent'
    }

    return @{
        SiteCode                = $SiteCode
        ClientSettingName       = $ClientSettingName
        Enable                  = $enabled
        ScanStart               = $scanSchedule.Start
        ScanScheduleType        = $scanSchedule.ScheduleType
        ScanDayOfWeek           = $scanSchedule.DayofWeek
        ScanMonthlyWeekOrder    = $scanSchedule.WeekOrder
        ScanDayofMonth          = $scanSchedule.MonthDay
        ScanRecurInterval       = $scanSchedule.RecurInterval
        EvalStart               = $evalSchedule.Start
        EvalScheduleType        = $evalSchedule.ScheduleType
        EvalDayOfWeek           = $evalSchedule.DayofWeek
        EvalMonthlyWeekOrder    = $evalSchedule.WeekOrder
        EvalDayofMonth          = $evalSchedule.MonthDay
        EvalRecurInterval       = $evalSchedule.RecurInterval
        EnforceMandatory        = $enforce
        TimeUnit                = $unitTime
        BatchingTimeout         = $finalValue
        EnableDeltaDownload     = $express
        DeltaDownloadPort       = $expressPort
        Office365ManagementType = $office
        EnableThirdPartyUpdates = $thirdParty
        ClientSettingStatus     = $status
        ClientType              = $type
    }
}

<#
    .SYNOPSIS
        This will set the desired state.
 
    .PARAMETER SiteCode
        Specifies a site code for the Configuration Manager site.
 
    .Parameter ClientSettingName
        Specifies which client settings policy to modify.
 
    .Parameter Enable
        Specifies if software update for clients is enabled or disabled.
 
    .PARAMETER ScanStart
        Specifies the start date and start time for the software update scan schedule Month/Day/Year, example 1/1/2020 02:00.
 
    .PARAMETER ScanScheduleType
        Specifies the schedule type for the software update scan schedule.
 
    .PARAMETER ScanRecurInterval
        Specifies how often the ScanScheduleType is run.
 
    .PARAMETER ScanMonthlyByWeek
        Specifies week order for MonthlyByWeek scan schedule type.
 
    .PARAMETER ScanDayOfWeek
        Specifies the day of week name for MonthlyByWeek and Weekly scan schedules.
 
    .PARAMETER ScanDayOfMonth
        Specifies the day number for MonthlyByDay scan schedules.
        Note specifying 0 sets the schedule to run the last day of the month.
 
    .PARAMETER EvalStart
        Specifies the start date and start time for the software update eval schedule Month/Day/Year, example 1/1/2020 02:00.
 
    .PARAMETER EvalScheduleType
        Specifies the schedule type for the software update eval schedule.
 
    .PARAMETER EvalRecurInterval
        Specifies how often the EvalScheduleType is run.
 
    .PARAMETER EvalMonthlyByWeek
        Specifies week order for MonthlyByWeek eval schedule type.
 
    .PARAMETER EvalDayOfWeek
        Specifies the day of week name for MonthlyByWeek and Weekly eval schedules.
 
    .PARAMETER EvalDayOfMonth
        Specifies the day number for MonthlyByDay eval schedules.
        Note specifying 0 sets the schedule to run the last day of the month.
 
    .Parameter EnforceMandatory
        Specifies if any software update deployment deadline is
        reached to install all deployments with dealing coming within a specific time period.
 
    .Parameter TimeUnit
        Specifies the unit of time, hours or days time frame to install pending software updates.
 
    .Parameter BatchingTimeOut
        Specifies the time within TimeUnit to install the depending updates.
 
    .Parameter EnableDeltaDownload
        Specifies if client are allowed to download delta content when available.
 
    .Parameter DeltaDownloadPort
        Specifies the port that clients will use to receive requests for delta content.
 
    .Parameter Office365ManagementType
        Specifies the management of the Office 365 client.
 
    .Parameter EnableThirdPartyUpdates
        Specifies if third party updates is enabled or disabled.
#>

function Set-TargetResource
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true)]
        [String]
        $SiteCode,

        [Parameter(Mandatory = $true)]
        [String]
        $ClientSettingName,

        [Parameter(Mandatory = $true)]
        [Boolean]
        $Enable,

        [Parameter()]
        [String]
        $ScanStart,

        [Parameter()]
        [ValidateSet('MonthlyByDay','MonthlyByWeek','Weekly','Days','Hours','Minutes','None')]
        [String]
        $ScanScheduleType,

        [Parameter()]
        [UInt32]
        $ScanRecurInterval,

        [Parameter()]
        [ValidateSet('First','Second','Third','Fourth','Last')]
        [String]
        $ScanMonthlyWeekOrder,

        [Parameter()]
        [ValidateSet('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday')]
        [String]
        $ScanDayOfWeek,

        [Parameter()]
        [ValidateRange(0,31)]
        [UInt32]
        $ScanDayOfMonth,

        [Parameter()]
        [String]
        $EvalStart,

        [Parameter()]
        [ValidateSet('MonthlyByDay','MonthlyByWeek','Weekly','Days','Hours','Minutes','None')]
        [String]
        $EvalScheduleType,

        [Parameter()]
        [UInt32]
        $EvalRecurInterval,

        [Parameter()]
        [ValidateSet('First','Second','Third','Fourth','Last')]
        [String]
        $EvalMonthlyWeekOrder,

        [Parameter()]
        [ValidateSet('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday')]
        [String]
        $EvalDayOfWeek,

        [Parameter()]
        [ValidateRange(0,31)]
        [UInt32]
        $EvalDayOfMonth,

        [Parameter()]
        [Boolean]
        $EnforceMandatory,

        [Parameter()]
        [ValidateSet('Hours','Days')]
        [String]
        $TimeUnit,

        [Parameter()]
        [ValidateRange(1,365)]
        [UInt32]
        $BatchingTimeOut,

        [Parameter()]
        [Boolean]
        $EnableDeltaDownload,

        [Parameter()]
        [UInt32]
        $DeltaDownloadPort,

        [Parameter()]
        [ValidateSet('NotConfigured','Yes','No')]
        [String]
        $Office365ManagementType,

        [Parameter()]
        [Boolean]
        $EnableThirdPartyUpdates
    )

    Import-ConfigMgrPowerShellModule -SiteCode $SiteCode
    Set-Location -Path "$($SiteCode):\"
    $state = Get-TargetResource -SiteCode $SiteCode -ClientSettingName $ClientSettingName -Enable $Enable
    $schedResult = $true

    try
    {
        if ($state.ClientSettingStatus -eq 'Absent')
        {
            throw ($script:localizedData.ClientPolicySetting -f $ClientSettingName)
        }

        if ($state.ClientType -eq 'User')
        {
            throw $script:localizedData.WrongClientType
        }

        if ($Enable -eq $true)
        {
            if ((-not $PSBoundParameters.ContainsKey('ScanScheduleType')) -and ($PSBoundParameters.ContainsKey('ScanStart') -or
                $PSBoundParameters.ContainsKey('ScanRecurInterval') -or $PSBoundParameters.ContainsKey('ScanMonthlyWeekOrder') -or
                $PSBoundParameters.ContainsKey('ScanDayOfWeek') -or $PSBoundParameters.ContainsKey('ScanDayOfMonth')))
            {
                throw $script:localizedData.RequiredSchedule
            }

            if ((-not $PSBoundParameters.ContainsKey('EvalScheduleType')) -and ($PSBoundParameters.ContainsKey('EvalStart') -or
                $PSBoundParameters.ContainsKey('EvalRecurInterval') -or $PSBoundParameters.ContainsKey('EvalMonthlyWeekOrder') -or
                $PSBoundParameters.ContainsKey('EvalDayOfWeek') -or $PSBoundParameters.ContainsKey('EvalDayOfMonth')))
            {
                throw $script:localizedData.RequiredSchedule
            }

            $defaultValues = @('Enable','EnforceMandatory','EnableDeltaDownload','EnableThirdPartyUpdates')

            if ($EnableDeltaDownload -eq $false -and $PSBoundParameters.ContainsKey('DeltaDownloadPort'))
            {
                Write-Warning -Message $script:localizedData.DeltaPortIgnore
            }
            else
            {
                $defaultValues += 'DeltaDownloadPort'
            }

            if ($EnforceMandatory -eq $true)
            {
                $defaultValues += ('TimeUnit','BatchingTimeOut')
                if (-not $PSBoundParameters.ContainsKey('TimeUnit') -or -not $PSBoundParameters.ContainsKey('BatchingTimeOut'))
                {
                    throw $script:localizedData.MissingEnforce
                }

                if ($TimeUnit -eq 'Hours' -and $BatchingTimeOut -gt 23)
                {
                    Write-Warning -Message $script:localizedData.MaxBatchHours
                    $PSBoundParameters.Remove('BatchingTimeOut') | Out-Null
                    $PSBoundParameters.Add('BatchingTimeOut',23)
                }
            }
            elseif ($PSBoundParameters.ContainsKey('TimeUnit') -or $PSBoundParameters.ContainsKey('BatchingTimeOut'))
            {
                Write-Warning -Message $script:localizedData.TimeBatchIgnore
            }

            foreach ($param in $PSBoundParameters.GetEnumerator())
            {
                if ($defaultValues -contains $param.Key)
                {
                    if ($param.Value -ne $state[$param.Key])
                    {
                        Write-Verbose -Message ($script:localizedData.SettingValue -f $param.Key, $param.Value)
                        $buildingParams += @{
                            $param.Key = $param.Value
                        }
                    }
                }
            }

            if ($PSBoundParameters.ContainsKey('Office365ManagementType') -and
                $Office365ManagementType -ne $state.Office365ManagementType)
            {
                if ($Office365ManagementType -eq 'NotConfigured')
                {
                    $buildingParams += @{
                        Office365ManagementType = $null
                    }
                }
                elseif ($Office365ManagementType -eq 'Yes')
                {
                    $buildingParams += @{
                        Office365ManagementType = $true
                    }
                }
                else
                {
                    $buildingParams += @{
                        Office365ManagementType = $false
                    }
                }
            }

            if ($ScanScheduleType)
            {
                $valuesToValidate = @('ScanScheduleType','ScanRecurInterval','ScanMonthlyWeekOrder',
                    'ScanDayOfWeek','ScanDayOfMonth','ScanStart')
                foreach ($item in $valuesToValidate)
                {
                    if ($PSBoundParameters.ContainsKey($item))
                    {
                        $scanScheduleCheck += @{
                            $item.Substring(4) = $PSBoundParameters[$item]
                        }
                    }
                }

                foreach ($scan in $state.Keys)
                {
                    if ($valuesToValidate -contains $scan)
                    {
                        $scanState += @{
                            $scan.SubString(4) = $state[$scan]
                        }
                    }
                }

                $scanResult = Test-CMSchedule @scanScheduleCheck -State $scanState
            }

            if ($scanResult -eq $false)
            {
                $sched = Set-CMSchedule @scanScheduleCheck
                $newSchedule = New-CMSchedule @sched

                Write-Verbose -Message $script:localizedData.NewSchedule
                $buildingParams += @{
                    ScanSchedule = $newSchedule
                }
            }

            if ($EvalScheduleType)
            {
                $valuesToValidate = @('EvalScheduleType','EvalRecurInterval','EvalMonthlyWeekOrder',
                    'EvalDayOfWeek','EvalDayOfMonth','EvalStart')

                foreach ($item in $valuesToValidate)
                {
                    if ($PSBoundParameters.ContainsKey($item))
                    {
                        $evalScheduleCheck += @{
                            $item.Substring(4) = $PSBoundParameters[$item]
                        }
                    }
                }

                foreach ($eval in $state.Keys)
                {
                    if ($valuesToValidate -contains $eval)
                    {
                        $evalState += @{
                            $eval.SubString(4) = $state[$eval]
                        }
                    }
                }

                $evalResult = Test-CMSchedule @evalScheduleCheck -State $evalState
            }

            if ($evalResult -eq $false)
            {
                $sched = Set-CMSchedule @evalScheduleCheck
                $newSchedule = New-CMSchedule @sched

                Write-Verbose -Message $script:localizedData.NewSchedule
                $buildingParams += @{
                    DeploymentEvaluationSchedule = $newSchedule
                }
            }
        }
        elseif ($state.Enable -eq $true)
        {
            if ($PSBoundParameters.Keys.Count -ge 4)
            {
                Write-Warning -Message $script:localizedData.DisableIgnore
            }

            $buildingParams = @{
                Enable = $false
            }
        }

        if ($buildingParams)
        {
            if ($state.ClientType -eq 'Default')
            {
                Set-CMClientSettingSoftwareUpdate -DefaultSetting @buildingParams
            }
            else
            {
                Set-CMClientSettingSoftwareUpdate -Name $ClientSettingName @buildingParams
            }
        }
    }
    catch
    {
        throw $_
    }
    finally
    {
        Set-Location -Path "$env:temp"
    }
}

<#
    .SYNOPSIS
        This will test the desired state.
 
    .PARAMETER SiteCode
        Specifies a site code for the Configuration Manager site.
 
    .Parameter ClientSettingName
        Specifies which client settings policy to modify.
 
    .Parameter Enable
        Specifies if software update for clients is enabled or disabled.
 
    .PARAMETER ScanStart
        Specifies the start date and start time for the software update scan schedule Month/Day/Year, example 1/1/2020 02:00.
 
    .PARAMETER ScanScheduleType
        Specifies the schedule type for the software update scan schedule.
 
    .PARAMETER ScanRecurInterval
        Specifies how often the ScanScheduleType is run.
 
    .PARAMETER ScanMonthlyByWeek
        Specifies week order for MonthlyByWeek scan schedule type.
 
    .PARAMETER ScanDayOfWeek
        Specifies the day of week name for MonthlyByWeek and Weekly scan schedules.
 
    .PARAMETER ScanDayOfMonth
        Specifies the day number for MonthlyByDay scan schedules.
        Note specifying 0 sets the schedule to run the last day of the month.
 
    .PARAMETER EvalStart
        Specifies the start date and start time for the software update eval schedule Month/Day/Year, example 1/1/2020 02:00.
 
    .PARAMETER EvalScheduleType
        Specifies the schedule type for the software update eval schedule.
 
    .PARAMETER EvalRecurInterval
        Specifies how often the EvalScheduleType is run.
 
    .PARAMETER EvalMonthlyByWeek
        Specifies week order for MonthlyByWeek eval schedule type.
 
    .PARAMETER EvalDayOfWeek
        Specifies the day of week name for MonthlyByWeek and Weekly eval schedules.
 
    .PARAMETER EvalDayOfMonth
        Specifies the day number for MonthlyByDay eval schedules.
        Note specifying 0 sets the schedule to run the last day of the month.
 
    .Parameter EnforceMandatory
        Specifies if any software update deployment deadline is
        reached to install all deployments with dealing coming within a specific time period.
 
    .Parameter TimeUnit
        Specifies the unit of time, hours or days time frame to install pending software updates.
 
    .Parameter BatchingTimeOut
        Specifies the time within TimeUnit to install the depending updates.
 
    .Parameter EnableDeltaDownload
        Specifies if client are allowed to download delta content when available.
 
    .Parameter DeltaDownloadPort
        Specifies the port that clients will use to receive requests for delta content.
 
    .Parameter Office365ManagementType
        Specifies the management of the Office 365 client.
 
    .Parameter EnableThirdPartyUpdates
        Specifies if third party updates is enabled or disabled.
#>

function Test-TargetResource
{
    [CmdletBinding()]
    [OutputType([System.Boolean])]
    param
    (
        [Parameter(Mandatory = $true)]
        [String]
        $SiteCode,

        [Parameter(Mandatory = $true)]
        [String]
        $ClientSettingName,

        [Parameter(Mandatory = $true)]
        [Boolean]
        $Enable,

        [Parameter()]
        [String]
        $ScanStart,

        [Parameter()]
        [ValidateSet('MonthlyByDay','MonthlyByWeek','Weekly','Days','Hours','Minutes','None')]
        [String]
        $ScanScheduleType,

        [Parameter()]
        [UInt32]
        $ScanRecurInterval,

        [Parameter()]
        [ValidateSet('First','Second','Third','Fourth','Last')]
        [String]
        $ScanMonthlyWeekOrder,

        [Parameter()]
        [ValidateSet('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday')]
        [String]
        $ScanDayOfWeek,

        [Parameter()]
        [ValidateRange(0,31)]
        [UInt32]
        $ScanDayOfMonth,

        [Parameter()]
        [String]
        $EvalStart,

        [Parameter()]
        [ValidateSet('MonthlyByDay','MonthlyByWeek','Weekly','Days','Hours','Minutes','None')]
        [String]
        $EvalScheduleType,

        [Parameter()]
        [UInt32]
        $EvalRecurInterval,

        [Parameter()]
        [ValidateSet('First','Second','Third','Fourth','Last')]
        [String]
        $EvalMonthlyWeekOrder,

        [Parameter()]
        [ValidateSet('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday')]
        [String]
        $EvalDayOfWeek,

        [Parameter()]
        [ValidateRange(0,31)]
        [UInt32]
        $EvalDayOfMonth,

        [Parameter()]
        [Boolean]
        $EnforceMandatory,

        [Parameter()]
        [ValidateSet('Hours','Days')]
        [String]
        $TimeUnit,

        [Parameter()]
        [ValidateRange(1,365)]
        [UInt32]
        $BatchingTimeOut,

        [Parameter()]
        [Boolean]
        $EnableDeltaDownload,

        [Parameter()]
        [UInt32]
        $DeltaDownloadPort,

        [Parameter()]
        [ValidateSet('NotConfigured','Yes','No')]
        [String]
        $Office365ManagementType,

        [Parameter()]
        [Boolean]
        $EnableThirdPartyUpdates
    )

    Import-ConfigMgrPowerShellModule -SiteCode $SiteCode
    Set-Location -Path "$($SiteCode):\"
    $state = Get-TargetResource -SiteCode $SiteCode -ClientSettingName $ClientSettingName -Enable $Enable
    $result = $true
    $schedResult = $true

    if ($state.ClientSettingStatus -eq 'Absent')
    {
        Write-Warning -Message ($script:localizedData.ClientPolicySetting -f $ClientSettingName)
        $result = $false
    }
    elseif ($state.ClientType -eq 'User')
    {
        Write-Warning -Message $script:localizedData.WrongClientType
        $result = $false
    }
    else
    {
        if ($Enable -eq $true)
        {
            if ((-not $PSBoundParameters.ContainsKey('ScanScheduleType')) -and ($PSBoundParameters.ContainsKey('ScanStart') -or
                $PSBoundParameters.ContainsKey('ScanRecurInterval') -or $PSBoundParameters.ContainsKey('ScanMonthlyWeekOrder') -or
                $PSBoundParameters.ContainsKey('ScanDayOfWeek') -or $PSBoundParameters.ContainsKey('ScanDayOfMonth')))
            {
                Write-Warning -Message $script:localizedData.RequiredSchedule
                $badInput = $true
            }

            if ((-not $PSBoundParameters.ContainsKey('EvalScheduleType')) -and ($PSBoundParameters.ContainsKey('EvalStart') -or
                $PSBoundParameters.ContainsKey('EvalRecurInterval') -or $PSBoundParameters.ContainsKey('EvalMonthlyWeekOrder') -or
                $PSBoundParameters.ContainsKey('EvalDayOfWeek') -or $PSBoundParameters.ContainsKey('EvalDayOfMonth')))
            {
                Write-Warning -Message $script:localizedData.RequiredSchedule
                $badInput = $true
            }

            $defaultValues = @('Enable','EnforceMandatory','EnableDeltaDownload','Office365ManagementType',
                'EnableThirdPartyUpdates')

            if ($EnableDeltaDownload -eq $false -and $PSBoundParameters.ContainsKey('DeltaDownloadPort'))
            {
                Write-Warning -Message $script:localizedData.DeltaPortIgnore
            }
            else
            {
                $defaultValues += 'DeltaDownloadPort'
            }

            if ($EnforceMandatory -eq $true)
            {
                $defaultValues += ('TimeUnit','BatchingTimeOut')
                if (-not $PSBoundParameters.ContainsKey('TimeUnit') -or -not $PSBoundParameters.ContainsKey('BatchingTimeOut'))
                {
                    Write-Warning -Message $script:localizedData.MissingEnforce
                    $badInput = $true
                }

                if ($TimeUnit -eq 'Hours' -and $BatchingTimeOut -gt 23)
                {
                    Write-Warning -Message $script:localizedData.MaxBatchHours
                    $PSBoundParameters.Remove('BatchingTimeOut') | Out-Null
                    $PSBoundParameters.Add('BatchingTimeOut',23)
                }
            }
            elseif ($PSBoundParameters.ContainsKey('TimeUnit') -or $PSBoundParameters.ContainsKey('BatchingTimeOut'))
            {
                Write-Warning -Message $script:localizedData.TimeBatchIgnore
            }

            $testParams = @{
                CurrentValues = $state
                DesiredValues = $PSBoundParameters
                ValuesToCheck = $defaultValues
            }

            $result = Test-DscParameterState @testParams -TurnOffTypeChecking -Verbose

            if ($ScanScheduleType)
            {
                $valuesToValidate = @('ScanScheduleType','ScanRecurInterval','ScanMonthlyWeekOrder',
                    'ScanDayOfWeek','ScanDayOfMonth','ScanStart')
                foreach ($item in $valuesToValidate)
                {
                    if ($PSBoundParameters.ContainsKey($item))
                    {
                        $scanScheduleCheck += @{
                            $item.Substring(4) = $PSBoundParameters[$item]
                        }
                    }
                }

                foreach ($scan in $state.Keys)
                {
                    if ($valuesToValidate -contains $scan)
                    {
                        $scanState += @{
                            $scan.SubString(4) = $state[$scan]
                        }
                    }
                }

                $scanResult = Test-CMSchedule @scanScheduleCheck -State $scanState
            }

            if ($EvalScheduleType)
            {
                $valuesToValidate = @('EvalScheduleType','EvalRecurInterval','EvalMonthlyWeekOrder',
                    'EvalDayOfWeek','EvalDayOfMonth','EvalStart')
                foreach ($item in $valuesToValidate)
                {
                    if ($PSBoundParameters.ContainsKey($item))
                    {
                        $evalScheduleCheck += @{
                            $item.Substring(4) = $PSBoundParameters[$item]
                        }
                    }
                }

                foreach ($eval in $state.Keys)
                {
                    if ($valuesToValidate -contains $eval)
                    {
                        $evalState += @{
                            $eval.SubString(4) = $state[$eval]
                        }
                    }
                }

                $evalResult = Test-CMSchedule @evalScheduleCheck -State $evalState
            }
        }
        else
        {
            if ($PSBoundParameters.Keys.Count -ge 4)
            {
                Write-Warning -Message $script:localizedData.DisableIgnore
            }

            if ($state.Enable -eq $true)
            {
                Write-Verbose -Message $script:localizedData.TestDisabled
                $result = $false
            }
        }
    }

    if ($result -eq $false -or $scanResult -eq $false -or $badInput -eq $true -or $evalResult -eq $false)
    {
        $return = $false
    }
    else
    {
        $return = $true
    }

    Write-Verbose -Message ($script:localizedData.TestState -f $return)
    Set-Location -Path "$env:temp"
    return $return
}

Export-ModuleMember -Function *-TargetResource