¿Cómo instalar un servicio de Windows mediante programación en C #?

78

Tengo 3 proyectos en mi solución VS. Uno de ellos es una aplicación web, el segundo es un servicio de Windows y el último es un proyecto de instalación para mi aplicación web.

Lo que quiero es que al final de la instalación de la aplicación web en mi proyecto de instalación, dentro de mi acción personalizada, intente instalar mi servicio de Windows dado que ya tengo la ubicación del ensamblaje para entonces.

Konstantinos
fuente

Respuestas:

90

Encontré varios errores en el código que reutilizó y los solucioné y también lo limpié un poco. Nuevamente, el código original se toma de aquí .

public static class ServiceInstaller
{
    private const int STANDARD_RIGHTS_REQUIRED = 0xF0000;
    private const int SERVICE_WIN32_OWN_PROCESS = 0x00000010;

    [StructLayout(LayoutKind.Sequential)]
    private class SERVICE_STATUS
    {
        public int dwServiceType = 0;
        public ServiceState dwCurrentState = 0;
        public int dwControlsAccepted = 0;
        public int dwWin32ExitCode = 0;
        public int dwServiceSpecificExitCode = 0;
        public int dwCheckPoint = 0;
        public int dwWaitHint = 0;
    }

    #region OpenSCManager
    [DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
    static extern IntPtr OpenSCManager(string machineName, string databaseName, ScmAccessRights dwDesiredAccess);
    #endregion

    #region OpenService
    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, ServiceAccessRights dwDesiredAccess);
    #endregion

    #region CreateService
    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern IntPtr CreateService(IntPtr hSCManager, string lpServiceName, string lpDisplayName, ServiceAccessRights dwDesiredAccess, int dwServiceType, ServiceBootFlag dwStartType, ServiceError dwErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, IntPtr lpdwTagId, string lpDependencies, string lp, string lpPassword);
    #endregion

    #region CloseServiceHandle
    [DllImport("advapi32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool CloseServiceHandle(IntPtr hSCObject);
    #endregion

    #region QueryServiceStatus
    [DllImport("advapi32.dll")]
    private static extern int QueryServiceStatus(IntPtr hService, SERVICE_STATUS lpServiceStatus);
    #endregion

    #region DeleteService
    [DllImport("advapi32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool DeleteService(IntPtr hService);
    #endregion

    #region ControlService
    [DllImport("advapi32.dll")]
    private static extern int ControlService(IntPtr hService, ServiceControl dwControl, SERVICE_STATUS lpServiceStatus);
    #endregion

    #region StartService
    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern int StartService(IntPtr hService, int dwNumServiceArgs, int lpServiceArgVectors);
    #endregion

    public static void Uninstall(string serviceName)
    {
        IntPtr scm = OpenSCManager(ScmAccessRights.AllAccess);

        try
        {
            IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.AllAccess);
            if (service == IntPtr.Zero)
                throw new ApplicationException("Service not installed.");

            try
            {
                StopService(service);
                if (!DeleteService(service))
                    throw new ApplicationException("Could not delete service " + Marshal.GetLastWin32Error());
            }
            finally
            {
                CloseServiceHandle(service);
            }
        }
        finally
        {
            CloseServiceHandle(scm);
        }
    }

    public static bool ServiceIsInstalled(string serviceName)
    {
        IntPtr scm = OpenSCManager(ScmAccessRights.Connect);

        try
        {
            IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.QueryStatus);

            if (service == IntPtr.Zero)
                return false;

            CloseServiceHandle(service);
            return true;
        }
        finally
        {
            CloseServiceHandle(scm);
        }
    }

    public static void InstallAndStart(string serviceName, string displayName, string fileName)
    {
        IntPtr scm = OpenSCManager(ScmAccessRights.AllAccess);

        try
        {
            IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.AllAccess);

            if (service == IntPtr.Zero)
                service = CreateService(scm, serviceName, displayName, ServiceAccessRights.AllAccess, SERVICE_WIN32_OWN_PROCESS, ServiceBootFlag.AutoStart, ServiceError.Normal, fileName, null, IntPtr.Zero, null, null, null);

            if (service == IntPtr.Zero)
                throw new ApplicationException("Failed to install service.");

            try
            {
                StartService(service);
            }
            finally
            {
                CloseServiceHandle(service);
            }
        }
        finally
        {
            CloseServiceHandle(scm);
        }
    }

    public static void StartService(string serviceName)
    {
        IntPtr scm = OpenSCManager(ScmAccessRights.Connect);

        try
        {
            IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.QueryStatus | ServiceAccessRights.Start);
            if (service == IntPtr.Zero)
                throw new ApplicationException("Could not open service.");

            try
            {
                StartService(service);
            }
            finally
            {
                CloseServiceHandle(service);
            }
        }
        finally
        {
            CloseServiceHandle(scm);
        }
    }

    public static void StopService(string serviceName)
    {
        IntPtr scm = OpenSCManager(ScmAccessRights.Connect);

        try
        {
            IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.QueryStatus | ServiceAccessRights.Stop);
            if (service == IntPtr.Zero)
                throw new ApplicationException("Could not open service.");

            try
            {
                StopService(service);
            }
            finally
            {
                CloseServiceHandle(service);
            }
        }
        finally
        {
            CloseServiceHandle(scm);
        }
    }

    private static void StartService(IntPtr service)
    {
        SERVICE_STATUS status = new SERVICE_STATUS();
        StartService(service, 0, 0);
        var changedStatus = WaitForServiceStatus(service, ServiceState.StartPending, ServiceState.Running);
        if (!changedStatus)
            throw new ApplicationException("Unable to start service");
    }

    private static void StopService(IntPtr service)
    {
        SERVICE_STATUS status = new SERVICE_STATUS();
        ControlService(service, ServiceControl.Stop, status);
        var changedStatus = WaitForServiceStatus(service, ServiceState.StopPending, ServiceState.Stopped);
        if (!changedStatus)
            throw new ApplicationException("Unable to stop service");
    }

    public static ServiceState GetServiceStatus(string serviceName)
    {
        IntPtr scm = OpenSCManager(ScmAccessRights.Connect);

        try
        {
            IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.QueryStatus);
            if (service == IntPtr.Zero)
                return ServiceState.NotFound;

            try
            {
                return GetServiceStatus(service);
            }
            finally
            {
                CloseServiceHandle(service);
            }
        }
        finally
        {
            CloseServiceHandle(scm);
        }
    }

    private static ServiceState GetServiceStatus(IntPtr service)
    {
        SERVICE_STATUS status = new SERVICE_STATUS();

        if (QueryServiceStatus(service, status) == 0)
            throw new ApplicationException("Failed to query service status.");

        return status.dwCurrentState;
    }

    private static bool WaitForServiceStatus(IntPtr service, ServiceState waitStatus, ServiceState desiredStatus)
    {
        SERVICE_STATUS status = new SERVICE_STATUS();

        QueryServiceStatus(service, status);
        if (status.dwCurrentState == desiredStatus) return true;

        int dwStartTickCount = Environment.TickCount;
        int dwOldCheckPoint = status.dwCheckPoint;

        while (status.dwCurrentState == waitStatus)
        {
            // Do not wait longer than the wait hint. A good interval is
            // one tenth the wait hint, but no less than 1 second and no
            // more than 10 seconds.

            int dwWaitTime = status.dwWaitHint / 10;

            if (dwWaitTime < 1000) dwWaitTime = 1000;
            else if (dwWaitTime > 10000) dwWaitTime = 10000;

            Thread.Sleep(dwWaitTime);

            // Check the status again.

            if (QueryServiceStatus(service, status) == 0) break;

            if (status.dwCheckPoint > dwOldCheckPoint)
            {
                // The service is making progress.
                dwStartTickCount = Environment.TickCount;
                dwOldCheckPoint = status.dwCheckPoint;
            }
            else
            {
                if (Environment.TickCount - dwStartTickCount > status.dwWaitHint)
                {
                    // No progress made within the wait hint
                    break;
                }
            }
        }
        return (status.dwCurrentState == desiredStatus);
    }

    private static IntPtr OpenSCManager(ScmAccessRights rights)
    {
        IntPtr scm = OpenSCManager(null, null, rights);
        if (scm == IntPtr.Zero)
            throw new ApplicationException("Could not connect to service control manager.");

        return scm;
    }
}


public enum ServiceState
{
    Unknown = -1, // The state cannot be (has not been) retrieved.
    NotFound = 0, // The service is not known on the host server.
    Stopped = 1,
    StartPending = 2,
    StopPending = 3,
    Running = 4,
    ContinuePending = 5,
    PausePending = 6,
    Paused = 7
}

[Flags]
public enum ScmAccessRights
{
    Connect = 0x0001,
    CreateService = 0x0002,
    EnumerateService = 0x0004,
    Lock = 0x0008,
    QueryLockStatus = 0x0010,
    ModifyBootConfig = 0x0020,
    StandardRightsRequired = 0xF0000,
    AllAccess = (StandardRightsRequired | Connect | CreateService |
                 EnumerateService | Lock | QueryLockStatus | ModifyBootConfig)
}

[Flags]
public enum ServiceAccessRights
{
    QueryConfig = 0x1,
    ChangeConfig = 0x2,
    QueryStatus = 0x4,
    EnumerateDependants = 0x8,
    Start = 0x10,
    Stop = 0x20,
    PauseContinue = 0x40,
    Interrogate = 0x80,
    UserDefinedControl = 0x100,
    Delete = 0x00010000,
    StandardRightsRequired = 0xF0000,
    AllAccess = (StandardRightsRequired | QueryConfig | ChangeConfig |
                 QueryStatus | EnumerateDependants | Start | Stop | PauseContinue |
                 Interrogate | UserDefinedControl)
}

public enum ServiceBootFlag
{
    Start = 0x00000000,
    SystemStart = 0x00000001,
    AutoStart = 0x00000002,
    DemandStart = 0x00000003,
    Disabled = 0x00000004
}

public enum ServiceControl
{
    Stop = 0x00000001,
    Pause = 0x00000002,
    Continue = 0x00000003,
    Interrogate = 0x00000004,
    Shutdown = 0x00000005,
    ParamChange = 0x00000006,
    NetBindAdd = 0x00000007,
    NetBindRemove = 0x00000008,
    NetBindEnable = 0x00000009,
    NetBindDisable = 0x0000000A
}

public enum ServiceError
{
    Ignore = 0x00000000,
    Normal = 0x00000001,
    Severe = 0x00000002,
    Critical = 0x00000003
}

¡Por favor, avíseme si alguien encuentra algún problema con este código!

Lars A. Brekken
fuente
Estoy intentando usar este código. Pero tengo un problema. El código dentro de mi servicio depende (necesita) del nombre del servicio. Y aunque utilizo este método InstallServicecon un nombre de servicio en particular, si estoy consultando la ServiceNamepropiedad de ServiceBasedentro de mi servicio, siempre me devuelve algo más. ¿Alguna sugerencia sobre cómo obtener ese nombre desde el interior del servicio?
fretje
¿Cómo usaría esto en conjunto con ServiceInstaller y ServiceProcessInstaller?
Alex
¡Muchas gracias Lars! Este código parece hacer exactamente lo que necesito que haga, pero tuve que cambiar algunas cosas porque estaba impaciente. la función "WaitForServiceStatus" se interrumpía y recibía el error "No se puede iniciar el servicio", aunque el servicio se estaba iniciando. Me deshice de muchas comprobaciones y ahora tengo un bucle infinito potencial, pero funciona ... ¿tal vez tienes una idea de por qué la función no está esperando?
thepaulpage
Por lo que recuerdo, es muy impredecible qué tan rápido cambia el estado de un servicio (lo mismo se aplica a la desinstalación). Creo que la documentación también menciona esto.
Lars A. Brekken
1
¿Bajo qué licencia está ese código? ¿Puedo usarlo en un proyecto MS-PL?
Florian
75

Ok, esto es lo que REALMENTE funcionó para mí, se ha probado en varias máquinas con diferentes sistemas operativos (Vista, XP, Win2k, servidor Win2003)

El código se ha tomado de aquí, por lo que todo el crédito es para quien escribió este código.

Una vez que agregue el archivo dll o fuente a su proyecto, asegúrese de agregar el espacio de nombres de ServiceTools y luego tendrá acceso a algunas funciones muy útiles como ...

//Installs and starts the service
ServiceInstaller.InstallAndStart("MyServiceName", "MyServiceDisplayName", "C:\\PathToServiceFile.exe");

//Removes the service
ServiceInstaller.Uninstall("MyServiceName");

//Checks the status of the service
ServiceInstaller.GetServiceStatus("MyServiceName");

//Starts the service
ServiceInstaller.StartService("MyServiceName");

//Stops the service
ServiceInstaller.StopService("MyServiceName");

//Check if service is installed
ServiceInstaller.ServiceIsInstalled("MyServiceName");

Espero que esto ayude.

Konstantinos
fuente
4
Publiqué una respuesta que contiene algunas correcciones de errores en el código que publicó. Eche un vistazo al hilo de discusión en el que encontró el código y verá que el autor del código se da cuenta de que tiene algunos errores.
Lars A. Brekken
La publicación a la que me refiero es: tech-archive.net/Archive/VB/microsoft.public.vb.winapi/2006-08/… Además, encontré otro error o dos en los que el identificador del servicio no se publicó.
Lars A. Brekken
8
Esa solución parece luchar contra una hidra de 25 cabezas cuando todo lo que quieres es un paseo tranquilo por el parque ... tiene que haber una forma más sencilla
Newtopian
¿Cómo puedo configurar un determinado usuario y pw bajo el cual debe ejecutarse el servicio? ¿Puedo utilizar el ServiceInstaller mencionado anteriormente también?
mJay
Si el tiempo de instalación es superior a 10 segundos, informará de la falla.
Sendreams
32

Por favor, lea este artículo .


A veces, es posible que desee instalar un servicio de Windows mediante programación, pero la máquina de destino no tiene InstallUtil.exe.

Agregar una referencia a System.Configuration.Install

Utilice el siguiente código.

Tenga en cuenta que exeFileNamees InstallerClass .exe y no ServiceClass .exe.

public static void InstallService(string exeFilename)
{
    string[] commandLineOptions = new string[1] { "/LogFile=install.log" };

    System.Configuration.Install.AssemblyInstaller installer = new System.Configuration.Install.AssemblyInstaller(exeFilename, commandLineOptions);

    installer.UseNewContext = true;    
    installer.Install(null);    
    installer.Commit(null);

}

Para desinstalar:

public static void UninstallService(string exeFilename)
{
    string[] commandLineOptions = new string[1] { "/LogFile=uninstall.log" };

    System.Configuration.Install.AssemblyInstaller installer = new System.Configuration.Install.AssemblyInstaller(exeFilename, commandLineOptions);

    installer.UseNewContext = true;    
    installer.Uninstall(null);

}
lakshmanaraj
fuente
Ya lo he intentado pero no funciona. Sin excepciones o lo que sea, simplemente no instala el servicio
Konstantinos
Puede ser un problema de ruta completa o de credenciales> Puede intentar escribir un servicio simple. ¿También ha intentado usar la URL anterior donde SCM llama a las API apropiadas usando P / Invoke en C #
lakshmanaraj
3
mi compilador se queja de que AssemblyInstaller (ExeFilename) consume más de un argumento, en realidad parece tener 3 sobrecargas, una no tiene argumentos, los otros dos tienen 2 argumentos cada uno. ¿Ha cambiado algo desde que publicaron esto?
Brian Sweeney
1
Ésta es la forma correcta de instalar un conjunto como servicio. Si no funciona para usted, ¡hizo algo mal! No necesitas todo ese otro código de tercera parte. ¡Gracias lakshmanaraj!
Josh M.
3
Debería ser la respuesta aceptada. Es simple y funciona. (He sugerido una edición ya que falta el segundo parámetro. Además, debe hacer referencia a InstallerClass y no a ServiceClass como exeFileName).
Zanon
12

Después de crear una instancia de una clase de instalador para mi servicio (muy básico), todo lo que tenía que hacer era llamar:

ManagedInstallerClass.InstallHelper(new string[] { 
    Assembly.GetExecutingAssembly().Location });

para instalarlo y

ManagedInstallerClass.InstallHelper(new string[] { "/u", 
    Assembly.GetExecutingAssembly().Location });

para desinstalar el servicio. El código de llamada está, aquí, en el mismo ensamblado que el ejecutable del servicio.

para que el servicio se instale a través de la línea de comando, todo lo que tuve que hacer es conectar esto al ejecutable a través de los argumentos de la línea de comando y probar para System.Environment.UserInteractivesaber si es el servicio que se está ejecutando o alguien que intenta instalarlo, desinstalarlo y listo ... no cosas de interoperabilidad funky ... no se filtran punteros ...

En total, unas 20 líneas de código distribuidas en dos clases hicieron el truco.

para reemplazar InstallUtil, solo eche un vistazo a ManagedInstallerClass.InstallHelper

Newtopian
fuente
Simple. Podría haber llegado a la misma conclusión al reflexionar en InstallUtil.exe. Hace exactamente lo mismo. Además, tiene algunas correcciones de codificación de consola interesantes. Instalar y desinstalar funciona bien. (Recuerde ejecutarlo como administrador ...)
ygoe
6

Al usar el proyecto Topshelf , puede instalar llamando a su ejecutable:

MyService.exe install

Topshelf también se encarga de la plomería de otros servicios de Windows.

Brian Low
fuente
4

Ya que me enfrenté al desafío de instalar servicios mediante programación que se ejecutan bajo un determinado usuario. Amplié el InstallAndStartmétodo para hacer uso de lpy lpPassword...

No mucho, pero podría ayudar.

public static void InstallAndStart(
    string serviceName, 
    string displayName, 
    string fileName, 
    string username, 
    string password)
{
    IntPtr scm = OpenSCManager(ScmAccessRights.AllAccess);

    try
    {
        IntPtr service = OpenService(
            scm, 
            serviceName, 
            ServiceAccessRights.AllAccess);

        if (service == IntPtr.Zero)
            service = CreateService(
                scm, 
                serviceName, 
                displayName, 
                ServiceAccessRights.AllAccess, 
                SERVICE_WIN32_OWN_PROCESS, 
                ServiceBootFlag.AutoStart, 
                ServiceError.Normal, 
                fileName, 
                null, 
                IntPtr.Zero, 
                null, 
                username, 
                password);

        if (service == IntPtr.Zero)
            throw new ApplicationException("Failed to install service.");

        try
        {
            StartService(service);
        }
        finally
        {
            CloseServiceHandle(service);
        }
    }
    finally
    {
        CloseServiceHandle(scm);
    }
}
mJay
fuente
1

En este artículo leí todas las publicaciones y comentarios, pero todavía no sé ¿Cómo puedo configurar el tipo de cuenta y el método StartType cuando voy a agregar el servicio de Windows? Este ejemplo de código funciona bien, por mi parte, solo agregue un servicio propio del sistema local) Pero preparo el programa de instalación, debo pensar en el método StartMode y User Account Type debido al sistema del cliente.
Hay todas las apariencias que ServiceBootFlag enum proporciona StartType pero el tipo de cuenta sigue siendo un problema.

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

    private static extern IntPtr CreateService(IntPtr hSCManager, string

    lpServiceName, string lpDisplayName, ServiceRights dwDesiredAccess, int

    dwServiceType, ServiceBootFlag dwStartType, ServiceError dwErrorControl,

    string lpBinaryPathName, string lpLoadOrderGroup, IntPtr lpdwTagId, string

    lpDependencies, string lp, string lpPassword); 
Tayfur Yılmaz
fuente
1

Usé la respuesta de Lars para administrar mi servicio y funciona bien. Pero necesitaba pasar argumentos al servicio y me tomó un par de horas descubrir cómo hacerlo. Así que decidí publicar una clase alterada con la capacidad de iniciar el servicio con parámetros:

    public static class ServiceHelper
    {
        private const int STANDARD_RIGHTS_REQUIRED = 0xF0000;
        private const int SERVICE_WIN32_OWN_PROCESS = 0x00000010;

        [StructLayout(LayoutKind.Sequential)]
        private class SERVICE_STATUS
        {
            public int dwServiceType = 0;
            public ServiceState dwCurrentState = 0;
            public int dwControlsAccepted = 0;
            public int dwWin32ExitCode = 0;
            public int dwServiceSpecificExitCode = 0;
            public int dwCheckPoint = 0;
            public int dwWaitHint = 0;
        }

        #region OpenSCManager
        [DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
        static extern IntPtr OpenSCManager(string machineName, string databaseName, ScmAccessRights dwDesiredAccess);
        #endregion

        #region OpenService
        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, ServiceAccessRights dwDesiredAccess);
        #endregion

        #region CreateService
        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        private static extern IntPtr CreateService(IntPtr hSCManager, string lpServiceName, string lpDisplayName, ServiceAccessRights dwDesiredAccess, int dwServiceType, ServiceBootFlag dwStartType, ServiceError dwErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, IntPtr lpdwTagId, string lpDependencies, string lp, string lpPassword);
        #endregion

        #region CloseServiceHandle
        [DllImport("advapi32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool CloseServiceHandle(IntPtr hSCObject);
        #endregion

        #region QueryServiceStatus
        [DllImport("advapi32.dll")]
        private static extern int QueryServiceStatus(IntPtr hService, SERVICE_STATUS lpServiceStatus);
        #endregion

        #region DeleteService
        [DllImport("advapi32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool DeleteService(IntPtr hService);
        #endregion

        #region ControlService
        [DllImport("advapi32.dll")]
        private static extern int ControlService(IntPtr hService, ServiceControl dwControl, SERVICE_STATUS lpServiceStatus);
        #endregion

        #region StartService
        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern int StartService(IntPtr hService, int dwNumServiceArgs, string[] lpServiceArgVectors);
        #endregion

        public static void Uninstall(string serviceName)
        {
            IntPtr scm = OpenSCManager(ScmAccessRights.AllAccess);

            try
            {
                IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.AllAccess);
                if (service == IntPtr.Zero)
                    throw new ApplicationException("Service not installed.");

                try
                {
                    StopService(service);
                    if (!DeleteService(service))
                        throw new ApplicationException("Could not delete service " + Marshal.GetLastWin32Error());
                }
                finally
                {
                    CloseServiceHandle(service);
                }
            }
            finally
            {
                CloseServiceHandle(scm);
            }
        }

        public static bool ServiceIsInstalled(string serviceName)
        {
            IntPtr scm = OpenSCManager(ScmAccessRights.Connect);

            try
            {
                IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.QueryStatus);

                if (service == IntPtr.Zero)
                    return false;

                CloseServiceHandle(service);
                return true;
            }
            finally
            {
                CloseServiceHandle(scm);
            }
        }

        public static void InstallAndStart(string serviceName, string displayName, string fileName,string[] args)
        {
            IntPtr scm = OpenSCManager(ScmAccessRights.AllAccess);

            try
            {
                IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.AllAccess);

                if (service == IntPtr.Zero)
                    service = CreateService(scm, serviceName, displayName, ServiceAccessRights.AllAccess, SERVICE_WIN32_OWN_PROCESS, ServiceBootFlag.AutoStart, ServiceError.Normal, fileName, null, IntPtr.Zero, null, null, null);

                if (service == IntPtr.Zero)
                    throw new ApplicationException("Failed to install service.");

                try
                {
                    StartService(service,args);
                }
                finally
                {
                    CloseServiceHandle(service);
                }
            }
            finally
            {
                CloseServiceHandle(scm);
            }
        }

        public static void StartService(string serviceName,string[] args)
        {
            IntPtr scm = OpenSCManager(ScmAccessRights.Connect);

            try
            {
                IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.QueryStatus | ServiceAccessRights.Start);
                if (service == IntPtr.Zero)
                    throw new ApplicationException("Could not open service.");

                try
                {
                    StartService(service,args);
                }
                finally
                {
                    CloseServiceHandle(service);
                }
            }
            finally
            {
                CloseServiceHandle(scm);
            }
        }

        public static void StopService(string serviceName)
        {
            IntPtr scm = OpenSCManager(ScmAccessRights.Connect);

            try
            {
                IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.QueryStatus | ServiceAccessRights.Stop);
                if (service == IntPtr.Zero)
                    throw new ApplicationException("Could not open service.");

                try
                {
                    StopService(service);
                }
                finally
                {
                    CloseServiceHandle(service);
                }
            }
            finally
            {
                CloseServiceHandle(scm);
            }
        }

        private static void StartService(IntPtr service,string[] args)
        {
            SERVICE_STATUS status = new SERVICE_STATUS();
            StartService(service, args.Length, args);
            var changedStatus = WaitForServiceStatus(service, ServiceState.StartPending, ServiceState.Running);
            if (!changedStatus)
                throw new ApplicationException("Unable to start service");
        }

        private static void StopService(IntPtr service)
        {
            SERVICE_STATUS status = new SERVICE_STATUS();
            ControlService(service, ServiceControl.Stop, status);
            var changedStatus = WaitForServiceStatus(service, ServiceState.StopPending, ServiceState.Stopped);
            if (!changedStatus)
                throw new ApplicationException("Unable to stop service");
        }

        public static ServiceState GetServiceStatus(string serviceName)
        {
            IntPtr scm = OpenSCManager(ScmAccessRights.Connect);

            try
            {
                IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.QueryStatus);
                if (service == IntPtr.Zero)
                    return ServiceState.NotFound;

                try
                {
                    return GetServiceStatus(service);
                }
                finally
                {
                    CloseServiceHandle(service);
                }
            }
            finally
            {
                CloseServiceHandle(scm);
            }
        }

        private static ServiceState GetServiceStatus(IntPtr service)
        {
            SERVICE_STATUS status = new SERVICE_STATUS();

            if (QueryServiceStatus(service, status) == 0)
                throw new ApplicationException("Failed to query service status.");

            return status.dwCurrentState;
        }

        private static bool WaitForServiceStatus(IntPtr service, ServiceState waitStatus, ServiceState desiredStatus)
        {
            SERVICE_STATUS status = new SERVICE_STATUS();

            QueryServiceStatus(service, status);
            if (status.dwCurrentState == desiredStatus) return true;

            int dwStartTickCount = Environment.TickCount;
            int dwOldCheckPoint = status.dwCheckPoint;

            while (status.dwCurrentState == waitStatus)
            {
                // Do not wait longer than the wait hint. A good interval is
                // one tenth the wait hint, but no less than 1 second and no
                // more than 10 seconds.

                int dwWaitTime = status.dwWaitHint / 10;

                if (dwWaitTime < 1000) dwWaitTime = 1000;
                else if (dwWaitTime > 10000) dwWaitTime = 10000;

                Thread.Sleep(dwWaitTime);

                // Check the status again.

                if (QueryServiceStatus(service, status) == 0) break;

                if (status.dwCheckPoint > dwOldCheckPoint)
                {
                    // The service is making progress.
                    dwStartTickCount = Environment.TickCount;
                    dwOldCheckPoint = status.dwCheckPoint;
                }
                else
                {
                    if (Environment.TickCount - dwStartTickCount > status.dwWaitHint)
                    {
                        // No progress made within the wait hint
                        break;
                    }
                }
            }
            return (status.dwCurrentState == desiredStatus);
        }

        private static IntPtr OpenSCManager(ScmAccessRights rights)
        {
            IntPtr scm = OpenSCManager(null, null, rights);
            if (scm == IntPtr.Zero)
                throw new ApplicationException("Could not connect to service control manager.");

            return scm;
        }
    }


    public enum ServiceState
    {
        Unknown = -1, // The state cannot be (has not been) retrieved.
        NotFound = 0, // The service is not known on the host server.
        Stopped = 1,
        StartPending = 2,
        StopPending = 3,
        Running = 4,
        ContinuePending = 5,
        PausePending = 6,
        Paused = 7
    }

    [Flags]
    public enum ScmAccessRights
    {
        Connect = 0x0001,
        CreateService = 0x0002,
        EnumerateService = 0x0004,
        Lock = 0x0008,
        QueryLockStatus = 0x0010,
        ModifyBootConfig = 0x0020,
        StandardRightsRequired = 0xF0000,
        AllAccess = (StandardRightsRequired | Connect | CreateService |
                     EnumerateService | Lock | QueryLockStatus | ModifyBootConfig)
    }

    [Flags]
    public enum ServiceAccessRights
    {
        QueryConfig = 0x1,
        ChangeConfig = 0x2,
        QueryStatus = 0x4,
        EnumerateDependants = 0x8,
        Start = 0x10,
        Stop = 0x20,
        PauseContinue = 0x40,
        Interrogate = 0x80,
        UserDefinedControl = 0x100,
        Delete = 0x00010000,
        StandardRightsRequired = 0xF0000,
        AllAccess = (StandardRightsRequired | QueryConfig | ChangeConfig |
                     QueryStatus | EnumerateDependants | Start | Stop | PauseContinue |
                     Interrogate | UserDefinedControl)
    }

    public enum ServiceBootFlag
    {
        Start = 0x00000000,
        SystemStart = 0x00000001,
        AutoStart = 0x00000002,
        DemandStart = 0x00000003,
        Disabled = 0x00000004
    }

    public enum ServiceControl
    {
        Stop = 0x00000001,
        Pause = 0x00000002,
        Continue = 0x00000003,
        Interrogate = 0x00000004,
        Shutdown = 0x00000005,
        ParamChange = 0x00000006,
        NetBindAdd = 0x00000007,
        NetBindRemove = 0x00000008,
        NetBindEnable = 0x00000009,
        NetBindDisable = 0x0000000A
    }

    public enum ServiceError
    {
        Ignore = 0x00000000,
        Normal = 0x00000001,
        Severe = 0x00000002,
        Critical = 0x00000003
    }
Ali Sharafi
fuente
0

Use el siguiente código para instalar el servicio de Windows usando C #:

public void InstallWinService(string winServicePath)
{
        try
        {
            ManagedInstallerClass.InstallHelper(new string[] { winServicePath});
        }
        catch (Exception)
        {

            throw;
        }
}
Mahsh Nikam
fuente