Installing Windows Features in a Windows Azure Role Instance
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:
- Powershell.com has a free eBook entitled Mastering Powershell. Here’s the link: https://powershell.com/cs/blogs/ebook/default.aspx.
- Microsoft’s own Scripting Guy, Ed Wilson, published an excellent series of videos for the beginner: https://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:
Startup.CMD
powershell -command "Set-ExecutionPolicy Unrestricted" 2>> err.out
powershell .\startup.ps1 2>> err.outStartup.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:
Set-ExecutionPolicy
Here’s a great blog post that deals with this:
https://blogs.msdn.com/b/jimoneil/archive/2011/02/07/azure-startup-tasks-and-powershell-lessons-learned.aspxSet up remote desktop
Another Jim O’Neil posting:
https://blogs.msdn.com/b/jimoneil/archive/2010/12/29/azure-home-part-13-remote-desktop-configuration.aspxThis page has a list of installable Windows Features on WS2008R2:
Another good way to see a list of features but also each one’s current status on your instance is to open a PowerShell box, Import-Module Servermanager and then Get-WindowsFeature. Pipe the output to “more” (| more) if you want to see a page at a time.
And here’s Steve Marx’ very useful blog posting on Startup Tasks:
https://blog.smarx.com/posts/introduction-to-windows-azure-startup-tasks
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".