Skip to main content

Overview

ConfigurationProcessor is the central class for interacting with configuration sets. It provides methods to:
  • Open and parse configuration files
  • Apply configuration sets to the system
  • Test if the system matches the desired state
  • Get current system state
  • Check for conflicts between configurations
  • Manage configuration history

Class Definition

runtimeclass ConfigurationProcessor
{
    ConfigurationProcessor(IConfigurationSetProcessorFactory factory);
    
    // Diagnostics
    event EventHandler<IDiagnosticInformation> Diagnostics;
    DiagnosticLevel MinimumLevel;
    
    // Telemetry
    String Caller;
    Guid ActivityIdentifier;
    Boolean GenerateTelemetryEvents;
    
    // Events
    event TypedEventHandler<ConfigurationSet, ConfigurationChangeData> ConfigurationChange;
    
    // History
    IVector<ConfigurationSet> GetConfigurationHistory();
    IAsyncOperation<IVector<ConfigurationSet>> GetConfigurationHistoryAsync();
    
    // Opening configurations
    OpenConfigurationSetResult OpenConfigurationSet(IInputStream stream);
    IAsyncOperation<OpenConfigurationSetResult> OpenConfigurationSetAsync(IInputStream stream);
    
    // Conflict detection
    IVector<ConfigurationConflict> CheckForConflicts(
        IVectorView<ConfigurationSet> configurationSets, 
        Boolean includeConfigurationHistory
    );
    IAsyncOperation<IVector<ConfigurationConflict>> CheckForConflictsAsync(
        IVectorView<ConfigurationSet> configurationSets, 
        Boolean includeConfigurationHistory
    );
    
    // Details
    GetConfigurationSetDetailsResult GetSetDetails(
        ConfigurationSet configurationSet, 
        ConfigurationUnitDetailFlags detailFlags
    );
    IAsyncOperationWithProgress<GetConfigurationSetDetailsResult, GetConfigurationUnitDetailsResult> 
        GetSetDetailsAsync(
            ConfigurationSet configurationSet, 
            ConfigurationUnitDetailFlags detailFlags
        );
    
    GetConfigurationUnitDetailsResult GetUnitDetails(
        ConfigurationUnit unit, 
        ConfigurationUnitDetailFlags detailFlags
    );
    IAsyncOperation<GetConfigurationUnitDetailsResult> GetUnitDetailsAsync(
        ConfigurationUnit unit, 
        ConfigurationUnitDetailFlags detailFlags
    );
    
    // Apply operations
    ApplyConfigurationSetResult ApplySet(
        ConfigurationSet configurationSet, 
        ApplyConfigurationSetFlags flags
    );
    IAsyncOperationWithProgress<ApplyConfigurationSetResult, ConfigurationSetChangeData> 
        ApplySetAsync(
            ConfigurationSet configurationSet, 
            ApplyConfigurationSetFlags flags
        );
    
    ApplyConfigurationUnitResult ApplyUnit(ConfigurationUnit unit);
    IAsyncOperation<ApplyConfigurationUnitResult> ApplyUnitAsync(ConfigurationUnit unit);
    
    // Test operations
    TestConfigurationSetResult TestSet(ConfigurationSet configurationSet);
    IAsyncOperationWithProgress<TestConfigurationSetResult, TestConfigurationUnitResult> 
        TestSetAsync(ConfigurationSet configurationSet);
    
    TestConfigurationUnitResult TestUnit(ConfigurationUnit unit);
    IAsyncOperation<TestConfigurationUnitResult> TestUnitAsync(ConfigurationUnit unit);
    
    // Get settings
    GetConfigurationUnitSettingsResult GetUnitSettings(ConfigurationUnit unit);
    IAsyncOperation<GetConfigurationUnitSettingsResult> GetUnitSettingsAsync(ConfigurationUnit unit);
    
    GetAllConfigurationUnitSettingsResult GetAllUnitSettings(ConfigurationUnit unit);
    IAsyncOperation<GetAllConfigurationUnitSettingsResult> GetAllUnitSettingsAsync(ConfigurationUnit unit);
    
    // Find processors
    IVector<IConfigurationUnitProcessorDetails> FindUnitProcessors(FindUnitProcessorsOptions findOptions);
    IAsyncOperation<IVector<IConfigurationUnitProcessorDetails>> FindUnitProcessorsAsync(FindUnitProcessorsOptions findOptions);
    
    // Get all units
    GetAllConfigurationUnitsResult GetAllUnits(ConfigurationUnit unit);
    IAsyncOperation<GetAllConfigurationUnitsResult> GetAllUnitsAsync(ConfigurationUnit unit);
}

Constructor

ConfigurationProcessor()

Creates a configuration processor with the specified factory.
factory
IConfigurationSetProcessorFactory
required
The processor factory implementation (e.g., PowerShell DSC)
using Microsoft.Management.Configuration;

// Create PowerShell DSC factory
var factory = await ConfigurationStaticFunctions
    .CreateConfigurationSetProcessorFactoryAsync("pwsh");

var processor = new ConfigurationProcessor(factory);

// Configure diagnostics
processor.MinimumLevel = DiagnosticLevel.Informational;
processor.Caller = "MyApp";
processor.GenerateTelemetryEvents = true;

Opening Configuration Sets

OpenConfigurationSetAsync()

Loads a configuration set from a stream.
stream
IInputStream
required
Input stream containing YAML configuration
Returns
IAsyncOperation<OpenConfigurationSetResult>
Result containing the loaded configuration set or error details
using Windows.Storage;

// Open configuration file
var file = await StorageFile.GetFileFromPathAsync(
    @"C:\Configs\setup.yml"
);

using (var stream = await file.OpenReadAsync())
{
    var openResult = await processor.OpenConfigurationSetAsync(stream);
    
    if (openResult.ResultCode == 0)
    {
        var configSet = openResult.Set;
        Console.WriteLine($"Loaded: {configSet.Name}");
        Console.WriteLine($"Units: {configSet.Units.Count}");
        Console.WriteLine($"Schema: {configSet.SchemaVersion}");
        
        // List units
        foreach (var unit in configSet.Units)
        {
            Console.WriteLine($"  - {unit.Type} ({unit.Identifier})");
        }
    }
    else
    {
        Console.WriteLine($"Failed to open configuration:");
        Console.WriteLine($"  HRESULT: 0x{openResult.ResultCode:X8}");
        Console.WriteLine($"  Field: {openResult.Field}");
        Console.WriteLine($"  Value: {openResult.Value}");
        Console.WriteLine($"  Location: Line {openResult.Line}, Column {openResult.Column}");
    }
}

Applying Configurations

ApplySetAsync()

Applies a configuration set to the system.
configurationSet
ConfigurationSet
required
The configuration set to apply
flags
ApplyConfigurationSetFlags
required
Flags controlling application behavior
Returns
IAsyncOperationWithProgress<ApplyConfigurationSetResult, ConfigurationSetChangeData>
Async operation with progress updates
ApplyConfigurationSetFlags values:
  • None - Default behavior
  • DoNotOverwriteMatchingOriginSet - Create new instance instead of updating existing
  • PerformConsistencyCheckOnly - Only validate, don’t apply
var configSet = openResult.Set;

// Apply configuration with progress tracking
var operation = processor.ApplySetAsync(
    configSet,
    ApplyConfigurationSetFlags.None
);

operation.Progress = (op, data) =>
{
    switch (data.Change)
    {
        case ConfigurationSetChangeEventType.SetStateChanged:
            Console.WriteLine($"Set State: {data.SetState}");
            break;
            
        case ConfigurationSetChangeEventType.UnitStateChanged:
            Console.WriteLine($"Unit: {data.Unit.Type}");
            Console.WriteLine($"  State: {data.UnitState}");
            
            if (data.UnitState == ConfigurationUnitState.Completed)
            {
                var result = data.ResultInformation;
                if (result.ResultCode == 0)
                {
                    Console.WriteLine($"  ✓ Success");
                }
                else
                {
                    Console.WriteLine($"  ✗ Failed: {result.Description}");
                    Console.WriteLine($"    HRESULT: 0x{result.ResultCode:X8}");
                    Console.WriteLine($"    Details: {result.Details}");
                }
            }
            break;
    }
};

var applyResult = await operation;

Console.WriteLine($"\nApply Result: 0x{applyResult.ResultCode:X8}");
Console.WriteLine($"Unit Results: {applyResult.UnitResults.Count}");

foreach (var unitResult in applyResult.UnitResults)
{
    Console.WriteLine($"  {unitResult.Unit.Type}: {unitResult.State}");
    
    if (unitResult.State == ConfigurationUnitState.Completed)
    {
        Console.WriteLine($"    Previously in desired state: {unitResult.PreviouslyInDesiredState}");
        Console.WriteLine($"    Reboot required: {unitResult.RebootRequired}");
    }
}

Testing Configurations

TestSetAsync()

Tests if the system state matches the configuration set.
configurationSet
ConfigurationSet
required
The configuration set to test
Returns
IAsyncOperationWithProgress<TestConfigurationSetResult, TestConfigurationUnitResult>
Async operation with progress for each unit tested
var configSet = openResult.Set;

var operation = processor.TestSetAsync(configSet);

operation.Progress = (op, unitResult) =>
{
    Console.WriteLine($"Testing: {unitResult.Unit.Type}");
    Console.WriteLine($"  Result: {unitResult.TestResult}");
    
    if (unitResult.ResultInformation.ResultCode != 0)
    {
        Console.WriteLine($"  Error: {unitResult.ResultInformation.Description}");
    }
};

var testResult = await operation;

Console.WriteLine($"\nOverall Test Result: {testResult.TestResult}");
Console.WriteLine($"\nUnit Results:");

foreach (var unitResult in testResult.UnitResults)
{
    Console.WriteLine($"  {unitResult.Unit.Type}:");
    
    switch (unitResult.TestResult)
    {
        case ConfigurationTestResult.Positive:
            Console.WriteLine($"    ✓ System is in desired state");
            break;
            
        case ConfigurationTestResult.Negative:
            Console.WriteLine($"    ✗ System is NOT in desired state");
            break;
            
        case ConfigurationTestResult.Failed:
            Console.WriteLine($"    ✗ Test failed: {unitResult.ResultInformation.Description}");
            break;
            
        case ConfigurationTestResult.NotRun:
            Console.WriteLine($"    - Test not run");
            break;
    }
}

Getting Details

GetSetDetailsAsync()

Retrieves detailed information about all units in a configuration set.
configurationSet
ConfigurationSet
required
The configuration set
detailFlags
ConfigurationUnitDetailFlags
required
Level of detail to retrieve
ConfigurationUnitDetailFlags values:
  • None - No details
  • Local - Only local data
  • Catalog - Query catalog (no downloads)
  • Download - Download modules (don’t load)
  • Load - Download and load modules
  • ReadOnly - Local | Catalog
var configSet = openResult.Set;

var operation = processor.GetSetDetailsAsync(
    configSet,
    ConfigurationUnitDetailFlags.Load
);

operation.Progress = (op, unitDetails) =>
{
    Console.WriteLine($"Loading details for: {unitDetails.Unit.Type}");
};

var detailsResult = await operation;

foreach (var unitDetails in detailsResult.UnitResults)
{
    var unit = unitDetails.Unit;
    var details = unitDetails.Details;
    
    if (details != null)
    {
        Console.WriteLine($"\nUnit: {unit.Type}");
        Console.WriteLine($"  Description: {details.UnitDescription}");
        Console.WriteLine($"  Module: {details.ModuleName}");
        Console.WriteLine($"  Version: {details.Version}");
        Console.WriteLine($"  Author: {details.Author}");
        Console.WriteLine($"  Publisher: {details.Publisher}");
        Console.WriteLine($"  Is Public: {details.IsPublic}");
        Console.WriteLine($"  Is Local: {details.IsLocal}");
        
        if (details.UnitDocumentationUri != null)
        {
            Console.WriteLine($"  Docs: {details.UnitDocumentationUri}");
        }
        
        // Settings details
        Console.WriteLine($"  Settings:");
        foreach (var setting in details.Settings)
        {
            Console.WriteLine($"    - {setting.Identifier}");
            Console.WriteLine($"      Description: {setting.Description}");
            Console.WriteLine($"      Type: {setting.Type}");
            Console.WriteLine($"      Required: {setting.IsRequired}");
            Console.WriteLine($"      IsKey: {setting.IsKey}");
        }
    }
    else if (unitDetails.ResultInformation.ResultCode != 0)
    {
        Console.WriteLine($"\nFailed to get details for: {unit.Type}");
        Console.WriteLine($"  Error: {unitDetails.ResultInformation.Description}");
    }
}

Checking for Conflicts

CheckForConflictsAsync()

Checks for conflicts between configuration sets.
configurationSets
IVectorView<ConfigurationSet>
required
Configuration sets to check
includeConfigurationHistory
Boolean
required
Whether to check against previously applied configurations
var configSet = openResult.Set;

// Check against history
var configSets = new List<ConfigurationSet> { configSet };
var conflicts = await processor.CheckForConflictsAsync(
    configSets.AsReadOnly(),
    includeConfigurationHistory: true
);

if (conflicts.Count > 0)
{
    Console.WriteLine($"Found {conflicts.Count} conflicts:");
    
    foreach (var conflict in conflicts)
    {
        Console.WriteLine($"\nConflict Type: {conflict.Conflict}");
        Console.WriteLine($"  First Set: {conflict.FirstSet.Name}");
        Console.WriteLine($"  Second Set: {conflict.SecondSet.Name}");
        
        switch (conflict.Conflict)
        {
            case ConfigurationConflictType.MatchingOrigin:
                Console.WriteLine($"  Both sets have same origin: {conflict.FirstSet.Origin}");
                break;
                
            case ConfigurationConflictType.IdenticalSetApplied:
                Console.WriteLine($"  Identical set already applied");
                break;
                
            case ConfigurationConflictType.SettingsConflict:
                Console.WriteLine($"  First Unit: {conflict.FirstUnit.Type}");
                Console.WriteLine($"  Second Unit: {conflict.SecondUnit.Type}");
                Console.WriteLine($"  Conflicting settings:");
                
                foreach (var setting in conflict.Settings)
                {
                    Console.WriteLine($"    {setting.Name}");
                    Console.WriteLine($"      First: {setting.FirstValue}");
                    Console.WriteLine($"      Second: {setting.SecondValue}");
                }
                break;
        }
    }
}
else
{
    Console.WriteLine("No conflicts detected");
}

Configuration History

GetConfigurationHistoryAsync()

Retrieves previously applied configuration sets.
var history = await processor.GetConfigurationHistoryAsync();

Console.WriteLine($"Configuration History ({history.Count} sets):\n");

foreach (var configSet in history)
{
    Console.WriteLine($"Name: {configSet.Name}");
    Console.WriteLine($"  Origin: {configSet.Origin}");
    Console.WriteLine($"  State: {configSet.State}");
    Console.WriteLine($"  Instance ID: {configSet.InstanceIdentifier}");
    Console.WriteLine($"  First Apply: {configSet.FirstApply}");
    
    if (configSet.ApplyBegun != default)
    {
        Console.WriteLine($"  Last Apply Begun: {configSet.ApplyBegun}");
    }
    
    if (configSet.ApplyEnded != default)
    {
        Console.WriteLine($"  Last Apply Ended: {configSet.ApplyEnded}");
        
        var duration = configSet.ApplyEnded - configSet.ApplyBegun;
        Console.WriteLine($"  Duration: {duration.TotalSeconds:F2}s");
    }
    
    Console.WriteLine($"  Units: {configSet.Units.Count}");
    Console.WriteLine();
}

Diagnostics

Diagnostics Event

Receive diagnostic information from the configuration system.
processor.MinimumLevel = DiagnosticLevel.Verbose;

processor.Diagnostics += (sender, diagnostics) =>
{
    var level = diagnostics.Level switch
    {
        DiagnosticLevel.Verbose => "[VERBOSE]",
        DiagnosticLevel.Informational => "[INFO]",
        DiagnosticLevel.Warning => "[WARN]",
        DiagnosticLevel.Error => "[ERROR]",
        DiagnosticLevel.Critical => "[CRITICAL]",
        _ => "[UNKNOWN]"
    };
    
    Console.WriteLine($"{level} {diagnostics.Message}");
};

Build docs developers (and LLMs) love