Как программно установить службу Windows в C #?

У меня есть 3 проекта в моем решении VS. Одним из них является веб-приложение, вторым - служба Windows, а последним - проект установки для моего веб-приложения.

Что я хочу, так это к концу установки веб-приложения в моем проекте установки, в рамках моего настраиваемого действия, чтобы попытаться установить мою службу Windows, учитывая, что к тому времени у меня уже есть местоположение сборки.

9 ОТВЕТОВ

Пожалуйста, посмотрите на эту статью .


Иногда может потребоваться установить службу Windows программным способом, но на целевом компьютере не установлен InstallUtil.exe.

Добавить ссылку на System.Configuration.Install

Используйте код ниже.

Обратите внимание, что exeFileNameэто InstallerClass .exe, а не 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);

}

Чтобы удалить:

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);

}
31
5.09.2014 02:54:18
Я уже пробовал это, но это не работает. Никаких исключений или чего-то еще, он просто не устанавливает сервис
Konstantinos 11.12.2008 08:49:17
Может быть проблема с полным путем или учетными данными> Вы можете попробовать написать простой сервис. Вы также пытались использовать вышеупомянутый URL, где SCM вызывает соответствующие API, используя P / Invoke в C #
lakshmanaraj 11.12.2008 08:59:38
путь API / Pinvoke сделал свою работу. Видимо, простой способ требует, чтобы установщик был включен в проект службы Windows .. или так я думаю.
Konstantinos 11.12.2008 09:49:55
Мой компилятор жалуется, что AssemblyInstaller (ExeFilename) использует более одного аргумента - на самом деле кажется, что он имеет 3 перегрузки - у одного нет аргументов, у двух других по 2 аргумента. что-то изменилось с тех пор, как вы, ребята, опубликовали это?
Brian Sweeney 14.02.2009 20:46:07
Это должен быть принятый ответ. Это просто и это работает. (Я предложил редактирование, поскольку второй параметр отсутствует. Кроме того, вы должны ссылаться на InstallerClass, а не на ServiceClass в качестве exeFileName).
Zanon 5.09.2014 02:28:17
РЕШЕНИЕ

Хорошо, вот что ДЕЙСТВИТЕЛЬНО сработало для меня, это было протестировано на нескольких машинах с разными ОС (Vista, XP, Win2k, Win2003 server)

Код был взят отсюда, так что вся заслуга тому, кто написал этот кусок кода.

После того, как вы добавите dll или исходный файл в свой проект, обязательно добавьте пространство имен ServiceTools, и тогда у вас будет доступ к некоторым очень удобным функциям, таким как ...

//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");

Надеюсь, это поможет.

75
8.06.2018 15:40:26
Я опубликовал ответ, содержащий исправления ошибок в коде, который вы опубликовали. Посмотрите на ветку обсуждения, в которой вы нашли код, и вы увидите, что автор кода понимает, что в нем есть некоторые ошибки.
Lars A. Brekken 23.07.2009 14:24:08
Сообщение, на которое я ссылаюсь: tech-archive.net/Archive/VB/microsoft.public.vb.winapi/2006-08/… Кроме того, я обнаружил еще одну или две ошибки, когда дескриптор службы не был выпущен.
Lars A. Brekken 23.07.2009 14:25:47
Это решение похоже на борьбу с гидрой с 25 головами, когда все, что вам нужно, это тихая прогулка в парке ... должен быть более простой путь
Newtopian 23.07.2012 19:51:34
Как я могу установить определенного пользователя и pw, под которым должна работать служба? Могу ли я использовать ServiceInstaller, упомянутый выше?
mJay 27.11.2014 17:43:02
если время установки превышает 10 секунд, он сообщит об ошибке.
sendreams 14.04.2017 10:20:31

Я нашел несколько ошибок в коде, который вы использовали повторно, и исправил их, а также немного их очистил. Опять же, оригинальный код взят здесь .

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
}

Пожалуйста, дайте мне знать, если кто-нибудь найдет что-то не так с этим кодом!

83
23.07.2009 14:22:45
Использование его в производстве
Lars A. Brekken 6.11.2009 20:30:31
Я пытаюсь использовать этот код. Но у меня есть проблема. Код внутри моего сервиса зависит от (нуждается) в названии сервиса. И хотя я использую этот метод InstallServiceс определенным именем сервиса, если я запрашиваю ServiceNameсвойство ServiceBaseвнутри моего сервиса, он всегда возвращает мне что-то другое. Любые предложения о том, как на самом деле получить это имя из службы?
fretje 22.01.2010 16:02:18
как бы вы использовали это в сочетании с ServiceInstaller и ServiceProcessInstaller?
Alex 26.01.2010 10:46:33
Большое спасибо, Ларс! Этот код, кажется, делает именно то, что мне нужно, но мне пришлось кое-что изменить, потому что он был нетерпеливым. функция «WaitForServiceStatus» выходила из строя, и я получал ошибку «Невозможно запустить службу», хотя служба фактически запускалась. Я избавился от множества проверок, и теперь у меня есть потенциальный бесконечный цикл, но он работает ... может быть, у вас есть идея, почему функция не ждет?
thepaulpage 17.03.2010 15:32:17
Под какой лицензией этот код? Могу ли я использовать это проект MS-PL?
Florian 7.05.2014 06:23:05

Используя проект Topshelf, вы можете установить, вызвав свой исполняемый файл:

MyService.exe install

Topshelf также заботится о других системах Windows Service.

6
10.12.2010 03:51:55

После создания экземпляра класса установщика для моей службы (очень простой) все, что мне нужно было сделать, это позвонить:

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

установить его и

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

удалить службу. Здесь вызывающий код находится в той же сборке, что и исполняемый файл службы.

чтобы получить службу для установки через командную строку, все, что мне нужно было сделать, это подключить ее к исполняемому файлу через аргументы командной строки и проверить, System.Environment.UserInteractiveчтобы узнать, выполняет ли она службу или кто-то пытается ее установить, удалить и вуаля ... нет Прикольные вещи взаимодействия ... нет указателей утечки ...

Всего около 20 строк кода, распределенных по двум классам, сделали свое дело.

заменить InstallUtil просто взгляните на ManagedInstallerClass.InstallHelper

12
18.11.2013 22:41:42
Просто. Вы могли бы прийти к такому же выводу при отражении в InstallUtil.exe. Это делает то же самое. Плюс у него есть некоторые интересные исправления консольного кодирования. Установка и удаление работает нормально. (Не забудьте запустить его от имени администратора ...)
ygoe 13.02.2014 10:34:23

В этой статье я читаю все посты и комментарии, но до сих пор не знаю, как я могу установить тип учетной записи и метод StartType, когда я собираюсь добавить службу Windows. Этот пример кода отлично работает с моей стороны, это просто добавить собственную локальную систему службы) Но я готовлю программу установки, я должен думать, StartMode и метод типа учетной записи пользователя из-за системы клиентов.
есть каждое появление , что ServiceBootFlag перечисление обеспечивает StartType но тип счета до сих пор проблемы.

    [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); 
1
26.08.2013 15:01:02

Так как я столкнулся с проблемой программной установки сервисов, которые запускаются под определенным пользователем. Я расширил InstallAndStartметод, чтобы использовать lpи lpPassword...

Не очень, но может помочь.

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);
    }
}
4
25.02.2015 10:33:57

Используйте приведенный ниже код для установки службы Windows с использованием C #:

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

            throw;
        }
}
0
15.03.2016 12:55:06

Я использовал ответ Lars для управления своим сервисом, и он работает нормально. Но мне нужно было передать аргументы в службу, и мне потребовалось несколько часов, чтобы понять, как это сделать. Поэтому я решил опубликовать измененный класс с возможностью запуска сервиса с параметрами:

    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 
  
1
21.04.2020 16:00:59