In this posting I’ll talk about my experiences and final solution to what is usually a simple thing with a Windows Server box: installing Windows features.


If your Azure solution requires a Windows Feature, you might be tempted to set up a VHD and then upload to a VM Role.  While this will work, for various reasons it’s not the optimal solution if a worker or web role can do the job.  And, as is frequently the case these days, startup tasks can be used to handle this requirement quite nicely.

Initially, I experimented with techniques such as OCSetup and ServerManagerCmd.  I used Remote Desktop to try out scripting these options before settling on PowerShell.  OCSetup doesn’t give great feedback and has no option for querying status of existing features, and ServerManagerCmd is deprecated.  I needed to learn a little bit about PowerShell, but as it’s the technology of the future I decided it was worth the effort. 

I used a couple of excellent resources to learn what I needed to know: 

  1. Powershell.com has a free eBook entitled Mastering Powershell.  Here’s the link: http://powershell.com/cs/blogs/ebook/default.aspx.
  2. Microsoft’s own Scripting Guy, Ed Wilson, published an excellent series of videos for the beginner: http://technet.microsoft.com/en-us/scriptcenter/dd742419.aspx.

The particular Windows Features that I needed to add are “Ink Support” and “Ink Handwriting Recognition”, where “Ink Support” requires a reboot and is a prerequisite for “Ink Handwriting Recognition”.  Fortunately, the startup task that you can specify in your CSDEF file gets run every time a role instance boots (not only when the instance is created.)

Two scripts are needed in a PowerShell scenario,  one CMD file and one PS1 file:

  1. Startup.CMD

    powershell -command "Set-ExecutionPolicy Unrestricted" 2>> err.out 
    powershell .\startup.ps1 2>> err.out
  2. Startup.PS1

    Import-Module Servermanager
    $ink = Get-WindowsFeature "IH-Ink-Support"
    $hwr = Get-WindowsFeature "IH-Handwriting"
    if (!$ink.Installed) {
      Add-WindowsFeature -name "IH-Ink-Support" -Restart
    }
    if (!$hwr.Installed) {
      Add-WindowsFeature -name "IH-Handwriting"
    }
    Here, Get-WindowsFeature returns an object with various properties.  The one we care about is “.Installed”, which returns a boolean value indicating the installation status of the feature.  For the non-C crowd, the exclamation point, in PowerShell speak, indicates “not”.

Just a few notes:

And finally, as mentioned before (but always important to remember), don’t create a command file in Visual Studio.  Doing so inserts a couple of byte order chars at the front that prevent the command interpreter from being able to read it.  Start your command file with notepad, add it to your project, then you can edit in VS.

Cheers!

1/16/2014 - Thanks Stas Kuvshinov for pointing out that where checking .Installed you can get into a limbo state if the feature has been installed but the reboot not executed.  If you check .InstallState you'll get a more deterministic result - it could be "Installed" or "InstallPending".