PowerShell Desired State Configuration (DSC) Journey – Day 25

Edit:  This literally took me two days because Virtual Machine Manager is a complete pile.  Anyways….

When I left off last week I had gotten a Configuration to run on my VMM Template, with some work because I ran into a few issues.  I have updated my VMM Template to include all currently available DSC Modules (in case I need them) and added the DNS Settings to the Configuration I will be injecting.  I have also changed my Configuration file so that it doesn’t try to join the computer to the domain.  The need for credentials is complicating things so I have removed that for the time being.  The updated Configuration Script I am using for this next part is below.

$ConfigData = @{
AllNodes = @(
@{
NodeName = "localhost"
PSDscAllowPlainTextPassword = $True
}
)
}

Configuration DSCTemplate
{

Param
(

[pscredential]$Credential
)

Import-DscResource -Module xNetworking
Import-DscResource -Module xComputerManagement

Node $AllNodes.NodeName
{

xIPAddress IPAddress
{
InterfaceAlias = "Ethernet"
IPAddress = "100.198.100.152"
AddressFamily = "IPv4"
DefaultGateway = "100.198.100.1"
SubnetMask = 24
}

xDNSServerAddress DNSAddress
{
InterfaceAlias = "Ethernet"
Address = "100.198.100.2","100.198.100.3"
AddressFamily = "IPv4"
DependsOn = "[xIPAddress]IPAddress"
}

xComputer ComputerConfiguration
{
Name = "DSCTemplate"
DependsOn = "[xIPAddress]IPAddress"
}

}
}

DSCTemplate -ConfigurationData $ConfigData -Credential (Get-Credential)

For my next adventure, I am going to be attempting Option 2.1 from this article about how to Automatically Configure Your Machines Using DSC At Initial Boot.  One other thing I should mention is that article states that you need to put the Unattend.XML in the root directory ( C:\ ).  With VMM there is actually a setting in the Template where you can specify the location of an answer file (that must be in your VMM library).  When I deploy my Template next I will be using this setting in VMM so we will see if the scheduled task actually gets created.

First step is to generate a compiled Configuration.


PS C:\Scripts> C:\Users\jacob.benson\SkyDrive\PowerShell\DSC\DSCTemplate.ps1
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters

Directory: C:\Scripts\DSCTemplate

Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 4/21/2014 2:28 PM 3016 localhost.mof

Next step is to copy localhost.mof to pending.mof

Copy-Item C:\Scripts\DSCTemplate\localhost.mof C:\Scripts\DSCTemplate\Pending.mof

Now, the instructions in the article say to inject the pending.mof file under the DSC Local Configuration Manager. However, farther down it says that “the above process will make localhost.mof the pending Configuration. Doesn’t say anything about pending.mof. So I guess we will see what happens.

I will be using the same Unattend.xml as before except VMM will be the one applying it.  I update my RunDSC.cmd to use the arguments specified in the article (which are also shown below).  I also removed the DSCTemplate.ps1 file from the C:\DSC directory at this time.


schtasks.exe /Create /SC ONSTART /TN "\Microsoft\Windows\Desired State Configuration\DSCRestartBootTask" /RU System /F /TR "PowerShell.exe -NonInt -Command 'Invoke-CimMethod -Namespace root/Microsoft/Windows/DesiredStateConfiguration –ClassName MSFT_DSCLocalConfigurationManager -MethodName PerformRequiredConfigurationChecks -Arg @{Flags = [System.UInt32]3 }'"

I next deploy a VM from this Template, which includes the Unattend.xml file as part of the Template.  I have never tried to do this before so I have no idea if it will work or not.  Because of the multiple tests already performed the name of this VM is DSC-WEB-04.

First, the Unattend.xml must have worked because the Scheduled Task performed by the RunDSC.cmd file exists, and shows it last run when I booted the VM.  And that’s where the good news ends, because none of my Configuration was applied to the Server.  I copy the following text from the Action in the Scheduled Task and run it in a command prompt to see what happens.


<span style="font-family: Calibri; font-size: medium;"><span style="font-family: Calibri; font-size: medium;">Powershell.exe -NonInt -Command 'Invoke-CimMethod -Namespace root/Microsoft/Windows/DesiredStateConfiguration –ClassName MSFT_DSCLocalConfigurationManager -MethodName PerformRequiredConfigurationChecks -Arg @{Flags = [System.UInt32]3 }'"</span></span>

And…it just returns me to the command prompt.  No errors.  No output of any kind.  Awesome.  Now the first thing I am going to do is re-enable the Analytic and Debug DSC logs (I have had to rebuild this template multiple times and I forgot to re-enable them).  I run the same thing in the command prompt and the same thing happens and nothing happens in the logs.

I then realize that I could just put this command in PowerShell and run it and see what happens.


Invoke-CimMethod -Namespace root/Microsoft/Windows/DesiredStateConfiguration –ClassName MSFT_DSCLocalConfigurationManager -MethodName PerformRequiredConfigurationChecks -Arg @{Flags = [System.UInt32]3 }

And holy crap.  It runs perfectly, with no errors.

dsc31

Back to my command prompt, if I remove the -NonInt -Command section from the command prompt, the task runs exactly as you would expect.

dsc32

So, the first thing I am going to do is to restart the Computer to change it’s Computer Name.  Then, I am going to edit the Scheduled Task removing the -NonInt -Command parameters from it.  I will then change the IPAddress back to DHCP and rename it to something completely random, and reboot again, seeing if the Scheduled Task does what it should.

Now, after I renamed it and rebooted, there are now 2 Scheduled Tasks in the Desired State Configuration folder in Task Scheduler.  The first is the Consistency task, and the second is the DSCRestartBootTask, but looking at it’s configuration, it is slightly different than the one my DSCRun.cmd is supposed to create.


PowerShell.exe -NonInt -Window Hidden -Command "Invoke-CimMethod -Namespace root/Microsoft/Windows/DesiredStateConfiguration -ClassName MSFT_DSCLocalConfigurationManager -MethodName PerformRequiredConfigurationChecks -Arg @{Flags = [System.UInt32]2 }"

Things that make you go….hmmmmm.  I have no idea what the difference the 2 or 3 makes at the very end of the command line, but obviously it means something.  Well let’s figure this out.  I delete the scheduled task and run the RunDSC.cmd file to generate the other scheduled task and run it.  Nothing happens.  Next I add the -Window Hidden parameter to the arguments of the scheduled task, leaving everything else to be the same.  I also noticed as part of this that the additional parameters in the action section has a special character before -ClassName.  That looks to be coming from the syntax of the RunDSC.cmd where it places a ‘ before Invoke-Command.  When I successfully ran it in PowerShell and the Command prompt I removed that formatting.  Putting that thought on hold I run the ScheduledTask with the -Window Hidden parameter and again nothing happens.  I delete the scheduled task, and change the RunDSC.cmd to remove the ‘ from the script and run it.

At this point I should mention that whatever process is creating that “New” DSCRestartBoot task, it is overwriting any changes I make to it, even after I delete it.  I only realized this after much testing.

I instead create  a new Scheduled Task using the RunDSC.cmd and call it MyTestTask.  Running it with it’s original configuration does nothing.  I change some things around, still nothing.  Run it in PowerShell, and it completes successfully and nothing gets configured.  I then wonder if something isn’t wrong with the .MOF file.  I go look in the C:\Windows\System32\Configuration directory, and holy crap.

dsc33

The only thing that used to be in here was the pending.mof and localhost.mof.old (which I added in case I would need it for these tests).  Well this certainly explains a lot.

I copy my pending.mof file over to the Template and run the scheduled task again. GLORY GLORY HALLELUJAH.  IT WORKS!  Here is what I used for my final, working, DSCRun.cmd file to create my scheduled task.

dsc34

At this point I literally feel like my brain is melting and I am going to call it a day and process this a little bit.  I feel like I need to write up an entire post about all the things I learned in this single article.

Next up, is undoing the DSC Configuration and saving this as a template with the new RunDSC.cmd and trying to deploy another VM and see if I can get it to actually run on boot.