Use PowerShell to Determine Services with a StartType of Automatic or Manual with Trigger Start

Newer Windows operating systems have numerous services that are set to start automatically or manually with a triggered start. The following image is from a machine that's running Windows 10 Enterprise Edition (version 1511):

trigger-start-service1a.jpg

The problem is when you're trying to determine whether or not all of the services that are set to start automatically are running or not. These trigger start services can't be filtered out using the Get-Service cmdlet or with WMI and they aren't necessarily suppose to be running. The only way to filter them out is to query the registry.

Trigger start services have a TriggerInfo key under their registry key with one or more triggers defined beginning with 0. The DNS Client service is one of these Trigger Start services on Windows 10:

trigger-start-service2a.jpg

The simplest way to check for the existence of a registry key is with the Test-Path cmdlet:

1Test-Path -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\dnscache\TriggerInfo\'

trigger-start-service3a.jpg

I decided to create a reusable tool that returns a list of trigger start services. This function is written so that it's compatible with PowerShell version 2.0 and higher:

 1function Get-MrTriggerStartService {
 2
 3    [CmdletBinding(DefaultParameterSetName='Name')]
 4    param (
 5        [Parameter(ParameterSetName='Name',
 6                   Position=0)]
 7        [ValidateNotNullOrEmpty()]
 8        [string]$Name = '*',
 9
10        [Parameter(ParameterSetName='DisplayName')]
11        [ValidateNotNullOrEmpty()]
12        [string]$DisplayName = '*'
13    )
14
15    $Services = Get-WmiObject -Class Win32_Service -Filter "StartMode != 'Disabled' and Name like '$($Name -replace '\*', '%')' and DisplayName like '$($DisplayName -replace '\*', '%')'"
16
17    foreach ($Service in $Services) {
18
19        if (Test-Path -Path "HKLM:\SYSTEM\CurrentControlSet\Services\$($Service.Name)\TriggerInfo\") {
20
21            New-Object -TypeName PSObject -Property @{
22                Status = $Service.State
23                Name = $Service.Name
24                DisplayName = $Service.DisplayName
25                StartMode = "$($Service.StartMode) (Trigger Start)"
26            }
27
28        }
29
30    }
31
32}

Just running this function without specifying any parameters gives you a list of both the automatic and manual trigger start services:

1Get-MrTriggerStartService

trigger-start-service4a.jpg

The name of a specific service can be specified:

1Get-MrTriggerStartService -Name w32time

trigger-start-service6a.jpg

Wildcards are permitted as well as positional parameters:

1Get-MrTriggerStartService w*

trigger-start-service5a.jpg

The display name of a service can be specified instead of the service name by using the other parameter set:

1Get-MrTriggerStartService -DisplayName 'Dns Client'

trigger-start-service7a.jpg

The DisplayName parameter also accepts wildcards:

1Get-MrTriggerStartService -DisplayName 'Device *'

trigger-start-service8a.jpg

Hopefully Microsoft will consider adding this sort of functionality to either the Get-Service cmdlet or WMI as they have with delayed start services in the RTM version of Windows 10. You can find my blog on that topic here.

µ