Windows-Service StartUP

Hi folks,

it is possible to change the Startup Option of a windows service for example from automatic to manuell like in the managment console





Answer this question

Windows-Service StartUP

  • BrentNewbury

    UPDATE:

    There's an error in the QUERY_SERVICE_CONFIG struct I posted earlier. The string members should have the MarshalAs attribute set to UnmanagedType.LPStr instead of UnmanagedType.LPWStr

    Here's the new Struct definition (also updated in original post)

    public struct QUERY_SERVICE_CONFIG {

    [MarshalAs(UnmanagedType.U4)]

    public UInt32 dwServiceType;

    [MarshalAs(UnmanagedType.U4)]

    public UInt32 dwStartType;

    [MarshalAs(UnmanagedType.U4)]

    public UInt32 dwErrorControl;

    [MarshalAs(UnmanagedType.LPStr)]

    public String lpBinaryPathName;

    [MarshalAs(UnmanagedType.LPStr)]

    public String lpLoadOrderGroup;

    [MarshalAs(UnmanagedType.U4)]

    public UInt32 dwTagID;

    [MarshalAs(UnmanagedType.LPStr)]

    public String lpDependencies;

    [MarshalAs(UnmanagedType.LPStr)]

    public String lpServiceStartName;

    [MarshalAs(UnmanagedType.LPStr)]

    public String lpDisplayName;

    }



  • James_Peters

    thx for the answer, that’s what I was looking for


  • Ali Chant

    thanks for your help, thats excatly what I need :)


  • Quoyle

    Please note that when using WMI, the WMI service must be running. It's running by default, so if you are 100% certain that the user won't stop op disable it, it will always work.

    Here's a class you can use to do the same with the Win32 api. Just copy the code below into a class file & use the following code to try it (it will set the startup type of the messenger service to 'Manual'):

    ServiceManager.ChangeStartupType("Messenger", ServiceStartupType.SERVICE_DEMAND_START);

    using System;

    namespace ServiceDemo
    {

    public enum ServiceStartupType : int

    {

    SERVICE_BOOT_START = 0x00000000, //A device driver started by the system loader. This value is valid only for driver services.

    SERVICE_SYSTEM_START = 0x00000001, //A device driver started by the IoInitSystem function. This value is valid only for driver services.

    SERVICE_AUTO_START = 0x00000002, //A service started automatically by the service control manager during system startup.

    SERVICE_DEMAND_START = 0x00000003, //A service started by the service control manager when a process calls the StartService function.

    SERVICE_DISABLED = 0x00000004 //A service that cannot be started. Attempts to start the service result in the error code ERROR_SERVICE_DISABLED.

    }

    [Flags]

    public enum ServiceControlAccessRights : int {

    SC_MANAGER_CONNECT = 0x0001, //Required to connect to the service control manager.

    SC_MANAGER_CREATE_SERVICE = 0x0002, //Required to call the CreateService function to create a service object and add it to the database.

    SC_MANAGER_ENUMERATE_SERVICE= 0x0004, //Required to call the EnumServicesStatusEx function to list the services that are in the database.

    SC_MANAGER_LOCK = 0x0008, //Required to call the LockServiceDatabase function to acquire a lock on the database.

    SC_MANAGER_QUERY_LOCK_STATUS = 0x0010, //Required to call the QueryServiceLockStatus function to retrieve the lock status information for the database

    SC_MANAGER_MODIFY_BOOT_CONFIG= 0x0020, //Required to call the NotifyBootConfigStatus function.

    SC_MANAGER_ALL_ACCESS = 0xF003F //Includes STANDARD_RIGHTS_REQUIRED, in addition to all access rights in this table.

    }

    [Flags]

    public enum ServiceAccessRights : int {

    SERVICE_QUERY_CONFIG = 0x0001, //Required to call the QueryServiceConfig and QueryServiceConfig2 functions to query the service configuration.

    SERVICE_CHANGE_CONFIG = 0x0002, //Required to call the ChangeServiceConfig or ChangeServiceConfig2 function to change the service configuration. Because this grants the caller the right to change the executable file that the system runs, it should be granted only to administrators.

    SERVICE_QUERY_STATUS = 0x0004, //Required to call the QueryServiceStatusEx function to ask the service control manager about the status of the service.

    SERVICE_ENUMERATE_DEPENDENTS = 0x0008, //Required to call the EnumDependentServices function to enumerate all the services dependent on the service.

    SERVICE_START = 0x0010, //Required to call the StartService function to start the service.

    SERVICE_STOP = 0x0020, //Required to call the ControlService function to stop the service.

    SERVICE_PAUSE_CONTINUE = 0x0040, //Required to call the ControlService function to pause or continue the service.

    SERVICE_INTERROGATE = 0x0080, //Required to call the ControlService function to ask the service to report its status immediately.

    SERVICE_USER_DEFINED_CONTROL = 0x0100, //Required to call the ControlService function to specify a user-defined control code.

    SERVICE_ALL_ACCESS = 0xF01FF //Includes STANDARD_RIGHTS_REQUIRED in addition to all access rights in this table.

    }

    [Flags]

    public enum ServiceType : uint {

    SERVICE_KERNEL_DRIVER = 0x00000001, //Driver service.

    SERVICE_FILE_SYSTEM_DRIVER = 0x00000002, //File system driver service.

    SERVICE_WIN32_OWN_PROCESS = 0x00000010, //Service that runs in its own process.

    SERVICE_WIN32_SHARE_PROCESS = 0x00000020, //Service that shares a process with other services.

    SERVICE_INTERACTIVE_PROCESS = 0x00000100, //The service can interact with the desktop.

    SERVICE_NO_CHANGE = 0xffffffff

    }

    public enum ServiceErrorControl : uint

    {

    SERVICE_ERROR_IGNORE = 0x00000000, //The startup program ignores the error and continues the startup operation.

    SERVICE_ERROR_NORMAL = 0x00000001, //The startup program logs the error in the event log but continues the startup operation.

    SERVICE_ERROR_SEVERE = 0x00000002, //SERVICE_ERROR_CRITICAL = 0x00000003, //The startup program logs the error in the event log, if possible. If the last-known-good configuration is being started, the startup operation fails. Otherwise, the system is restarted with the last-known good configuration.

    SERVICE_ERROR_CRITICAL = 0x00000003, //The startup program logs the error in the event log, if possible. If the last-known-good configuration is being started, the startup operation fails. Otherwise, the system is restarted with the last-known good configuration.

    SERVICE_NO_CHANGE = 0xffffffff

    }

    public class ServiceManager

    {

    [System.Runtime.InteropServices.DllImport( "kernel32.dll", EntryPoint = "GetLastError" )]

    private static extern int GetLastError();

    [System.Runtime.InteropServices.DllImport( "advapi32.dll", EntryPoint = "OpenSCManager" )]

    private static extern int OpenSCManager(

    string machineName,

    string databaseName,

    ServiceControlAccessRights desiredAccess);

    [System.Runtime.InteropServices.DllImport( "advapi32.dll", EntryPoint = "CloseServiceHandle" )]

    private static extern int CloseServiceHandle( int hSCObject );

    [System.Runtime.InteropServices.DllImport( "advapi32.dll", EntryPoint = "OpenService" )]

    private static extern int OpenService(

    int hSCManager,

    string serviceName,

    ServiceAccessRights desiredAccess);

    [System.Runtime.InteropServices.DllImport( "advapi32.dll", EntryPoint = "ChangeServiceConfig" )]

    private static extern int ChangeServiceConfig(

    int hService,

    ServiceType dwServiceType,

    ServiceStartupType dwStartType,

    ServiceErrorControl dwErrorControl,

    string lpBinaryPathName,

    string lpLoadOrderGroup,

    IntPtr lpdwTagId,

    string lpDependencies,

    string lpServiceStartName,

    string lpPassword,

    string lpDisplayName );

    public ServiceManager()

    {

    //

    // TODO: Add constructor logic here

    //

    }

    public static void ChangeStartupType(string serviceName, ServiceStartupType startupType)

    {

    //open the service control manager

    int SCManager = OpenSCManager(

    null,

    null,

    ServiceControlAccessRights.SC_MANAGER_CONNECT);

    //verify if the SC is opened

    if(SCManager == 0)

    {

    throw new Exception(

    string.Format(

    "Unable to open Service Control Manager. GetLastError returned {0}",

    GetLastError().ToString()));

    }

    //open the service

    int Service = OpenService(

    SCManager,

    serviceName,

    ServiceAccessRights.SERVICE_CHANGE_CONFIG);

    //verify if the service is opened

    if(Service == 0)

    {

    //get the last dll error before making the next call

    int LastError = GetLastError();

    //make sure the SCManager is closed

    CloseServiceHandle(SCManager);

    throw new Exception(

    string.Format(

    "Unable to open the requested Service. GetLastError returned {0}",

    LastError.ToString()));

    }

    //try to change the startuptype

    int ChangeResult = ChangeServiceConfig(

    Service,

    ServiceType.SERVICE_NO_CHANGE,

    startupType,

    ServiceErrorControl.SERVICE_NO_CHANGE,

    null,

    null,

    IntPtr.Zero,

    null,

    null,

    null,

    null);

    if(ChangeResult == 0)

    {

    //get the last dll error before making the next call

    int LastError = GetLastError();

    CloseServiceHandle(SCManager);

    CloseServiceHandle(Service);

    throw new Exception(

    string.Format(

    "Unable to change the Service Config. GetLastError returned {0}",

    GetLastError().ToString()));

    }

    //clean up

    CloseServiceHandle(SCManager);

    CloseServiceHandle(Service);

    }

    }

    }



  • Mike Russo

    You can do it with wmi, here is vb.net cdoe:

    http://www.xtremevbtalk.com/showthread.php t=259004


  • CougarDave

    thank you, for your quick answer

    Up to now, I dind’t work with Win32Api it would help me if you give me a short code example

    Markus



  • spano

    Sven De Bont wrote:

    Please note that when using WMI, the WMI service must be running. It's running by default, so if you are 100% certain that the user won't stop op disable it, it will always work.

    If you need another service (here WMI) to be running, simply set it as a dependant service:

    ServiceInstaller.ServicesDependedOn Property

    Then Windows will start it, unless user has explicitly disabled it. Well, he/she can also disable your service, so....



  • TerminalReality

    Your class works fine but I need some more help

    I want to get the actual status of the StartUpType. I’m new in windows-programming and also in using the win32 api. I’m going to search some tutorials for this themes.
    Can you add a method to your class where I can read the actual status of the service please

    greets markus


  • JonPL

    Hi Markus,

    Here's a new version of the class. The text in Bold is added. I also changed the way the Win32 errors are handled in the new function. You can just throw a Win32Exception with the ErrorCode. This will show an error with a 'readable' output

    The QueryServiceConfig returns more than just the startup type. The code can be easily modify to get more info from the service.

    Use the new function like this:

    ServiceStartupType startup = ServiceManager.GetStartupType("Messenger");

    The new class;

    using System;
    using System.Runtime.InteropServices;

    namespace ServiceDemo

    {

    public enum ServiceStartupType : int

    {

    SERVICE_BOOT_START = 0x00000000, //A device driver started by the system loader. This value is valid only for driver services.

    SERVICE_SYSTEM_START = 0x00000001, //A device driver started by the IoInitSystem function. This value is valid only for driver services.

    SERVICE_AUTO_START = 0x00000002, //A service started automatically by the service control manager during system startup.

    SERVICE_DEMAND_START = 0x00000003, //A service started by the service control manager when a process calls the StartService function.

    SERVICE_DISABLED = 0x00000004 //A service that cannot be started. Attempts to start the service result in the error code ERROR_SERVICE_DISABLED.

    }

    [Flags]

    public enum ServiceControlAccessRights : int

    {

    SC_MANAGER_CONNECT = 0x0001, //Required to connect to the service control manager.

    SC_MANAGER_CREATE_SERVICE = 0x0002, //Required to call the CreateService function to create a service object and add it to the database.

    SC_MANAGER_ENUMERATE_SERVICE= 0x0004, //Required to call the EnumServicesStatusEx function to list the services that are in the database.

    SC_MANAGER_LOCK = 0x0008, //Required to call the LockServiceDatabase function to acquire a lock on the database.

    SC_MANAGER_QUERY_LOCK_STATUS = 0x0010, //Required to call the QueryServiceLockStatus function to retrieve the lock status information for the database

    SC_MANAGER_MODIFY_BOOT_CONFIG= 0x0020, //Required to call the NotifyBootConfigStatus function.

    SC_MANAGER_ALL_ACCESS = 0xF003F //Includes STANDARD_RIGHTS_REQUIRED, in addition to all access rights in this table.

    }

    [Flags]

    public enum ServiceAccessRights : int

    {

    SERVICE_QUERY_CONFIG = 0x0001, //Required to call the QueryServiceConfig and QueryServiceConfig2 functions to query the service configuration.

    SERVICE_CHANGE_CONFIG = 0x0002, //Required to call the ChangeServiceConfig or ChangeServiceConfig2 function to change the service configuration. Because this grants the caller the right to change the executable file that the system runs, it should be granted only to administrators.

    SERVICE_QUERY_STATUS = 0x0004, //Required to call the QueryServiceStatusEx function to ask the service control manager about the status of the service.

    SERVICE_ENUMERATE_DEPENDENTS = 0x0008, //Required to call the EnumDependentServices function to enumerate all the services dependent on the service.

    SERVICE_START = 0x0010, //Required to call the StartService function to start the service.

    SERVICE_STOP = 0x0020, //Required to call the ControlService function to stop the service.

    SERVICE_PAUSE_CONTINUE = 0x0040, //Required to call the ControlService function to pause or continue the service.

    SERVICE_INTERROGATE = 0x0080, //Required to call the ControlService function to ask the service to report its status immediately.

    SERVICE_USER_DEFINED_CONTROL = 0x0100, //Required to call the ControlService function to specify a user-defined control code.

    SERVICE_ALL_ACCESS = 0xF01FF //Includes STANDARD_RIGHTS_REQUIRED in addition to all access rights in this table.

    }

    [Flags]

    public enum ServiceType : uint

    {

    SERVICE_KERNEL_DRIVER = 0x00000001, //Driver service.

    SERVICE_FILE_SYSTEM_DRIVER = 0x00000002, //File system driver service.

    SERVICE_WIN32_OWN_PROCESS = 0x00000010, //Service that runs in its own process.

    SERVICE_WIN32_SHARE_PROCESS = 0x00000020, //Service that shares a process with other services.

    SERVICE_INTERACTIVE_PROCESS = 0x00000100, //The service can interact with the desktop.

    SERVICE_NO_CHANGE = 0xffffffff

    }

    public enum ServiceErrorControl : uint

    {

    SERVICE_ERROR_IGNORE = 0x00000000, //The startup program ignores the error and continues the startup operation.

    SERVICE_ERROR_NORMAL = 0x00000001, //The startup program logs the error in the event log but continues the startup operation.

    SERVICE_ERROR_SEVERE = 0x00000002, //SERVICE_ERROR_CRITICAL = 0x00000003, //The startup program logs the error in the event log, if possible. If the last-known-good configuration is being started, the startup operation fails. Otherwise, the system is restarted with the last-known good configuration.

    SERVICE_ERROR_CRITICAL = 0x00000003, //The startup program logs the error in the event log, if possible. If the last-known-good configuration is being started, the startup operation fails. Otherwise, the system is restarted with the last-known good configuration.

    SERVICE_NO_CHANGE = 0xffffffff

    }

    [StructLayout(LayoutKind.Sequential)]

    public struct QUERY_SERVICE_CONFIG

    {

    [MarshalAs(UnmanagedType.U4)]

    public UInt32 dwServiceType;

    [MarshalAs(UnmanagedType.U4)]

    public UInt32 dwStartType;

    [MarshalAs(UnmanagedType.U4)]

    public UInt32 dwErrorControl;

    [MarshalAs(UnmanagedType.LPStr)]

    public String lpBinaryPathName;

    [MarshalAs(UnmanagedType.LPStr)]

    public String lpLoadOrderGroup;

    [MarshalAs(UnmanagedType.U4)]

    public UInt32 dwTagID;

    [MarshalAs(UnmanagedType.LPStr)]

    public String lpDependencies;

    [MarshalAs(UnmanagedType.LPStr)]

    public String lpServiceStartName;

    [MarshalAs(UnmanagedType.LPStr)]

    public String lpDisplayName;

    }

     

    public class ServiceManager

    {

    [DllImport( "kernel32.dll", EntryPoint = "GetLastError" )]

    private static extern int GetLastError();

    [DllImport( "advapi32.dll", EntryPoint = "OpenSCManager" )]

    private static extern int OpenSCManager(

    string machineName,

    string databaseName,

    ServiceControlAccessRights desiredAccess);

    [DllImport( "advapi32.dll", EntryPoint = "CloseServiceHandle" )]

    private static extern int CloseServiceHandle( int hSCObject );

    [DllImport( "advapi32.dll", EntryPoint = "OpenService" )]

    private static extern int OpenService(

    int hSCManager,

    string serviceName,

    ServiceAccessRights desiredAccess);

    [DllImport( "advapi32.dll", EntryPoint = "ChangeServiceConfig" )]

    private static extern int ChangeServiceConfig(

    int hService,

    ServiceType dwServiceType,

    ServiceStartupType dwStartType,

    ServiceErrorControl dwErrorControl,

    string lpBinaryPathName,

    string lpLoadOrderGroup,

    IntPtr lpdwTagId,

    string lpDependencies,

    string lpServiceStartName,

    string lpPassword,

    string lpDisplayName );

    [DllImport( "advapi32.dll", EntryPoint = "QueryServiceConfig" )]

    private static extern int QueryServiceConfig(

    int hService,

    IntPtr lpServiceConfig,

    int cbBufSize,

    out int pcbBytesNeeded);

    public ServiceManager()

    {

    //

    // TODO: Add constructor logic here

    //

    }

    public static void ChangeStartupType(string serviceName, ServiceStartupType startupType)

    {

    //open the service control manager

    int SCManager = OpenSCManager(

    null,

    null,

    ServiceControlAccessRights.SC_MANAGER_CONNECT);

    //verify if the SC is opened

    if(SCManager == 0)

    {

    throw new Exception(

    string.Format(

    "Unable to open Service Control Manager. GetLastError returned {0}",

    GetLastError().ToString()));

    }

    //open the service

    int Service = OpenService(

    SCManager,

    serviceName,

    ServiceAccessRights.SERVICE_CHANGE_CONFIG);

    //verify if the service is opened

    if(Service == 0)

    {

    //get the last dll error before making the next call

    int LastError = GetLastError();

    //make sure the SCManager is closed

    CloseServiceHandle(SCManager);

    throw new Exception(

    string.Format(

    "Unable to open the requested Service. GetLastError returned {0}",

    LastError.ToString()));

    }

    //try to change the startuptype

    int ChangeResult = ChangeServiceConfig(

    Service,

    ServiceType.SERVICE_NO_CHANGE,

    startupType,

    ServiceErrorControl.SERVICE_NO_CHANGE,

    null,

    null,

    IntPtr.Zero,

    null,

    null,

    null,

    null);

    if(ChangeResult == 0)

    {

    //get the last dll error before making the next call

    int LastError = GetLastError();

    CloseServiceHandle(SCManager);

    CloseServiceHandle(Service);

    throw new Exception(

    string.Format(

    "Unable to change the Service Config. GetLastError returned {0}",

    GetLastError().ToString()));

    }

    //clean up

    CloseServiceHandle(SCManager);

    CloseServiceHandle(Service);

    }

    public static ServiceStartupType GetStartupType(string serviceName)

    {

    //open the service control manager

    int SCManager = OpenSCManager(

    null,

    null,

    ServiceControlAccessRights.SC_MANAGER_CONNECT);

    //verify if the SC is opened

    if(SCManager == 0)

    {

    throw new System.ComponentModel.Win32Exception(GetLastError());

    }

    //open the service

    int Service = OpenService(

    SCManager,

    serviceName,

    ServiceAccessRights.SERVICE_QUERY_CONFIG);

    //verify if the service is opened

    if(Service == 0)

    {

    //get the last dll error before making the next call

    int LastError = GetLastError();

    //make sure the SCManager is closed

    CloseServiceHandle(SCManager);

    throw new System.ComponentModel.Win32Exception(LastError);

    }

    int dwBytesNeeded = 0;

    // Allocate memory for struct.

    IntPtr ptr = Marshal.AllocHGlobal(4096);

    int QueryResult = QueryServiceConfig(

    Service,

    ptr,

    4096,

    out dwBytesNeeded);

    if(QueryResult == 0)

    {

    //get the last dll error before making the next call

    int LastError = GetLastError();

    CloseServiceHandle(SCManager);

    CloseServiceHandle(Service);

    throw new System.ComponentModel.Win32Exception(LastError);

    }

    //clean up

    CloseServiceHandle(SCManager);

    CloseServiceHandle(Service);

    //cast the buffer to a QUERY_SERVICE_CONFIG struct

    QUERY_SERVICE_CONFIG config =

    (QUERY_SERVICE_CONFIG)Marshal.PtrToStructure(

    ptr, typeof(QUERY_SERVICE_CONFIG));

    return (ServiceStartupType)config.dwStartType;

    }

    }

    }



  • Jonathan Allen

    I don't think there is a standard fuction for that in the .net framework, but you can always use interop to access a service. You need to call the following Win32Api methods (use dllimport):

    1. OpenScManager
    2. OpenService
    3. ChangeServiceConfig
    4. CloseServiceHandle (for the service)
    5. CloseServiceHandle (for the ScManager)

    All these function are in advapi32.dll.

    Let me know if you need more help so I can supply you with a code example.

    Sven



  • Windows-Service StartUP