Tag: <span>Windows service</span>

After reading this post at StackOverflow, I realized that I was probably wrong to think it was OK to directly access the registry keys that Windows uses to keep track of installed services. Though the names and locations of the keys probably won’t change any time soon, it’s always better to use a higher level of abstraction when dealing with Windows internals. In this case, WMI fits the bill very nicely.

I had not written any WMI-related code up til now, simply because I’ve always been able to find other methods to get the information I need. But after reading that post and knowing of a particular program of mine that does access the registry directly to determine the start mode for a service, I decided to re-write that code to use WMI via the System.Management namespace in the .NET framework.

I came across a couple of different C# samples on the web and was able to modify them to fit my needs. Below is a new class I created for service management that will hopefully grow over time.

Imports System.Management

'''
''' Used to manage Windows services.
''' 
Public Class ServiceManagement
    'Enumeration of service startup modes
    Public Enum ServiceStartMode
        Boot = 0
        System = 1
        Automatic = 2
        Manual = 3
        Disabled = 4
    End Enum

    'Return values for service-related WMI routines
    Public Enum ReturnValue
        Success = 0
        NotSupported = 1
        AccessDenied = 2
        DependentServicesRunning = 3
        InvalidServiceControl = 4
        ServiceCannotAcceptControl = 5
        ServiceNotActive = 6
        ServiceRequestTimeout = 7
        UnknownFailure = 8
        PathNotFound = 9
        ServiceAlreadyRunning = 10
        ServiceDatabaseLocked = 11
        ServiceDependencyDeleted = 12
        ServiceDependencyFailure = 13
        ServiceDisabled = 14
        ServiceLogonFailure = 15
        ServiceMarkedForDeletion = 16
        ServiceNoThread = 17
        StatusCircularDependency = 18
        StatusDuplicateName = 19
        StatusInvalidName = 20
        StatusInvalidParameter = 21
        StatusInvalidServiceAccount = 22
        StatusServiceExists = 23
        ServiceAlreadyPaused = 24
        ServiceNotFound = 25
    End Enum

    '''
    ''' Gets the current start mode for the given service.
    ''' 
    '''Name of an installed service.
    ''' Numerical code indicating the service's start mode.
    Public Shared Function GetStartMode(ByVal serviceName As String) As ServiceStartMode
        Dim service As ManagementObject = Nothing
        Dim servicePath As String
        Dim startMode As String

        GetStartMode = ServiceStartMode.Disabled

        Try
            servicePath = String.Format("Win32_Service.Name=""{0}""", serviceName)
            service = New ManagementObject(servicePath)
            startMode = service.GetPropertyValue("StartMode").ToString

            'We can't return the exact property value because StartMode will
            'show as 'Auto' rather than 'Automatic'. Since the ChangeStartMode 
            'WMI method will need to have 'Automatic' passed when setting the 
            'service to auto-start, our ServiceStartMode enum uses 'Automatic'
            Select Case startMode
                Case "Boot"
                    Return ServiceStartMode.Boot
                Case "System"
                    Return ServiceStartMode.System
                Case "Auto"
                    Return ServiceStartMode.Automatic
                Case "Manual"
                    Return ServiceStartMode.Manual
                Case "Disabled"
                    Return ServiceStartMode.Disabled
            End Select
        Catch
            Throw
        Finally
            If service IsNot Nothing Then
                service.Dispose()
            End If
        End Try
    End Function

    '''
    ''' Sets the start mode for the given service.
    ''' 
    '''Name of an installed service.
    '''Numerical code representing the new start mode.
    ''' Error code indicating the result of the change operation.
    Public Shared Function SetStartMode(ByVal serviceName As String, ByVal startMode As ServiceStartMode) 
                                        As ReturnValue
        Dim service As ManagementObject = Nothing
        Dim inParams As ManagementBaseObject = Nothing
        Dim outParams As ManagementBaseObject = Nothing
        Dim servicePath As String

        SetStartMode = ReturnValue.UnknownFailure

        Try
            servicePath = String.Format("Win32_Service.Name=""{0}""", serviceName)
            service = New ManagementObject(servicePath)
            inParams = service.GetMethodParameters("ChangeStartMode")
            inParams("StartMode") = startMode.ToString()
            outParams = service.InvokeMethod("ChangeStartMode", inParams, Nothing)

            Return DirectCast([Enum].Parse(GetType(ReturnValue), 
                                           outParams("ReturnValue").ToString()), ReturnValue)
        Catch
            Throw
        Finally
            If inParams IsNot Nothing Then
                inParams.Dispose()
            End If

            If outParams IsNot Nothing Then
                outParams.Dispose()
            End If

            If service IsNot Nothing Then
                service.Dispose()
            End If
        End Try
    End Function
End Class