DSCResources/DSC_CMGroupDiscovery/DSC_CMGroupDiscovery.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 Enabled
        Specifies the enablement of the Group discovery method.
#>

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

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

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

    $groupDiscovery = Get-CMDiscoveryMethod -Name ActiveDirectoryGroupDiscovery -SiteCode $SiteCode

    if ($groupDiscovery)
    {
        $adContainers = ($groupDiscovery.Proplists | Where-Object -FilterScript {$_.PropertyListName -eq 'AD Containers'}).Values
        $count = 0

        if ($adContainers)
        {
            $adGroups = @()
            foreach ($item in $adContainers)
            {
                if ($item -ne 0 -and $item -ne 1)
                {
                    $value = $count + 2
                    if ($adContainers[$value] -eq 0)
                    {
                        $recurse = $true
                    }
                    else
                    {
                        $recurse = $false
                    }

                    $ou = ($groupDiscovery.Proplists | Where-Object -FilterScript {$_.PropertyListName -eq "Search Bases:$item"}).Values
                    $adCollection = @{
                        Name         = $item
                        Recurse      = $recurse
                        LDAPLocation = $ou[0]
                    }
                    $adGroups += ConvertTo-AnyCimInstance -ClassName DSC_CMGroupDiscoveryScope -Hashtable $adCollection
                }
                $count ++
            }
        }

        $status = ($groupDiscovery.Props | Where-Object -FilterScript {$_.PropertyName -eq 'Settings'}).Value1

        if ($status -eq 'Active')
        {
            foreach ($prop in $groupDiscovery.Props)
            {
                switch ($prop.PropertyName)
                {
                    'Settings'                          { $enabledStatus = ($prop.Value1 -eq 'Active') }
                    'Full Sync Schedule'                { $groupSchedule = $prop.Value1 }
                    'Enable Incremental Sync'           { [boolean]$deltaEnabled = $prop.Value }
                    'Startup Schedule'                  { $groupDelta = $prop.Value1 }
                    'Enable Filtering Expired Logon'    { [boolean]$lastLogonEnabled = $prop.Value }
                    'Days Since Last Logon'             { $lastLogon = $prop.Value }
                    'Enable Filtering Expired Password' { [boolean]$lastPasswordEnabled = $prop.Value }
                    'Days Since Last Password Set'      { $lastPassword = $prop.Value }
                    'Discover DG Membership'            { [boolean]$dgMemberEnabled = $prop.Value }
                }
            }

            if ($deltaEnabled -eq $false)
            {
                $groupSchedule = $groupDelta
                $groupDelta = $null
            }

            $schedule = Get-CMSchedule -ScheduleString $groupSchedule

            if (-not [string]::IsNullOrEmpty($groupDelta))
            {
                $sDelta = Convert-CMSchedule -ScheduleString $groupDelta

                if ($sDelta.HourSpan -eq 1)
                {
                    $syncDelta = 60
                }
                else
                {
                    $syncDelta = $sDelta.MinuteSpan
                }
            }
        }
        else
        {
            $enabledStatus = $false
        }
    }

    return @{
        SiteCode                            = $SiteCode
        Enabled                             = $enabledStatus
        EnableDeltaDiscovery                = $deltaEnabled
        DeltaDiscoveryMins                  = $syncDelta
        EnableFilteringExpiredLogon         = $lastLogonEnabled
        TimeSinceLastLogonDays              = $lastLogon
        EnableFilteringExpiredPassword      = $lastPasswordEnabled
        TimeSinceLastPasswordUpdateDays     = $lastPassword
        DiscoverDistributionGroupMembership = $dgMemberEnabled
        GroupDiscoveryScope                 = $adGroups
        Start                               = $schedule.Start
        ScheduleType                        = $schedule.ScheduleType
        DayOfWeek                           = $schedule.DayofWeek
        MonthlyWeekOrder                    = $schedule.WeekOrder
        DayofMonth                          = $schedule.MonthDay
        RecurInterval                       = $schedule.RecurInterval
    }
}

<#
    .SYNOPSIS
        This will set the desired state.
 
    .PARAMETER SiteCode
        Specifies the site code for Configuration Manager site.
 
    .PARAMETER Enabled
        Specifies the enablement of the group discovery method.
 
    .PARAMETER EnableDeltaDiscovery
        Indicates whether Configuration Manager discovers resources created or modified in AD DS
        since the last discovery cycle. If you specify a value of $True for this parameter,
        specify a value for the DeltaDiscoveryMins parameter.
 
    .PARAMETER DeltaDiscoveryMins
        Specifies the number of minutes for the delta discovery.
 
    .PARAMETER EnableFilteringExpiredLogon
        Indicates whether Configuration Manager discovers only computers that have logged onto a
        domain within a specified number of days. Specify the number of days by using the
        TimeSinceLastLogonDays parameter.
 
    .PARAMETER TimeSinceLastLogonDays
        Specify the number of days for EnableFilteringExpiredLogon.
 
    .PARAMETER EnableFilteringExpiredPassword
        Indicates whether Configuration Manager discovers only computers that have updated ther
        account password within a specified number of days. Specify the number of days by using the
        TimeSinceLastPasswordUpdateDays parameter.
 
    .PARAMETER TimeSinceLastPasswordUpdateDays
        Specify the number of days for EnableFilteringExpiredPassword.
 
    .PARAMETER DiscoverDistributionGroupMembership
        Specify if group discovery will discover distribution groups and the members of the group.
 
    .PARAMETER GroupDiscoveryScope
        Specifies an array of Group Discovery Scopes to match to the discovery.
 
    .PARAMETER GroupDiscoveryScopeToInclude
        Specifies an array of Group Discovery Scopes to add to the discovery.
 
    .PARAMETER GroupDiscoveryScopeToExclude
        Specifies an array of names of Group Discovery Scopes to exclude to the discovery.
 
    .PARAMETER Start
        Specifies the start date and start time for the group discovery schedule Month/Day/Year, example 1/1/2020 02:00.
 
    .PARAMETER ScheduleType
        Specifies the schedule type for the group discovery schedule.
 
    .PARAMETER RecurInterval
        Specifies how often the ScheduleType is run.
 
    .PARAMETER MonthlyByWeek
        Specifies week order for MonthlyByWeek schedule type.
 
    .PARAMETER DayOfWeek
        Specifies the day of week name for MonthlyByWeek and Weekly schedules.
 
    .PARAMETER DayOfMonth
        Specifies the day number for MonthlyByDay schedules.
        Note specifying 0 sets the schedule to run the last day of the month.
#>

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

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

        [Parameter()]
        [Boolean]
        $EnableDeltaDiscovery,

        [Parameter()]
        [ValidateRange(5,60)]
        [UInt32]
        $DeltaDiscoveryMins,

        [Parameter()]
        [Boolean]
        $EnableFilteringExpiredLogon,

        [Parameter()]
        [ValidateRange(14,720)]
        [UInt32]
        $TimeSinceLastLogonDays,

        [Parameter()]
        [Boolean]
        $EnableFilteringExpiredPassword,

        [Parameter()]
        [ValidateRange(30,720)]
        [UInt32]
        $TimeSinceLastPasswordUpdateDays,

        [Parameter()]
        [Boolean]
        $DiscoverDistributionGroupMembership,

        [Parameter()]
        [Microsoft.Management.Infrastructure.CimInstance[]]
        $GroupDiscoveryScope,

        [Parameter()]
        [Microsoft.Management.Infrastructure.CimInstance[]]
        $GroupDiscoveryScopeToInclude,

        [Parameter()]
        [String[]]
        $GroupDiscoveryScopeToExclude,

        [Parameter()]
        [String]
        $Start,

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

        [Parameter()]
        [UInt32]
        $RecurInterval,

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

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

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

    Import-ConfigMgrPowerShellModule -SiteCode $SiteCode
    Set-Location -Path "$($SiteCode):\"

    try
    {
        $state = Get-TargetResource -SiteCode $SiteCode -Enabled $Enabled

        if ($Enabled -eq $true)
        {
            if (($PSBoundParameters.ContainsKey('DeltaDiscoveryMins')) -and ($EnableDeltaDiscovery -eq $false -or
                $state.EnableDeltaDiscovery -eq $false))
            {
                throw $script:localizedData.MissingDeltaDiscovery
            }

            if (($EnableDeltaDiscovery -eq $true -and $state.EnableDeltaDiscovery -eq $false) -and
                (-not $PSBoundParameters.ContainsKey('DeltaDiscoveryMins')))
            {
                throw $script:localizedData.DeltaNoInterval
            }

            if ($PSBoundParameters.ContainsKey('GroupDiscoveryScope'))
            {
                if ($PSBoundParameters.ContainsKey('GroupDiscoveryScopeToInclude') -or
                    $PSBoundParameters.ContainsKey('GroupDiscoveryScopeToExclude'))
                {
                    Write-Warning -Message $script:localizedData.GdsIgnore
                }
            }
            elseif ($GroupDiscoveryScopeToInclude -and $GroupDiscoveryScopeToExclude)
            {
                foreach ($item in $GroupDiscoveryScopeToInclude)
                {
                    if ($GroupDiscoveryScopeToExclude -contains $item.Name)
                    {
                        throw ($script:localizedData.GdsInEx -f $item.Name)
                    }
                }
            }

            if ((-not $PSBoundParameters.ContainsKey('ScheduleType')) -and ($PSBoundParameters.ContainsKey('Start') -or
                $PSBoundParameters.ContainsKey('RecurInterval') -or $PSBoundParameters.ContainsKey('MonthlyWeekOrder') -or
                $PSBoundParameters.ContainsKey('DayOfWeek') -or $PSBoundParameters.ContainsKey('DayOfMonth')))
            {
                throw $script:localizedData.MissingScheduleType
            }

            if ($PSBoundParameters.ContainsKey('TimeSinceLastLogonDays') -and $EnableFilteringExpiredLogon -ne $true)
            {
                throw $script:localizedData.TimeSinceLastLogon
            }

            if ($PSBoundParameters.ContainsKey('TimeSinceLastPasswordUpdateDays') -and $EnableFilteringExpiredPassword -ne $true)
            {
                throw $script:localizedData.PasswordExpiredFilter
            }

            $paramsToCheck = @('Enabled','EnableDeltaDiscovery','DeltaDiscoveryMins','EnableFilteringExpiredLogon',
                              'TimeSinceLastLogonDays','EnableFilteringExpiredPassword','TimeSinceLastPasswordUpdateDays',
                              'DiscoverDistributionGroupMembership')

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

            if ($ScheduleType)
            {
                $valuesToValidate = @('ScheduleType','RecurInterval','MonthlyWeekOrder','DayOfWeek','DayOfMonth','Start')
                foreach ($item in $valuesToValidate)
                {
                    if ($PSBoundParameters.ContainsKey($item))
                    {
                        $scheduleCheck += @{
                            $item = $PSBoundParameters[$item]
                        }
                    }
                }

                $schedResult = Test-CMSchedule @scheduleCheck -State $state
            }

            if ($schedResult -eq $false)
            {
                $sched = Set-CMSchedule @scheduleCheck
                $newSchedule = New-CMSchedule @sched

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

            if ($GroupDiscoveryScope -or $GroupDiscoveryScopeToInclude)
            {
                if ($GroupDiscoveryScope)
                {
                    $refObject = $GroupDiscoveryScope
                }
                elseif ($GroupDiscoveryScopeToInclude)
                {
                    $refObject = $GroupDiscoveryScopeToInclude
                }

                $compareParams = @{
                    ReferenceObject  = $refObject
                    DifferenceObject = $state.GroupDiscoveryScope
                    Property         = 'Recurse','Name','LdapLocation'
                    IncludeEqual     = $null
                }

                $compare = Compare-Object @compareParams
                $removing = @()
                $missing = @()

                foreach ($item in $compare)
                {
                    if ($item.SideIndicator -eq '<=')
                    {
                        if ($state.GroupDiscoveryScope.Name -contains $item.Name)
                        {
                            Write-Verbose -Message ($script:localizedData.GdsUpdate -f $item.Name, $item.LdapLocation, $item.Recurse, $item.LdapLocation, $item.Recurse)
                        }
                        else
                        {
                            Write-Verbose -Message ($script:localizedData.GdsMissing -f $item.Name, $item.LdapLocation, $item.Recurse)
                        }

                        $cmAddGroup = @{
                            SiteCode        = $SiteCode
                            LdapLocation    = $item.LdapLocation
                            Name            = $item.Name
                            RecursiveSearch = $item.Recurse
                        }

                        [array]$groupOus += New-CMADGroupDiscoveryScope @cmAddGroup
                    }

                    if ($GroupDiscoveryScope)
                    {
                        if ($item.SideIndicator -eq '=>')
                        {
                            Write-Verbose -Message ($script:localizedData.GdsExtra -f $item.Name)
                            $removing += "$($item.Name)"
                        }
                    }
                }
            }

            if ((-not $GroupDiscoveryScope) -and ($GroupDiscoveryScopeToExclude))
            {
                foreach ($item in $GroupDiscoveryScopeToExclude)
                {
                    if ($state.GroupDiscoveryScope.Name -contains $item)
                    {
                        Write-Verbose -Message ($script:localizedData.GdsExtra -f $item)
                        $removing += $item
                    }
                }
            }

            if ($removing)
            {
                Set-CMDiscoveryMethod -ActiveDirectoryGroupDiscovery -SiteCode $SiteCode -RemoveGroupDiscoveryScope $removing
            }

            if ($groupOus)
            {
                $buildingParams += @{
                    AddGroupDiscoveryScope = $groupOus
                }
            }

            if ($buildingParams)
            {
                Set-CMDiscoveryMethod -ActiveDirectoryGroupDiscovery -SiteCode $SiteCode @buildingParams
            }
        }
        elseif ($state.Enabled -eq $true)
        {
            Write-Verbose -Message $script:localizedData.SetDisabled
            Set-CMDiscoveryMethod -ActiveDirectoryGroupDiscovery -Enabled $false -SiteCode $SiteCode
        }
    }
    catch
    {
        throw $_
    }
    finally
    {
        Set-Location -Path "$env:temp"
    }
}

<#
    .SYNOPSIS
        This will set the desired state.
 
    .PARAMETER SiteCode
        Specifies the site code for Configuration Manager site.
 
    .PARAMETER Enabled
        Specifies the enablement of the group discovery method.
 
    .PARAMETER EnableDeltaDiscovery
        Indicates whether Configuration Manager discovers resources created or modified in AD DS
        since the last discovery cycle. If you specify a value of $True for this parameter,
        specify a value for the DeltaDiscoveryMins parameter.
 
    .PARAMETER DeltaDiscoveryMins
        Specifies the number of minutes for the delta discovery.
 
    .PARAMETER EnableFilteringExpiredLogon
        Indicates whether Configuration Manager discovers only computers that have logged onto a
        domain within a specified number of days. Specify the number of days by using the
        TimeSinceLastLogonDays parameter.
 
    .PARAMETER TimeSinceLastLogonDays
        Specify the number of days for EnableFilteringExpiredLogon.
 
    .PARAMETER EnableFilteringExpiredPassword
        Indicates whether Configuration Manager discovers only computers that have updated ther
        account password within a specified number of days. Specify the number of days by using the
        TimeSinceLastPasswordUpdateDays parameter.
 
    .PARAMETER TimeSinceLastPasswordUpdateDays
        Specify the number of days for EnableFilteringExpiredPassword.
 
    .PARAMETER DiscoverDistributionGroupMembership
        Specify if group discovery will discover distribution groups and the members of the group.
 
    .PARAMETER GroupDiscoveryScope
        Specifies an array of Group Discovery Scopes to match to the discovery.
 
    .PARAMETER GroupDiscoveryScopeToInclude
        Specifies an array of Group Discovery Scopes to add to the discovery.
 
    .PARAMETER GroupDiscoveryScopeToExclude
        Specifies an array of names of Group Discovery Scopes to exclude to the discovery.
 
    .PARAMETER Start
        Specifies the start date and start time for the group discovery schedule Month/Day/Year, example 1/1/2020 02:00.
 
    .PARAMETER ScheduleType
        Specifies the schedule type for the group discovery schedule.
 
    .PARAMETER RecurInterval
        Specifies how often the ScheduleType is run.
 
    .PARAMETER MonthlyByWeek
        Specifies week order for MonthlyByWeek schedule type.
 
    .PARAMETER DayOfWeek
        Specifies the day of week name for MonthlyByWeek and Weekly schedules.
 
    .PARAMETER DayOfMonth
        Specifies the day number for MonthlyByDay schedules.
        Note specifying 0 sets the schedule to run the last day of the month.
#>

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

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

        [Parameter()]
        [Boolean]
        $EnableDeltaDiscovery,

        [Parameter()]
        [ValidateRange(5,60)]
        [UInt32]
        $DeltaDiscoveryMins,

        [Parameter()]
        [Boolean]
        $EnableFilteringExpiredLogon,

        [Parameter()]
        [ValidateRange(14,720)]
        [UInt32]
        $TimeSinceLastLogonDays,

        [Parameter()]
        [Boolean]
        $EnableFilteringExpiredPassword,

        [Parameter()]
        [ValidateRange(30,720)]
        [UInt32]
        $TimeSinceLastPasswordUpdateDays,

        [Parameter()]
        [Boolean]
        $DiscoverDistributionGroupMembership,

        [Parameter()]
        [Microsoft.Management.Infrastructure.CimInstance[]]
        $GroupDiscoveryScope,

        [Parameter()]
        [Microsoft.Management.Infrastructure.CimInstance[]]
        $GroupDiscoveryScopeToInclude,

        [Parameter()]
        [String[]]
        $GroupDiscoveryScopeToExclude,

        [Parameter()]
        [String]
        $Start,

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

        [Parameter()]
        [UInt32]
        $RecurInterval,

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

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

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

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

    if ($Enabled -eq $true)
    {
        if ((-not $PSBoundParameters.ContainsKey('ScheduleType')) -and ($PSBoundParameters.ContainsKey('Start') -or
                $PSBoundParameters.ContainsKey('RecurInterval') -or $PSBoundParameters.ContainsKey('MonthlyWeekOrder') -or
                $PSBoundParameters.ContainsKey('DayOfWeek') -or $PSBoundParameters.ContainsKey('DayOfMonth')))
        {
            Write-Warning -Message $script:localizedData.MissingScheduleType
            $badInput = $true
        }

        if (($PSBoundParameters.ContainsKey('DeltaDiscoveryMins')) -and ($EnableDeltaDiscovery -eq $false -or
                $state.EnableDeltaDiscovery -eq $false))
        {
            Write-Warning -Message $script:localizedData.MissingDeltaDiscovery
            $badInput = $true
        }

        if ($PSBoundParameters.ContainsKey('TimeSinceLastLogonDays') -and $EnableFilteringExpiredLogon -ne $true)
        {
            Write-Warning -Message $script:localizedData.TimeSinceLastLogon
            $badInput = $true
        }

        if ($PSBoundParameters.ContainsKey('TimeSinceLastPasswordUpdateDays') -and $EnableFilteringExpiredPassword -ne $true)
        {
            Write-Warning -Message $script:localizedData.PasswordExpiredFilter
            $badInput = $true
        }

        $testParams = @{
            CurrentValues = $state
            DesiredValues = $PSBoundParameters
            ValuesToCheck = @('Enabled','EnableDeltaDiscovery','DeltaDiscoveryMins','EnableFilteringExpiredLogon',
                              'TimeSinceLastLogonDays','EnableFilteringExpiredPassword','TimeSinceLastPasswordUpdateDays',
                              'DiscoverDistributionGroupMembership')
        }

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

        if ($ScheduleType)
        {
            $valuesToValidate = @('ScheduleType','RecurInterval','MonthlyWeekOrder','DayOfWeek','DayOfMonth','Start')
            foreach ($item in $valuesToValidate)
            {
                if ($PSBoundParameters.ContainsKey($item))
                {
                    $scheduleCheck += @{
                        $item = $PSBoundParameters[$item]
                    }
                }
            }

            $schedResult = Test-CMSchedule @scheduleCheck -State $state
        }

        if (($EnableDeltaDiscovery -eq $true -and $state.EnableDeltaDiscovery -eq $false) -and
                (-not $PSBoundParameters.ContainsKey('DeltaDiscoveryMins')))
        {
            Write-Warning -Message $script:localizedData.DeltaNoInterval
        }

        if ($PSBoundParameters.ContainsKey('GroupDiscoveryScope'))
        {
            if ($PSBoundParameters.ContainsKey('GroupDiscoveryScopeToInclude') -or
                $PSBoundParameters.ContainsKey('GroupDiscoveryScopeToExclude'))
            {
                Write-Warning -Message $script:localizedData.GdsIgnore
            }
        }
        elseif (-not $PSBoundParameters.ContainsKey('GroupDiscoveryScope') -and
                $PSBoundParameters.ContainsKey('GroupDiscoveryScopeToInclude') -and
                $PSBoundParameters.ContainsKey('GroupDiscoveryScopeToExclude'))
        {
            foreach ($item in $GroupDiscoveryScopeToInclude)
            {
                if ($GroupDiscoveryScopeToExclude -contains $item.Name)
                {
                    Write-Warning -Message ($script:localizedData.GdsInEx -f $item.Name)
                    $result = $false
                }
            }
        }

        if ($GroupDiscoveryScope -or $GroupDiscoveryScopeToInclude)
        {
            if ($GroupDiscoveryScope)
            {
                $refObject = $GroupDiscoveryScope
            }
            elseif ($GroupDiscoveryScopeToInclude)
            {
                $refObject = $GroupDiscoveryScopeToInclude
            }

            $compareParams = @{
                ReferenceObject  = $refObject
                DifferenceObject = $state.GroupDiscoveryScope
                Property         = 'Recurse','Name','LdapLocation'
                IncludeEqual     = $null
            }

            $compare = Compare-Object @compareParams
            $removing = @()
            $missing = @()
            foreach ($item in $compare)
            {
                if ($item.SideIndicator -eq '<=')
                {
                    if ($state.GroupDiscoveryScope.Name -contains $item.Name)
                    {
                        Write-Verbose -Message ($script:localizedData.GdsUpdate -f $item.Name, $item.LdapLocation, $item.Recurse, $item.LdapLocation, $item.Recurse)
                    }
                    else
                    {
                        Write-Verbose -Message ($script:localizedData.GdsMissing -f $item.Name, $item.LdapLocation, $item.Recurse)
                    }

                    $result = $false
                }

                if ($GroupDiscoveryScope)
                {
                    if ($item.SideIndicator -eq '=>')
                    {
                        Write-Verbose -Message ($script:localizedData.GdsExtra -f $item.Name)
                        $result = $false
                    }
                }
            }
        }

        if ((-not $GroupDiscoveryScope) -and ($GroupDiscoveryScopeToExclude))
        {
            foreach ($item in $GroupDiscoveryScopeToExclude)
            {
                if ($state.GroupDiscoveryScope.Name -contains $item)
                {
                    Write-Verbose -Message ($script:localizedData.GdsExtra -f $item)
                    $result = $false
                }
            }
        }

        if ($result -eq $false -or $testResult -eq $false -or $schedResult -eq $false -or $badInput -eq $true)
        {
            $result = $false
        }
        else
        {
            $result = $true
        }
    }
    elseif ($state.Enabled -eq $true)
    {
        Write-Verbose -Message $script:localizedData.TestDisabled
        $result = $false
    }

    Write-Verbose -Message ($script:localizedData.TestState -f $result)
    return $result
}

Export-ModuleMember -Function *-TargetResource