Public/Test-DscMofConfig.ps1

<#
    .SYNOPSIS
        Tests resource states defined in a MOF file or local configuration.
 
    .PARAMETER Path
        Path to the folder containing many MOF files or path to a singular MOF file
 
    .EXAMPLE
        Test-DscMofConfig -Path C:\temp\file.mof
#>

function Test-DscMofConfig
{
    [CmdletBinding()]
    [OutputType([bool])]
    param
    (
        [Parameter()]
        [switch]
        $Force
    )

    $verboseSetting = $PSCmdlet.MyInvocation.BoundParameters['Verbose'].IsPresent -and $PSCmdlet.MyInvocation.BoundParameters['Verbose']
    $output = @()
    $allInstances = @()
    $lcmResourcesList = @()
    $lcm = Get-LcmConfig
    if ($lcm.Settings.Status -ne 'Idle' -and -not [string]::IsNullOrEmpty($lcm.Settings.ProcessId -and -not $Force))
    {
        Write-Warning -Message ($LocalizedData.LcmBusy -f $lcm.Settings.ProcessId)
        return
    }
    elseif ($lcm.Settings.Status -ne 'Idle' -and -not [string]::IsNullOrEmpty($lcm.Settings.ProcessId) -and $Force)
    {
        Write-Verbose -Message ($LocalizedData.ForceStop)
        Stop-Lcm -Force
    }
    else
    {
        $lcm.Settings.Status = 'Busy'
        $lcm.Settings.ProcessId = $PID
        $lcm | ConvertTo-Json -Depth 6 | Out-File -FilePath $MofConfigPath
    }

    foreach($configuration in $lcm.Configurations)
    {
        $lcmResourcesList += $configuration.Resources
        $allInstances += Get-MofCimInstances -Path $configuration.MofPath
    }

    $graph = @{}
    foreach ($mofInstance in $allInstances)
    {
        $graph[$mofInstance.ResourceId] = $mofInstance.DependsOn
    }

    $sorted = Invoke-SortDependencyGraph -Graph $graph
    $count = 0
    foreach ($resourceId in $sorted)
    {
        $instance = $allInstances.Where({$_.ResourceId -eq $resourceId}) | Select-Object -First 1
        $updateResource = $lcmResourcesList.Where({$_.ResourceID -eq $resourceId}) | Select-Object -First 1

        # Test that module is present. If not skip it.
        if (-not (Test-ModulePresent -ModuleName $instance.ModuleName -ModuleVersion $instance.ModuleVersion))
        {
            Write-Warning -Message ($LocalizedData.ModuleNotPresent -f $instance.ModuleName, $instance.ModuleVersion, $instance.ResourceId)
            if ($PSCmdlet.ParameterSetName -eq 'ByConfiguration')
            {
                $updateResource.Exception = ($LocalizedData.ModuleNotPresent -f $instance.ModuleName, $instance.ModuleVersion, $instance.ResourceId)
            }

            continue
        }

        $count++
        Write-Progress -Activity "$count of $($allInstances.Count), $(($count/$($allInstances.Count)).ToString('P'))" -Status "$($instance.ResourceId)" -PercentComplete ($count/$($allInstances.Count))
        
        $dependencySet = $false
        if ($null -ne $instance.DependsOn)
        {
            $skip = $false
            foreach ($dependencyId in $instance.DependsOn)
            {
                $lastSet = ($allInstances.Where({$_.ResourceId -eq $dependencyId}) | Select-Object -First 1).LastSet
                $dependencySet = -not [string]::IsNullOrEmpty($lastSet)
                if ($dependencySet)
                {
                    Write-Verbose -Message ($LocalizedData.DependencySet -f $resourceId, $dependencyId)
                }
                else
                {
                    $updateResource.Exception = ($LocalizedData.DependencyNotSet -f $resourceId, $dependencyId)
                    Write-Warning -Message ($LocalizedData.DependencyNotSet -f $resourceId, $dependencyId)
                    $skip = $true
                    break
                }
            }
        }

        if ($skip)
        {
            break
        }

        try
        {
            $resource = Convert-MofInstance -Instance $instance -IncludeProperties
        }
        catch
        {
            $updateResource.Exception = $_.Exception.Message
            Write-Warning -Message $_.Exception.Message
            continue
        }
        
        # Check for cancellation token
        $cancel = (Get-LcmConfig).Settings.Cancel
        if ($cancel -eq $true)
        {
            break
        }

        try
        {
            $result = Test-MofResource -Resource $resource -Verbose:$verboseSetting
            $updateResource.LastTest = Get-TimeStamp
            $updateResource.InDesiredState = $result

            # Check for cancellation token
            $cancel = (Get-LcmConfig).Settings.Cancel
            if ($cancel -eq $true)
            {
                break
            }
        }
        catch
        {
            $updateResource.Exception = $_.Exception.Message
            $updateResource.InDesiredState = $false
            Write-EventLogEntry -EntryMessage "$(`$LocalizedData.ExternalFunctionError)" -EntryArguments @($updateResource.ResourceId, "Test", $_.Exception.Message) -EntryType Error
        }
       
        $output += $result
    }

    # Update LCM status
    $lcm | ConvertTo-Json -Depth 6 | Out-File -FilePath $MofConfigPath
    Reset-Lcm

    Write-Progress -Completed -Activity 'Completed'
    return ($output -notcontains $false)
}