Installing a Windows Service in a Windows Azure Worker Role
It might seem like a giant leap backward to bother with installing a Windows service in a worker role. After all, the Windows Azure and Visual Studio teams went to a lot of trouble to create worker roles as a core part of the platform. Worker role code is monitored by the fabric controller, so we know when it is no longer healthy and we can take steps to remediate. Windows services have additional plumbing associated with them so they can be started up, paused, shut down and managed by the Services.msc MMC plug-in. So why bother?
At this point I know of only one good reason: on-ramping to the cloud. You might have a Windows service that you rely on and want to do a proof of concept on Windows Azure but not want to take the time to refactor to worker role code. I’m sure that there are other good reasons and I’d love to hear them!
The process to making this happen is pretty simple. It involves the use of admin mode (available with the 1.3 SDK) and a short cmd script. Here’s a brief overview of the process:
- Create a Windows service app for your test. I used the template in VS2010, made it installable and gave it a name. Nothing else.
- Create a new cloud solution and add a worker role.
- Add the Windows service app (my example is testapp.exe) to the worker role files. Mark its properties “Build Action = None”, “Copy to Output Directory = Copy Always”.
- Add InstallUtil.exe and InstallUtil.exe.config in the same way. My service was compiled using .NET 4.0, so I found the .NET 4.0 version of InstallUtil on my system to use.
- Create a command script using Notepad. This command script will install your service using admin mode during the spin up of your worker role instances. Include this file in your worker role files the same way as the others. (NOTE: Don’t use VS to create the command script. According to Steve Marx’ and Wade Wegner’s recent Cloud Cover episode, this causes the file to not execute.)
- Add a few lines to your ServiceDefinition file that will cause your script to run.
- Configure Remote Desktop connections on your roles. You’ll use RD to debug your script. Here’s another Cloud Cover episode that should help you get this going.
When you’ve got it set up correctly, your service will install automatically each time an instance of your role starts up.
Here are a few details:
InstallService.cmd creates a new user account and makes it an administrator. This user account is needed for the InstallUtil invocation. The last line (exit /B 0) is to ensure that the script exits with a good return code. This allows you to RDP into the instance while testing. If you didn’t do this, the worker role will cycle, attempting to get a clean start. Once your code is clean, you can remove the exit.
One more thing: what did I put into my worker role code? Nothing! I just used the code as it comes out of the template. It loops, waits 10 seconds, loops, etc.