Desired State Configuration code: How to troubleshoot the extension

Hello folks! If you have made it this far, know I think you're amazing and one of a kind! If you are just tuning in now and would like to see the full blog series daisy chained together, take note of the URLs below, so you can take in the full spectrum of what it looks like to fully automate a replica build within Azure:

Introduction to Building a Replica Domain Controller ARM Template
Pre-Requisites to Build a Replica Domain Controller ARM Template
Design Considerations of Building a Replica
Digging into the Replica Domain Controller ARM Template Code
Desired State Configuration Extension and the Replica Domain Controller ARM Template
GitHub Repo – Sample Code

This last post will surround the actual code + how to troubleshoot the extension. Since troubleshooting the extension is quick, let us step through that task first.

When you head over to the extensions setting underneath your VM blade, you always want to see something like this:


It might seem obvious, but “Provisioning succeeded” means the script ran and the extension has been applied to the object. Since some of you may be newer to DSC, the first handful of times this operation may not work properly. What happens if you see something like this instead?


Unfortunately, that means you must dig on the itself. Since there is no pull server, all troubleshooting logs show up on the deployed VM. So long as the VM is up, it provisioned successfully, and is accessible, the log files will generate in the following location:


What you will find here are the extension output logs. When you log into the VM in Azure, you should see a folder like this:


Drilling into that folder, you should see a series of text files with number GUIDs generated at the end. Ensure you see “CommandExecution” and “DscExtensionHandler” files:


Open the DscExtensionHandler file and filter on error. You should hopefully see some helpful clues show up, seeing as this extension throws verbose logging into these files. In my example below, I discovered that I had either mistyped the password or did not formulate the password correctly in the way DSC requires:


There is a specific workflow the extension follows for any Azure VM. The extension package is downloaded and deployed to this location on the Azure VM itself:



The extension status file contains the sub status and the status success/error codes along with the detailed error and description for each extension run:

C:PackagesPlugins{Extension_Name}{Extension_Version}Status{0}.Status  -> {0} being the sequence number


Now, in my screen shots, you will not see any “1.status” folders because one of the troubleshooting steps within the DSC Extension deployment is to remove any failed deployments. Remember this screen shot?


If the DSC extension deployment fails, you need to uninstall the extension using something like PowerShell, the Azure CLI, or in the portal by examining the screen shot below:


Now that the troubleshooting and caveats for re-running a DSC extension have been covered, let us move into the DSC code itself.

Many sysadmins have come to me over the years and asked how to manage systems at scale. With the cloud, many sysadmins are looking at ways to build and manage infrastructure without manual intervention. is one of the tools I talk about and I personally feel it can be one of the unsung heroes of any Windows server system environment. In a regular configuration management flow, DSC is comprised of both a data file and a configuration file that are compiled into a text file following the Managed Object Format (MOF). The MOF file is then parsed and executed on the target server using DSC features that know how to configure the system. Now, the Local Configuration Manager (LCM) is the engine of DSC. The LCM runs on every target node and is responsible for parsing and enacting configurations that are sent to the node. Fun fact, every Azure VM deployed within your subscriptions is a LCM, so DSC runs naturally, whether evoked from a pull server or through a DSC extension.

The Azure DSC extension uses the Azure VM Agent framework to configure and report on DSC configurations running on Azure VMs. When the DSC extension is processed the first time, it will install the right version of Windows Management Framework (WMF), unless the server OS is Windows Server 2016 or newer (Windows Server 2016 and newer OSes have the latest version of PowerShell installed). If WMF winds up installed because you are using an older Windows OS, it will require a reboot. When you use the DSC extension, the DSC extension is what creates the MOF file, so all you need to supply is the PowerShell script.

Seems pretty darn awesome, right? Right.

So, what does the actual DSC script look like in my GitHub repo? Let's go through it section by section.

First, the configuration itself is given a title. This is called upon within the ARM Template.



Let us expand the parameters next. These are declared parameters within your parameters JSON file from the ARM Template deployment.



Once the parameters are effectively declared, the DSC script imports some DSC modules:


Within the template, the DSC ZIP file I reference (found here) contains the right manifests + DSC modules. If you download and open the ZIP file, you will see this in the folder:


xActiveDirectory, xDSCDomainjoin, xNetworking, xPendingReboot, and xStorage are all experimental DSC modules and can be downloaded here or you can search for these modules using your search engine of choice and download accordingly. The larger zip from the script center packages up all Microsoft documentation for each experimental module. Personally, I have found that helpful when trying to figure out how to make use of the modules to build a .


Packaging up the DSC modules and then importing them in the script you pass to the DSC extension is how the DSC extension can align the configuration on the target nodes. The DSC extension takes the ZIP file and extracts the modules to the following folder:


Additionally, the PowerShell script gets plugged into the following folder:


And if you double click into “CreateADReplicaDC,” you will see the MOF files:


By this point, it should be hopefully coming full circle in terms of how DSC and the DSC extension work to configure VMs during deployment using the Azure Resource Manager (ARM) model.

After the modules are imported, we need to lean on the PSCredential Class System.Management.Automation. This class offers a centralized way to manage usernames, passwords, and credentials. I incorrectly passed credentials in as strings (I know, I know – I should have been thinking about credentials being secure objects and placed my dev hat on, but I digress). I leaned on my pal Matt Canty once more and he helped me formulate the right credential object by using these two lines of code in the PowerShell script:


After all parameters and credential objects are declared at the beginning of the PowerShell script, the PowerShell script follows a specific flow. I will outline those steps next:


If we read this, the script declaratively states that on the localhost, the Local Configuration Manager (LCM) first gets called. The script then indicates that the configuration should continue after any reboots, the configuration mode should apply the configuration, and the server will reboot if needed. The script then installs RSAT, which are good tools to have on any Windows server. From there, the script calls upon the xDisk experimental module to add the non-cached drive for the SYSVOL folder (you may recall this was a design consideration in my 3rd blog post). The steps taken to initialize the extra drive and format happen sequentially after previous tasks run on the target node.

After the disk has been initialized and is reporting as ready to the LCM, the script moves on into joining the VM to the domain, adding the Active Directory Domain Services role, and building out the replica :


As you can see, DSC code is not too hard to read through and understand each step taken before deployment. Each step depends on the previous step, so you declare some parameters you want met related to the Log Path, SYSVOL Path, and Database Path, and let the LCM do the rest after the script is parsed and applied to the node.

In closing, if you take on this code and run into problems, please do not hesitate to reach out. The steps involved to break this down so everyone understands took me many posts to unravel. The beauty here is you can reach out if you get stuck, but getting deeper with ARM Templates and understanding DSC scripting is going to take you from regular sysadmin status to HERO or HEROINE status in your current role. :smiling_face_with_smiling_eyes:


This article was originally published by Microsoft's Azure Security Blog. You can find the original article here.