Get Windows service start type?
Asked Answered
M

4

6

In the System.ServiceProcess namespace, is there any kind of enumeration or other direct member to determine a Service's Start Type (Auto, Delayed Auto, On Demand, Disabled) of a ServiceController?

The idea is to use an available member of that namespace (or other namespace) of the .NET framework class library to determine that thing, instead of looking into the OS registry or WMI for the service's start type, because I could do that, I'm only asking if the .NET framework exposes an easier way to determine that thing.

Pseudo-Code written in VB.Net but I could manage a C# approach too:

Public Shared Function GetStartType(ByVal svcName As String) As ServiceControllerStatus

    Dim svc As ServiceController = (From service As ServiceController In ServiceController.GetServices()
         Where service.ServiceName.Equals(svcName, StringComparison.OrdinalIgnoreCase)
        ).FirstOrDefault

    If svc Is Nothing Then
        Throw New ArgumentException("Any service found with the specified name.", "svcName")
    Else
        Using svc
            ' Note that StartTypeEnumValue does not exists.
            Return svc.StartTypeEnumValue
        End Using
    End If

End Function
Microphysics answered 14/4, 2015 at 6:5 Comment(5)
Yes.Nabalas
@TheBlueDog While there is indeed this enumeration, you can't use it to determine a service's StartType. It is only used for installing services.Shore
@Shore do you think I could do some trick to cast a Servicecontroller to ServiceInstaller only to retrieve the ServiceStartMode? maybe I said a stupid thing but it should exists a workaround to retrieve the start mode for an existing service under this namespace!. @The Blue Dog thanks for the info!Microphysics
@sloth: Well that's pretty pointless then ...Nabalas
@Microphysics No. These two classes are not related. You have to use the ManagementObjectSearcher or the registry to get the startup type of a service.Shore
M
4

Since I'm not totally sure of the answer to my main question (a member inside .net framework class library capable to get this info) i've developed this registry approach which at least is much more fast that messing with WMI and also can determine if a service is autostart delayed.

Firstlly a custom enum to extend the actual ServiceStartMode enum:

''' <summary>
''' Indicates the start mode of a service.
''' </summary>
Public Enum SvcStartMode As Integer

    ''' <summary>
    ''' Indicates that the service has not a start mode defined.
    ''' Since a service should have a start mode defined, this means an error occured retrieving the start mode.
    ''' </summary>
    Undefinied = 0

    ''' <summary>
    ''' Indicates that the service is to be started (or was started) by the operating system, at system start-up.
    ''' The service is started after other auto-start services are started plus a short delay.
    ''' </summary>
    AutomaticDelayed = 1

    ''' <summary>
    ''' Indicates that the service is to be started (or was started) by the operating system, at system start-up. 
    ''' If an automatically started service depends on a manually started service, 
    ''' the manually started service is also started automatically at system startup.
    ''' </summary>
    Automatic = 2 'ServiceStartMode.Automatic

    ''' <summary>
    ''' Indicates that the service is started only manually, 
    ''' by a user (using the Service Control Manager) or by an application.
    ''' </summary>
    Manual = 3 'ServiceStartMode.Manual

    ''' <summary>
    ''' Indicates that the service is disabled, so that it cannot be started by a user or application.
    ''' </summary>
    Disabled = 4 ' ServiceStartMode.Disabled

End Enum

Secondly, this function:

''' <summary>
''' Gets the start mode of a service.
''' </summary>
''' <param name="svcName">The service name.</param>
''' <returns>The service's start mode.</returns>
''' <exception cref="ArgumentException">
''' Any service found with the specified name.
''' </exception>
''' <exception cref="Exception">
''' Registry value "Start" not found for service.
''' </exception>
''' <exception cref="Exception">
''' Registry value "DelayedAutoStart" not found for service.
''' </exception>
Public Shared Function GetStartMode(ByVal svcName As String) As SvcStartMode

    Dim reg As RegistryKey = Nothing
    Dim startModeValue As Integer = 0
    Dim delayedAutoStartValue As Integer = 0

    Try
        reg = Registry.LocalMachine.
              OpenSubKey("SYSTEM\CurrentControlSet\Services\" & svcName,
              writable:=False)

        If reg Is Nothing Then
            Throw New ArgumentException("Any service found with the specified name.", 
                                        paramName:="svcName")

        Else
            startModeValue = Convert.ToInt32(reg.GetValue("Start",
                             defaultValue:=-1))

            delayedAutoStartValue = Convert.ToInt32(reg.GetValue("DelayedAutoStart", 
                                    defaultValue:=0))

            If startModeValue = -1 Then
                Throw New Exception(String.Format(
                          "Registry value ""Start"" not found for service '{0}'.", 
                          svcName))

                Return SvcStartMode.Undefinied

            Else
                Return DirectCast(
                       [Enum].Parse(GetType(SvcStartMode),
                                   (startModeValue - delayedAutoStartValue).ToString), 
                                    SvcStartMode)

            End If

        End If

    Catch ex As Exception
        Throw

    Finally
        If reg IsNot Nothing Then
            reg.Dispose()
        End If

    End Try

End Function
Microphysics answered 14/4, 2015 at 9:16 Comment(0)
W
6

If possible, set your project target .NET framework to 4.6.1 or higher. The class ServiceController now has a property StartType

https://msdn.microsoft.com/en-us/library/system.serviceprocess.servicecontroller(v=vs.110).aspx

Wisteria answered 19/4, 2016 at 9:22 Comment(2)
Thanks but StartType property just returns a ServiceStartMode value, that is a "uncomplete" enum of possible start modes, which I'd extended in my accepted answer..Microphysics
@Microphysics In my case all I needed were the values in ServiceStartMode msdn.microsoft.com/en-us/library/…Wisteria
P
5

You could use WMI and ManagementObject to achieve this, based on C# – Get Startup Type of a Service (Windows).

Something like this (based on code in linked article). The original example is in C#, so I've attempted a quick translation to VB.NET on the fly, but the syntax may be a bit wrong. I also modified the method return type to String since as I wasn't sure what you wanted to do with the value once you got it.

Don't forget to add Imports System.Management.

Public Shared Function GetStartType(ByVal svcName As String) As String

    Dim startMode As String = String.Empty
    Dim filter As String = String.Format("SELECT StartMode FROM Win32_Service WHERE Name = '{0}'", svcName)
    Dim svc As ManagementObjectSearcher = New ManagementObjectSearcher(filter)

    If svc Is Nothing Then
        Throw New ArgumentException("Any service found with the specified name.", paramName:="svcName")
    Else
        Try
            Dim services As ManagementObjectCollection = svc.Get()

            For Each service As ManagementObject In services
                startMode = service.GetPropertyValue("StartMode").ToString()
            Next
        Catch ex As Exception
            ' Do something if needed
        End Try
    End If

    Return StartMode
End Function
Parthinia answered 14/4, 2015 at 7:0 Comment(4)
Thankyou but your solution does not answer to my question. I'm not looking for other approachs (I know them) accesing and messing with WMI queries is one of the things that I would like to avoid in case of .Net framework class library exposes a direct way to retrieve that info. thanks anywaysMicrophysics
Ah, ok. Sorry it didn't match what you were looking for. Good luck on your search :)Parthinia
Someone answered to my main question in the comments and then your approach seems the only one (I mean together with windows registry search). thanks again.Microphysics
Well, since this solution does not provide a way to determine the delayed AutoStart I unmark it, the DelayedAutoStart property of Win32_Service seems unselectable from query (unaccesible) I don't know why. I know how to do it from registry but it is ugly and intrusive (like WMI queries)Microphysics
M
4

Since I'm not totally sure of the answer to my main question (a member inside .net framework class library capable to get this info) i've developed this registry approach which at least is much more fast that messing with WMI and also can determine if a service is autostart delayed.

Firstlly a custom enum to extend the actual ServiceStartMode enum:

''' <summary>
''' Indicates the start mode of a service.
''' </summary>
Public Enum SvcStartMode As Integer

    ''' <summary>
    ''' Indicates that the service has not a start mode defined.
    ''' Since a service should have a start mode defined, this means an error occured retrieving the start mode.
    ''' </summary>
    Undefinied = 0

    ''' <summary>
    ''' Indicates that the service is to be started (or was started) by the operating system, at system start-up.
    ''' The service is started after other auto-start services are started plus a short delay.
    ''' </summary>
    AutomaticDelayed = 1

    ''' <summary>
    ''' Indicates that the service is to be started (or was started) by the operating system, at system start-up. 
    ''' If an automatically started service depends on a manually started service, 
    ''' the manually started service is also started automatically at system startup.
    ''' </summary>
    Automatic = 2 'ServiceStartMode.Automatic

    ''' <summary>
    ''' Indicates that the service is started only manually, 
    ''' by a user (using the Service Control Manager) or by an application.
    ''' </summary>
    Manual = 3 'ServiceStartMode.Manual

    ''' <summary>
    ''' Indicates that the service is disabled, so that it cannot be started by a user or application.
    ''' </summary>
    Disabled = 4 ' ServiceStartMode.Disabled

End Enum

Secondly, this function:

''' <summary>
''' Gets the start mode of a service.
''' </summary>
''' <param name="svcName">The service name.</param>
''' <returns>The service's start mode.</returns>
''' <exception cref="ArgumentException">
''' Any service found with the specified name.
''' </exception>
''' <exception cref="Exception">
''' Registry value "Start" not found for service.
''' </exception>
''' <exception cref="Exception">
''' Registry value "DelayedAutoStart" not found for service.
''' </exception>
Public Shared Function GetStartMode(ByVal svcName As String) As SvcStartMode

    Dim reg As RegistryKey = Nothing
    Dim startModeValue As Integer = 0
    Dim delayedAutoStartValue As Integer = 0

    Try
        reg = Registry.LocalMachine.
              OpenSubKey("SYSTEM\CurrentControlSet\Services\" & svcName,
              writable:=False)

        If reg Is Nothing Then
            Throw New ArgumentException("Any service found with the specified name.", 
                                        paramName:="svcName")

        Else
            startModeValue = Convert.ToInt32(reg.GetValue("Start",
                             defaultValue:=-1))

            delayedAutoStartValue = Convert.ToInt32(reg.GetValue("DelayedAutoStart", 
                                    defaultValue:=0))

            If startModeValue = -1 Then
                Throw New Exception(String.Format(
                          "Registry value ""Start"" not found for service '{0}'.", 
                          svcName))

                Return SvcStartMode.Undefinied

            Else
                Return DirectCast(
                       [Enum].Parse(GetType(SvcStartMode),
                                   (startModeValue - delayedAutoStartValue).ToString), 
                                    SvcStartMode)

            End If

        End If

    Catch ex As Exception
        Throw

    Finally
        If reg IsNot Nothing Then
            reg.Dispose()
        End If

    End Try

End Function
Microphysics answered 14/4, 2015 at 9:16 Comment(0)
D
0

Use
Dim SingleSvc As Object

Dim listaSvcs() As ServiceProcess.ServiceController
Dim SingleSvc As Object
iniservice:
listaSvcs = ServiceProcess.ServiceController.GetServices
Try
    For Each SingleSvc In listaSvcs
        If SingleSvc.ServiceName.IndexOf("postgresql") >= 0 And SingleSvc.StartType.ToString <> "Disabled" Then
            If SingleSvc.Status <> ServiceProcess.ServiceControllerStatus.Running Then
                'MessageBox.Show(SingleSvc.StartType.ToString)
                SingleSvc.Start()
                GoTo iniservice
                End If
            End If
        Next
Catch ex As Exception
    MessageBox.Show(ex.Message)
End Try

Run in Framework 4 Tanks

Djerba answered 26/9, 2016 at 19:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.