Set service startup using DSC Windows PowerShell Desired State Configuration (DSC) newbie here. The MOF file generation fails with:


PSDesiredStateConfiguration\Node : The argument is null or empty. Provide an argument that is not null or empty, and then try the command again. At line:13 char:5
+     Node localhost
+     ~~~~
    + CategoryInfo          : MetadataError: (:) [PSDesiredStateConfiguration\node], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : ArgumentIsNull,PSDesiredStateConfiguration\node   Compilation errors occurred while processing configuration 'SQLConfig'. Please review the errors reported in error stream and modify your configuration code appropriately. At C:\windows\system32\WindowsPowerShell\v1.0\Modules\PSDesiredStateConfiguration\PSDesiredStateConfiguration.psm1:3917 char:5
+     throw $ErrorRecord
+     ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (SQLConfig:String) [], InvalidOperationException
    + FullyQualifiedErrorId : FailToProcessConfiguration



Script

Configuration SQLConfig
{
    param(
        [Parameter(Mandatory =$true)][string[]]$serviceConfig,
        [Parameter(Mandatory =$true)][string]$DataDrive,
        [Parameter(Mandatory =$true)][string]$LogDrive

    )
    Import-DscResource -ModuleName SqlServerDsc
    Import-DscResource -ModuleName PSDesiredStateConfiguration

    Node localhost
    {
        WindowsFeature Net35
        {
            Name = 'NET-Framework-Core'
            Ensure = 'Present'
        }
        WindowsFeature Net45
        {
            Name = 'NET-Framework-45-Core'
            Ensure = 'Present'
        }
        WindowsFeature Cluster
        {
            Name = 'RSAT-Clustering'
            Ensure = 'Present'
        }

        File datadrive
        {
           Type = 'Directory'
           DestinationPath = $DataDrive
           Ensure ='Present' 

        }
        File logdrive
        {
           Type = 'Directory'
           DestinationPath = $LogDrive
           Ensure ='Present' 
        }
        SqlDatabaseDefaultLocation dataPath
        {
            InstanceName = 'MSSQLSERVER'
            Path = $DataDrive
            ServerName = 'localhost'
            Type = 'Data'
            DependsOn = '[File]datadrive'
        }
        SqlDatabaseDefaultLocation logPath
        {
            InstanceName = 'MSSQLSERVER'
            Path = $LogDrive
            ServerName = 'localhost'
            Type = 'Log'
            DependsOn = '[File]logdrive'
        }
        foreach ($service in $serviceConfig) {
            ServiceSet $service
            {
                Name = $service.ServiceName
                State = $service.State
                StartupType = $service.StartupType
                Ensure = $service.Ensure
            }


        }

    }
}

#region create configuration data

$serviceConfig=(
    @{ServiceName='MSSQLSERVER';State='Running';StartupType='Automatic';Ensure='Present'},
    @{ServiceName='SQLSERVERAGENT';State='Running';StartupType='Automatic';Ensure='Present'},
    @{ServiceName='SQLBrowser';State='Ignore';StartupType='Disabled';Ensure='Present'}
)
SQLConfig -serviceConfig $serviceConfig -DataDrive "F:\Data" -LogDrive "H:\Log" -OutputPath "C:\dump"
A few things that have to be corrected in your configuration function:


The parameter serviceConfig has to be the type [object[]] in order to accept an hashtable. Using [string[]] PowerShell does not properly handle iterating over that object, since it is a literal object and not just an array of strings.
When you are using a resource in DSC it has to be unique name. Your declaration of the ServiceSet resource is simply passing in $service; which in PowerShell terms is simply passing [System.Collections.Hashtable] each time and is therefore not unique.


Corrected version of the configuration that test and runs successfully on my system:

Configuration SQLConfig
{
    param(
        [Parameter(Mandatory =$true)][object[]]$serviceConfig,
        [Parameter(Mandatory =$true)][string]$DataDrive,
        [Parameter(Mandatory =$true)][string]$LogDrive

    )
    Import-DscResource -ModuleName SqlServerDsc
    Import-DscResource -ModuleName PSDesiredStateConfiguration

    Node localhost 
    {
        WindowsFeature Net35 {
            Name   = 'NET-Framework-Core'
            Ensure = 'Present'
        }
        WindowsFeature Net45 {
            Name   = 'NET-Framework-45-Core'
            Ensure = 'Present'
        }
        WindowsFeature Cluster {
            Name   = 'RSAT-Clustering'
            Ensure = 'Present'
        }

        File datadrive {
            Type            = 'Directory'
            DestinationPath = $DataDrive
            Ensure          ='Present' 

        }
        File logdrive {
            Type            = 'Directory'
            DestinationPath = $LogDrive
            Ensure          ='Present' 
        }
        SqlDatabaseDefaultLocation dataPath {
            InstanceName = 'MSSQLSERVER'
            Path         = $DataDrive
            ServerName   = 'localhost'
            Type         = 'Data'
            DependsOn    = '[File]datadrive'
        }
        SqlDatabaseDefaultLocation logPath {
            InstanceName = 'MSSQLSERVER'
            Path         = $LogDrive
            ServerName   = 'localhost'
            Type         = 'Log'
            DependsOn    = '[File]logdrive'
        }
        foreach ($service in $serviceConfig) {
            ServiceSet $service.ServiceName {
                Name        = $service.ServiceName
                State       = $service.State
                StartupType = $service.StartupType
                Ensure      = $service.Ensure
            }
        }

    }
}

$serviceConfig= @(
    @{ServiceName='MSSQLSERVER';State='Running';StartupType='Automatic';Ensure='Present'},
    @{ServiceName='SQLSERVERAGENT';State='Running';StartupType='Automatic';Ensure='Present'},
    @{ServiceName='SQLBrowser';State='Stopped';StartupType='Disabled';Ensure='Present'}
)
SQLConfig -serviceConfig $serviceConfig -DataDrive "C:\temp" -LogDrive "C:\temp" -OutputPath "C:\temp" -Verbose