Wish I can author DSC Resource in C#!!

Wish I can author DSC Resource in C#!!

Rate This
  • Comments 6

In previous blog, we learned how one can use their PowerShell skills to author DSC resources very easily. Still there are folks (we met some at TechEd NA) who want to author their DSC resources using C# because they are more productive with it than PowerShell language. Well, you can fully leverage the power of DSC by writing your resources in C#. In this blog, we will explore how you can write a C# based DSC resource and later seamlessly consume it from your DSC Configurations.

Authoring DSC resources in C#

For the purpose of this blog, we will write a DSC resource named “xDemoFile”. This resource will be used to assert the existence of a file and its contents. It is similar to a File resource but with limited functionalities.

I)             Project Setup:-

a)      Open visual studio

b)      Create a C# project and provide the name (such as  “cSharpDSCResourceExample”)

c)       Select “Class Library” from the available project templates

d)      Hit “Ok”

e)    Add assembly reference to system.automation.management.dll preferably from PowerShell SDK [but you can add assembly reference to your project from the windows assembly cache, GAC (<systemDrive>\ Windows\Microsoft.NET\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad364e35\System.Management.Automation.dll)].

f)      *Update the assembly name to match the DSC resource name. (write right click on the project then hit properties and change the Assembly Name to MSFT_xDemoFile)

 

II)           Resource Definition

Similar to script based DSC resource. You will need to define the input and output parameters of your resources in <ResourceName>.schema.mof.  You can generate the schema of your resource using the Resource Designer Tool.

Save the following in to a file named MSFT_xDemoFile.Schema.mof

[ClassVersion("1.0.0"), FriendlyName("xDemoFile")]

class MSFT_XDemoFile : OMI_BaseResource

{

                [Key, Description("path")] String Path;

                [Write, Description("Should the file be present"), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure;

                [Write, Description("Contentof file.")] String Content;                  

};

 

 

III)         Resource Implementation

In order to write DSC Resources in C#, you need to implement three PowerShell cmdlets. PowerShell cmdlets are written by inheriting from PSCmdlet or Cmdlet. Detail on how to write PowerShell Cmdlet in C# can be found in this MSDN documentation.

See below for the signature of the cmdlets:-

Get-TargetResource

       [OutputType(typeof(System.Collections.Hashtable))]

       [Cmdlet(VerbsCommon.Get, "TargetResource")]

       public class GetTargetResource : PSCmdlet

       {

              [Parameter(Mandatory = true)]

              public string Path { get; set; }

 

///<summary>

/// Implement the logic to write the current state of the resource as a

/// Hash table with keys being the resource properties

/// and the Values are the corresponding current values on the target machine.

 

///</summary>

              protected override void ProcessRecord()

              {

// Download the zip file at the end of this blog to see sample implementation.

 }

 

Set-TargetResouce

         [OutputType(typeof(void))]

    [Cmdlet(VerbsCommon.Set, "TargetResource")]

    public class SetTargetResource : PSCmdlet

    {

        privatestring _ensure;

        privatestring _content;

       

[Parameter(Mandatory = true)]

        public string Path { get; set; }

       

[Parameter(Mandatory = false)]     

       [ValidateSet("Present", "Absent", IgnoreCase = true)]

       public string Ensure {

            get

            {

                // set the default to present.

               return (this._ensure ?? "Present");

            }

            set

            {

                this._ensure = value;

            }

           } 

            public string Content {

            get { return (string.IsNullOrEmpty(this._content) ? "" : this._content); }

            set { this._content = value; }

        }

 

///<summary>

        /// Implement the logic to set the state of the machine to the desired state.

        ///</summary>

        protected override void ProcessRecord()

        {

//Implement the set method of the resource

/* Uncomment this section if your resource needs a machine reboot.

PSVariable DscMachineStatus = new PSVariable("DSCMachineStatus", 1, ScopedItemOptions.AllScope);

                this.SessionState.PSVariable.Set(DscMachineStatus);

*/    

  }

    }

Test-TargetResource    

       [Cmdlet("Test", "TargetResource")]

    [OutputType(typeof(Boolean))]

    public class TestTargetResource : PSCmdlet

    {  

       

        private string _ensure;

        private string _content;

 

        [Parameter(Mandatory = true)]

        public string Path { get; set; }

 

        [Parameter(Mandatory = false)]

        [ValidateSet("Present", "Absent", IgnoreCase = true)]

        public string Ensure

        {

            get

            {

                // set the default to present.

                return (this._ensure ?? "Present");

            }

            set

            {

                this._ensure = value;

            }

        }

 

        [Parameter(Mandatory = false)]

        public string Content

        {

            get { return (string.IsNullOrEmpty(this._content) ? "“:this._content);}

            set { this._content = value; }

        }

 

///<summary>

/// Write a Boolean value which indicates whether the current machine is in   

/// desired state or not.

        ///</summary>

        protected override void ProcessRecord()

        {

                // Implement the test method of the resource.

        }

}

 

IV)        How to handle Machine reboot in C# based DSC Resources.

If your resource needs a machine reboot. The way to indicate that in script-based DSC resource is setting the global variable $global:DSCMachineStatus  to 1 in the Set-TargetResource function of the resource.  To do similar in C#-based DSC resource, you will need to set the same variable in the runspace where the Set Cmdlet of the resource will be executed.

Adding the following two lines will signal a machine reboot to the DSC engine.

PSVariable DSCMachineStatus = new PSVariable("DSCMachineStatus", 1, ScopedItemOptions.AllScope);

this.SessionState.PSVariable.Set(DSCMachineStatus);

 

 

Consume C# based resources

I)        How to deploy C# based DSC Resource

The folder structure of C# based DSC resource is the same as the script based resource. Please refer to this blog to see how DSC resources should be deployed in your machine.

The output binaries from your project and the schema mof of the resource should be deployed to the correct path before you can use it to author or apply configurations.

Example: - if you deploy the resource under a module “CSharpDSCResource” inside $env:programfiles, the folder structure would look like:-

             $env:ProgramFiles\WindowsPowerShell\Modules\CSharpDSCResource\DSCResources\MSFT_XDemoFile\MSFT_XDemoFile.dll

             $env:ProgramFiles\WindowsPowerShell\Modules\CSharpDSCResource\DSCResources\MSFT_XDemoFile\MSFT_XDemoFile.Shema.mof

II)        Create Configuration:-

 

Configuration CsharpExample

{

    Import-DSCResource -Module CSharpDSCResource

    Node("localhost")

    {

        xDemoFile fileLog

        {

            Path = "c:\foo.txt"

            Content = "content example"

            Ensure =Present"         

           

        }

    }

}

 

III)        Run the configuration:-

 

Start-DSCConfiguration -ComputerName localhost -Path .\CsharpExample\ -Verbose -Wait

           

 

Berhe Abrha

Windows PowerShell Team

 

 

 

 

 

 

Attachment: Complet_Sample_DSCResource_CSharp.zip
Leave a Comment
  • Please add 2 and 7 and type the answer here:
  • Post
  • Very handy, thanks! By the same token, could I use P-Invoke or COM Interop in a  C# resource to call native APIs and COM objects? Any limitations there?

  • If you guys have any tools to help develop schema MOFs, that would be awesome. Not everyone knows how to write MOF syntax. :)

    Cheers,

    Trevor Sullivan

    Microsoft PowerShell MVP

  • This is great! It'd be even better if a PowerShell script could be provided to create this. Sharing GUI clicks is a challenge. Hopefully Visual Studio in the not to distant future will fully embrace PowerShell.

  • @Trevor

    Have you tried using the DSC Resource Designer to generate the schema.mof?  You can find it here: gallery.technet.microsoft.com/.../xDscResourceDesigne-Module-22eddb29

    Thanks,

    John Slack

    PowerShell Team

  • @PowerShell Team,

    Very interesting and I like how this works, but I'm very interested right now in creating a web app that would allow what we call Tier2 admins to create a DSC. Ideally this would output a valid MOF, since this is really just a text file I could cheat and reverse engineer some of the configurations we already have, but I'd really like to create something a little more flexible.

    Are there any resources at Microsoft to guide me in doing something like this? Thus far I think I've found one reference on MSDN that wasn't helpful at all.

    I'd also really like to not run PowerShell inside my C# if I can help it.

    Thanks,

  • While this is wonderful and I think I may see about porting the one Resource I've created in PowerShell over to C#, ideally I would LOVE the ability to create my DSC from scratch with C#. I have a need internally to provide an easy to use "webapp" that would allow tier 2 admins to create a DSC without the need to know how to program.

    While I could provide several common "templates" ie. Web Server, File Server, App Server and so on, by reverse engineering the MOF that the cmdlets output, I would ideally like to have more flexibility than that.

    I think I've found one reference to some of the internal DSC bits on MSDN but nothing really helpful at all. I doubt I'm the only person who is looking to create a solution like this, is there any help available from Microsoft for us developers trying to do this?

Page 1 of 1 (6 items)