X

Taking control of system services on stubborn virtual machines

One of the problems that I have long dealt with in my Hyper-V environment is that of virtual machines that refuse to start certain system services at the time the VM is booted. I’m not talking about errors associated with the Service Control Manager on a VM that is plagued with problems. I am talking about an otherwise healthy VM whose services fail to start automatically.

Crash course in system services

The Windows operating system utilizes a number of different system services, many of which are designed to start up automatically at the time that the operating system is booted. Many third-party applications also make use of services, which typically also start when the operating system is booted.

Services are displayed through the Service Control Manager. You can access the Service Control Manager by entering Services.msc at the server’s Run prompt. You can see what this looks like in the figure below.


Any service whose Startup type is set to Automatic should start automatically when the VM is booted. I haven’t really had any problems with operating system services, but I have found that when a VM is run on older (slow) hardware, application-specific services will very often fail to start automatically.

Now in all fairness, it isn’t that hard to manually start these services. You can simply open the Service Control Manager, right click on the service, and choose the Start command from the shortcut menu. That almost always forces the service to start. Even so, it’s a pain to have to go and check which services are and are not running each time you boot a VM.

Starting stubborn services

One way you can get around this problem is to build a PowerShell script that is designed to start services that typically will not start on their own. I will be the first to admit that this is a Band-Aid solution, but it works. If services do not start automatically like they are supposed to, then using an automated script to get the services running is a better solution, in my opinion, than having to manually check each service.

When it comes to using PowerShell to start services that should have started automatically, but did not, you can get as fancy as you want. You could go so far as to build a script containing dedicated functions for each service, and make it so that the script does not progress to the next function until the current function’s service has started. This approach works well if you have a complex set of dependencies and you need to be 100 percent sure that every service starts every time. Most of the time, though, a much simpler script will work just as well.

If the goal is to build a PowerShell script to start system services that are known to have problems starting on their own, and to keep that script as simple as possible, there are two basic commands that are going to be required.

The first of these commands is a time delay. You don’t want your script to initiate the command to start the first service, and then blast through the remaining commands before the service even has a chance to start. The command that I like to use for this is Start-Sleep. The Start-Sleep command initiates a time delay of a period that you specify. For example, if you wanted a 10-second delay, then the command would be:

Start-Sleep -S 10

The second type of command that is going to be required is the command that actually starts the service. The name of the command that you will need to use is Start-Service. Here is a really simple example of how to use this command:

Start-Service -Name "eventlog"

In this case, I am using the Start-Service cmdlet to start the Eventlog service. This, however, brings up an important point. When you use PowerShell to start a service, you are going to need to know the name of the service that you want to start. The easiest way to get the service name is to open a PowerShell window and enter the Get-Service cmdlet.

When you enter the Get-Service cmdlet by itself, the cmdlet returns three pieces of information — the service name, the service state, and the service description. The name that is displayed by the Get-Service cmdlet is the name that you would use with the Start-Service cmdlet.

The list of system services that are returned by the Get-Service cmdlet can be pretty long, but there are some ways of narrowing down the list. If, for example, you want to see a list of the services that are stopped, you can enter;

Get-Service | Where {$_.Status -eq ‘Stopped’}

The problem with the resulting list is that not every service that is displayed is configured to start automatically. If you want to see the services with a startup type of Automatic that are not running, you can use this command:

Get-Service | Where {$_.StartType-eq 'Automatic' -and $_.Status -eq 'Stopped'} | Select-Object Name, StartType, Status

You can see what this looks like in the figure below:

By using the Start-Sleep and the Start-Service cmdlets, it is possible to build a script that can start services that commonly fail to start on their own. Of course the one thing that is still missing is a mechanism for running the script. You can log onto the system, open a PowerShell window, and run the script manually, but doing so isn’t all that much more efficient than manually starting the failed services.

There are a number of different ways of forcing a PowerShell script to run automatically. For example, you might configure the Windows Task Scheduler to periodically run your script, or you could configure the script to execute as a startup item.

Photo credit: Shutterstock