Подтвердить что ты не робот

Как я могу программно остановить/запустить службу Windows в удаленном окне?

Я хочу написать консоль или приложение Click Once WinForms, которое будет программно останавливаться и/или запускать службу Windows в удаленном поле.

В обоих ящиках работает .NET 3.5 - какой .NET API доступен для этого?

4b9b3361

Ответ 1

в С#:

var sc = new System.ServiceProcess.ServiceController("MyService", "MyRemoteMachine");
sc.Start();
sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Running);
sc.Stop();
sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped);

Ответ 2

Вы также можете сделать это из командной консоли с помощью команды sc:

 sc <server> start [service name]
 sc <server> stop [service name]

Используйте

sc <server> query | find "SERVICE_NAME"

чтобы получить список имен служб.

Опция <server> имеет форму \\ServerName

Пример

sc \\MyServer stop schedule остановит службу Планировщика.

Ответ 3

ServiceController.

У вас должно быть разрешение на администрирование служб в удаленном поле.

Как говорит Мехрдад, вы также можете использовать WMI. Оба метода работают для запуска и остановки, но WMI требует больше кодирования и даст вам больше доступа к другим ресурсам.

Ответ 4

Если вы не хотите самостоятельно его кодировать, PsService от Microsoft/Sysinternals - это инструмент командной строки, который делает то, что вы хотите.

Ответ 5

Вы можете использовать API System.Management (WMI) для удаленного управления службами. WMI - это общий API для выполнения административных задач.

Для этой проблемы, однако, я предлагаю вам использовать более простой в использовании класс System.ServiceProcess.ServiceController.

Ответ 6

если вам нужно получить имя службы:

запустите это из командной строки:

sc

Вы увидите, например, что имя службы SQL Server - "MSSQL $SQLEXPRESS".

Итак, чтобы остановить службу SQL Server на С#:

        ServiceController controller = new ServiceController();
        controller.MachineName = "Machine1";
        controller.ServiceName = "MSSQL$SQLEXPRESS";

        if(controller.Status == ServiceControllerStatus.Running)
            controller.Stop();

        controller.WaitForStatus(ServiceControllerStatus.Stopped);

Ответ 7

Я сделал, как показано ниже:

Примечание:

  1. Если вы не запустили службу, если пытаетесь ее остановить, возникнет исключение.
  2. Если вы сконфигурируете эти вещи в своем файле web.config, исключение, связанное с конфигурацией, не появится. Не нужно ничего делать в IIS.

В Web.Config под <configuration>

  <appSettings>
    <add key="ServiceName" value="YourServiceName" />
    <add key="MachineName" value="YourMachineName" />
  </appSettings>
  <system.web>
    <authentication mode="Windows"/>
    <identity impersonate="true" userName="YourUserName" password="YourPassword"/>
  </system.web>

В моем классе обслуживания:

private void RestartService()
{
    string serviceName = System.Configuration.ConfigurationSettings.AppSettings["ServiceName"];
    string machineName = System.Configuration.ConfigurationSettings.AppSettings["MachineName"];

    try
    {
        var service = new ServiceController(serviceName, machineName);
        if (service.Status != ServiceControllerStatus.Stopped)
        {
            service.Stop();
            service.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped);
        }

        service.Start();
        service.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Running);

    }
    catch (Exception)
    {
    }
}

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

Ответ 8

Фрагмент кода

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

sc.Status == System.ServiceProcess.ServiceControllerStatus.Running

Кроме того, важно, чтобы в какой-то момент во время выполнения кода вызывал

sc.Refresh();

поскольку значения свойств (например, ServiceControllerStatus) могут не отражать фактические свойства службы. Например, вы можете вызвать

sc.Start();

и ждать неопределенно, когда эта команда выполняет

sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Running)

Вот версия этого кода, которую я кодировал с учетом этих соображений.

            //Restart Content Service on DEV. 
        String svcName = "TheServiceName";
        String machineName = "TheMachineName";
        var sc = new System.ServiceProcess.ServiceController(svcName, machineName);
        Console.WriteLine("Stopping Service '{0}' on machine '{1}", svcName, machineName);
        sc.Stop();
        sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped);          

        //sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Running);
        do
        {
            try
            {
                sc.Refresh();
                if (sc.Status == System.ServiceProcess.ServiceControllerStatus.Running)
                {
                    Console.WriteLine("Code has detected that servive start is pending, waiting 5 seconds to see if status changes..");
                    System.Threading.Thread.Sleep(5000);
                }
                else
                {
                    Console.WriteLine("waiting 5 seconds and retrying start..");
                    System.Threading.Thread.Sleep(5000);
                    Console.WriteLine("Attempt Starting Service '{0}' on machine '{1}", svcName, machineName);
                    sc.Start();
                }
            }

            catch(Exception ex)
            {
                //If it is already running, then abort do while
                if (ex.InnerException.Message == "An instance of the service is already running")
                {
                    Console.WriteLine(ex.InnerException.Message);
                    continue;
                }
                Console.WriteLine(ex.InnerException.ToString());
            }
        } while (sc.Status != System.ServiceProcess.ServiceControllerStatus.Running);

Ответ 9

Вот ServiceExtension, который может запускать и останавливать службы на удаленном компьютере.

И он может установить тип запуска для службы, даже для "автоматического (отложенного)"

измененная версия этого Answer для работы на удаленных машинах.

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.ServiceProcess;

namespace Helpers
{
    public enum ServiceStartModeEx
    {
        Automatic = 2,
        Manual = 3,
        Disabled = 4,
        DelayedAutomatic = 99
    }
    /// <summary>
    /// Extensions to the ServiceController class.
    /// </summary>
    public static class ServiceControlerExtensions
    {
        /// <summary>
        /// Set the start mode for the service.
        /// </summary>
        /// <param name="serviceController">The service controller.</param>
        /// <param name="mode">The desired start mode.</param>
        public static void SetStartMode(this ServiceController serviceController, ServiceStartModeEx mode)
        {
            IntPtr serviceManagerHandle = OpenServiceManagerHandle(serviceController);
            IntPtr serviceHandle = OpenServiceHandle(serviceController, serviceManagerHandle);

            try
            {
                if (mode == ServiceStartModeEx.DelayedAutomatic)
                {
                    ChangeServiceStartType(serviceHandle, ServiceStartModeEx.Automatic);
                    ChangeDelayedAutoStart(serviceHandle, true);
                }
                else
                {
                    // Delayed auto-start overrides other settings, so it must be set first.
                    ChangeDelayedAutoStart(serviceHandle, false);
                    ChangeServiceStartType(serviceHandle, mode);
                }
            }
            finally
            {
                if (serviceHandle != IntPtr.Zero)
                {
                    CloseServiceHandle(serviceHandle);
                }
                if (serviceManagerHandle != IntPtr.Zero)
                {
                    CloseServiceHandle(serviceManagerHandle);
                }
            }
        }

        private static IntPtr OpenServiceHandle(ServiceController serviceController, IntPtr serviceManagerHandle)
        {
            var serviceHandle = OpenService(
                                            serviceManagerHandle,
                                            serviceController.ServiceName,
                                            SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG);

            if (serviceHandle == IntPtr.Zero)
            {
                throw new ExternalException("Open Service Error");
            }
            return serviceHandle;
        }

        private static IntPtr OpenServiceManagerHandle(ServiceController serviceController)
        {
            var machineName = string.IsNullOrWhiteSpace(serviceController.MachineName)
                ? null
                : serviceController.MachineName;
            IntPtr serviceManagerHandle = OpenSCManager(machineName, null, SC_MANAGER_ALL_ACCESS);
            if (serviceManagerHandle == IntPtr.Zero)
            {
                throw new ExternalException("Open Service Manager Error");
            }
            return serviceManagerHandle;
        }

        private static void ChangeServiceStartType(IntPtr serviceHandle, ServiceStartModeEx mode)
        {
            bool result = ChangeServiceConfig(
                                             serviceHandle,
                                             SERVICE_NO_CHANGE,
                                             (uint)mode,
                                             SERVICE_NO_CHANGE,
                                             null,
                                             null,
                                             IntPtr.Zero,
                                             null,
                                             null,
                                             null,
                                             null);

            if (result == false)
            {
                ThrowLastWin32Error("Could not change service start type");
            }
        }

        private static void ChangeDelayedAutoStart(IntPtr hService, bool delayed)
        {
            // Create structure that contains DelayedAutoStart property.
            SERVICE_DELAYED_AUTO_START_INFO info = new SERVICE_DELAYED_AUTO_START_INFO();

            // Set the DelayedAutostart property in that structure.
            info.fDelayedAutostart = delayed;

            // Allocate necessary memory.
            IntPtr hInfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SERVICE_DELAYED_AUTO_START_INFO)));

            // Convert structure to pointer.
            Marshal.StructureToPtr(info, hInfo, true);

            // Change the configuration.
            bool result = ChangeServiceConfig2(hService, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, hInfo);

            // Release memory.
            Marshal.FreeHGlobal(hInfo);

            if (result == false)
            {
                ThrowLastWin32Error("Could not set service to delayed automatic");
            }
        }

        private static void ThrowLastWin32Error(string messagePrefix)
        {
            int nError = Marshal.GetLastWin32Error();
            var win32Exception = new Win32Exception(nError);
            string message = string.Format("{0}: {1}", messagePrefix, win32Exception.Message);
            throw new ExternalException(message);
        }

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

        [DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode,
            SetLastError = true)]
        private static extern IntPtr OpenSCManager(
            string machineName,
            string databaseName,
            uint dwAccess);

        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        private static extern Boolean ChangeServiceConfig(
            IntPtr hService,
            UInt32 nServiceType,
            UInt32 nStartType,
            UInt32 nErrorControl,
            String lpBinaryPathName,
            String lpLoadOrderGroup,
            IntPtr lpdwTagId,
            [In] char[] lpDependencies,
            String lpServiceStartName,
            String lpPassword,
            String lpDisplayName);

        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool ChangeServiceConfig2(
            IntPtr hService,
            int dwInfoLevel,
            IntPtr lpInfo);

        [DllImport("advapi32.dll", EntryPoint = "CloseServiceHandle")]
        private static extern int CloseServiceHandle(IntPtr hSCObject);

        private const uint SERVICE_NO_CHANGE = 0xFFFFFFFF;
        private const uint SERVICE_QUERY_CONFIG = 0x00000001;
        private const uint SERVICE_CHANGE_CONFIG = 0x00000002;
        private const uint SC_MANAGER_ALL_ACCESS = 0x000F003F;

        private const int SERVICE_CONFIG_DELAYED_AUTO_START_INFO = 3;

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        private struct SERVICE_DELAYED_AUTO_START_INFO
        {
            public bool fDelayedAutostart;
        }
    }
}

Вы можете запустить сервис, подобный этому

 using System.ServiceProcess;

serviceName = "имя службы"

machineName = "имя удаленного/локального хоста"

 var service = new ServiceController(serviceName, machineName);
 try
 {
     service.SetStartMode(ServiceStartModeEx.DelayedAutomatic);
     service.Start();
 }

 finally
 {
     service.Close();
 }

Вы можете остановить службу, подобную этой

var service = new ServiceController(serviceName, machineName);
try
{
    if (service.CanStop)
    {
        service.SetStartMode(ServiceStartModeEx.Disabled);
        service.Stop();

    }
}

finally
{
    service.Close();
}

Чтобы предоставить пользователю право запускать и останавливать службу на удаленном компьютере, вам необходимо установить некоторые права службы, вы можете указать, какой файл subinacl.exe и где его загрузить.

C:\Program Files (x86)\Windows Resource Kits\Tools>subinacl.exe /service SERVICENAME /grant=MACHINENAME\USERNAME=F