DSC: Combining class and MOF-based resources in one module

I had the need to add a class-based resource to an existing module that only contained MOF resources. Initially, I dropped the .psd1 and .psm1 files into the module’s DSCResources folder and updated the root .psd1 file. Using Get-DSCResource -Name ModuleName the new class resource was visible. I created a new configuration, to use the resource which compiled without issue, however on running it with Start-DSCResource I got the lovely error:

Could not find the generate schema file C:\Windows\system32\config\systemprofile\AppData\Local\dsc\cSQLServerTraceFlag.1.0.cSQLServerTraceFlag.schema.mof.
    + CategoryInfo          : InvalidData: (:) [], CimException
    + FullyQualifiedErrorId : ProviderSchemaNotFound
    + PSComputerName        : localhost

When browsing to C:\Windows\system32\config\systemprofile\AppData\Local\dsc\, I could see the file SqlServerDsc.10.0.cSQLServerTraceFlag.schema.mof had been created, however, it’s the wrong name.

After a lot of messing around with the new using key word, I started to look at the cmdlet that produces the incorrectly named file Start-DscConfiguration, which is part of the built-in PSDesiredStateConfiguration module. Looking at its .psd1 file, I noticed in the NestedModules = @() section the entry 'DSCClassResources\WindowsPackageCab\WindowsPackageCab.psd1' and sure enough the resource had the folder PSDesiredStateConfiguration\DSCClassResources.

Back to my module, I created the folder `ModuleName\DSCClassResources, moved the class-based resource into it, tried the configuration again and this time, not only did it compile, it also ran.

In this case, I was adding a community class resource to the SqlServerDsc resource. Probably not best practice, but I couldn’t wait for the developer to finish testing and for MS to commit it to the master branch.


The steps are:

  1. Download cSqlServerTraceFlag. Extract ZIP and rename to
  2. cSqlServerTraceFlag Create the folder
  3. “%ProgramFiles%\WindowsPowerShell\Modules\SqlServerDsc\DSCClassResources”
  4. Drop the folder (cSqlServerTraceFlag) into “%ProgramFiles%\WindowsPowerShell\Modules\SqlServerDsc\DSCClassResources”
  5. Edit .\Modules\SqlServerDsc\SQLServerDsc.psd1, adding:
    • NestedModules = @(‘DSCResources\cSQLServerTraceFlag\cSQLServerTraceFlag.psm1’)
    • DscResourcesToExport = @(‘cSQLServerTraceFlag’)


The configuration I used to test:

Configuration testTraceFlags
    Import-DscResource -ModuleName sqlServerDsc

    Node localhost
        cSqlServerTraceFlag "Set_Startup_Parameters"
            Ensure = "Present"
            SQLInstanceName = "MSSQLSERVER"
            TraceFlag = 'T1117'
            RestartSQLService = $true


testTraceFlags -OutputPath C:\Configurations\testTraceFlags -Verbose #-debug
Start-DscConfiguration -Path C:\Configurations\testTraceFlags -Wait -Force -Verbose -Debug

Update 1

I’ve discovered a little more is involved when there are helper functions in the mix. Like a good little wannabe developer, I encapsulate my functions. i.e each function is in its own .PS1 file.
Best practice dictates, in *.PSD1 files, we shouldn’t use FunctionsToExport = '*'. Instead we should explicitly name the functions. This is needed for the “AutoLoad” function feature to work anyway:

FunctionsToExport = @('Get-Something','Invoke-SomethingElse'.'Write-LetterToJohn')

So my resource file structure looks like:

C:\Program Files\WindowsPowerShell
        |   Demo.psd1
        |   Demo.psm1
        |   +---aClassResource
        |   |       aClassResource.psd1
        |   |       aClassResource.psm1
        |   |       aClassResourceHelper.psm1 (contains functions: Get-RegistryKey, Add-RegistryKey, Remove-RegistryKey)
        |   |
        |   \---anotherClassResource
        |           anotherClassResource.psd1
        |           anotherClassResource.psm1
        |           anotherClassResourceHelper.psm1
        |   +---ARC_MofResource1
        |   |       ARC_ModResource1.psm1
        |   |       ARC_ModResource1.schema.mof
        |   |
        |   \---ARC_MofResource2
        |           ARC_ModResource2.psm1
        |           ARC_ModResource2.schema.mof

When I moved aClassResource from ..Modules to ..Modules\Demo, I did the changes to Demo.psd1 as documented above, however aClassResource was not picked up by Get-DscResource -Module Demo until I set FunctionsToExport = '*', however this really slowed down Intellisence, compilation and execution. I recalled reading this post, whilst troubleshoot ordinary PS modules in the past. I looked it up again, and tried “Ewan Middleton’s” advice:

Try removing the .psm1 suffix from each of the Nested Modules you have listed, so you’ll have NestedModules = @(‘Mod1′,’Mod2’). I was experiencing exactly the scenario as you until I did this and now both nested modules autoload as expected and I can see all exported functions from both when using Get-Module. This is even after restarting ISE and deleting CommandAnalysis.

In Demo.psd1, I changed NestedModules = @('DSCResources\aClassResource\aClassResource.psm1') to NestedModules = @('DSCResources\aClassResource\aClassResource').
In Demo.psd1, I left FunctionsToExport = @('Get-Something','Invoke-SomethingElse'.'Write-LetterToJohn') unchanged.
In aClassResource.psm1, I changed FunctionsToExport = '*' to FunctionsToExport = @('Get-RegistryKey','Add-RegistryKey'.'Remove-RegistryKey').

Running Get-DscResource -Module Demo works, and I can compile and execute the module.

I’m sure there will be more changes along the way and sticking to the principle of ‘Encapsulation’, I should refactor aClassResourceHelper.psm1 functions into their own .ps1 files.

Leave a Reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

This site uses Akismet to reduce spam. Learn how your comment data is processed.