zoukankan      html  css  js  c++  java
  • C# 控制系统服务

    .net控制系统服务的类位于System.ServiceProcess命名空间下,应用程序需要引入System.ServiceProcess动态库。使用System.ServiceProcess.ServiceController类控制服务。ServiceController允许你与一个已有的服务进行交互并读取和修改其属性。下列程序展示了如何获取MySQL服务的名称、服务类型和显示名称。

    ServiceController scStateService = new 
    ServiceController("MySQL");
    Console.WriteLine(string.Format("Service Type: {0}",scStateService.ServiceType.ToString()));
    Console.WriteLine(string.Format("Service Name: {0}",scStateService.ServiceName));
    Console.WriteLine(string.Format("Display Name: {0}",scStateService.DisplayName));
    

    ServiceType有一些枚举值。

    描述
    Adapter 用于硬件设备的服务
    FileSystemDriver 文件系统驱动(内核级别)
    InteractiveProcess 与桌面进行通讯的服务
    KernelDriver 低级别的硬件设备驱动
    RecognizerDriver 在启动时用于确定文件系统的驱动
    Win32OwnProcess 作为一项服务在其独立进程中运行的Win32程序
    Win32ShareProcess 作为一项服务在共享进程(如svcHost)中运行的Win32程序

    确定一个服务的依赖性服务通常很有用。使用DependentServcies属性进行访问。它是一个ServiceController实例数组。

    foreach (ServiceController sc in scStateService.DependentServices)
    {
        Console.WriteLine(string.Format("{0} is depended on by: {1}",scStateService.DisplayName,sc.DisplayName));
    }
    

    ServicesDependedOn 数组包含当前服依赖的每一个服务对应的ServcieController实例。

    foreach (ServiceController sc in scStateService.ServicesDependedOn)
    {
        Console.WriteLine($"{scStateService.DisplayName} depends on: {sc.DisplayName}");
    }
    

    关于服务最重要的就是它的状态。要找出当前服务的状态,可检查Status属性。

    Console.WriteLine($"Status: {scStateService.Status}");
    //保存原始状态
    ServiceControllerStatus originalState = scStateService.Status;
    

    既然已经建立了合适的访问,就可以开始使用服务的方法。如果要停止服务,可以使用Stop方法,反之则使用Start方法启动服务。WaitForStatus可以接受一个超时值,使程序不必在出现问题时永远等待服务启动。

    TimeSpan serviceTimeout = TimeSpan.FromSeconds(60);
    if (scStateService.Status == ServiceControllerStatus.Stopped)
    {
        scStateService.Start();
        scStateService.WaitForStatus(ServiceControllerStatus.Running,serviceTimeout);
    }
    Console.WriteLine($"Status: {scStateService.Status}");
    

    服务也可以暂停。如果服务被暂停,应用程序可以查看CanPauseAndContinue属性检查是否能够继续运行。如果可以,continue方法使服务继续运行,而WaitForStatus方法应当被调用以等待服务运行。

    if (scStateService.Status == ServiceControllerStatus.Paused)
    {
        if (scStateService.CanPauseAndContinue)
        {
            scStateService.Continue();
            scStateService.WaitForStatus(ServiceControllerStatus.Running,serviceTimeout);
        }
    }
    Console.WriteLine($"Status: {scStateService.Status}");
    

    确定一种服务能否被停止可以使用CanStop属性来完成。如果它能被停止,足需要调用Stop方法以及WaitForStatus.

    if (scStateService.CanStop)
    {
        scStateService.Stop();
        scStateService.WaitForStatus(ServiceControllerStatus.Stopped,serviceTimeout);
    }
    Console.WriteLine($"Status: {scStateService.Status}");
    

    即使CanStop可能返回True,如果没有在管理上下文中运行,就会在试图停止服务时出现一下异常:

    A first chance exception of type 'System.InvalidOperationException' occurred in
    System.ServiceProcess.dll
    Additional information: Cannot open EventSystem service on computer '.'.
    

    这需要为代码设置适当的安全访问权限。
    将服务器状态回归原始状态。orinalStatus持有原始状态,switch语句将包含将服务从当前停止状态转换为原始状态的动作。

    switch (originalState)
    {
        case ServiceControllerStatus.Stopped:
            if (scStateService.CanStop)
                scStateService.Stop();
            break;
        case ServiceControllerStatus.Running:
            scStateService.Start();
            scStateService.WaitForStatus(ServiceControllerStatus.Running,serviceTimeout);
            break;
        case ServiceControllerStatus.Paused:
            if (scStateService.Status == ServiceControllerStatus.Stopped)
            {
                scStateService.Start();
                scStateService.WaitForStatus(ServiceControllerStatus.Running,serviceTimeout);
            }
            if (scStateService.CanPauseAndContinue)
            {
                scStateService.Pause();
                scStateService.WaitForStatus(ServiceControllerStatus.Paused,serviceTimeout);
            }
            break;
    }
    

    为确保服务的Status属性正确,程序应当在测试Status值之前调用Refresh进行更新。一旦应用程序完成对服务的使用,就调用Close方法。

    scStateService.Refresh();
    Console.WriteLine($"Status: {scStateService.Status.ToString()}");
    scStateService.Close();
    

    Tips:

    Windows 7或其之后的操作系统加入了UAC(用户账户控制),直接调用系统服务可能会出现权限不足的问题,这需要为应用程序提高权限.要在代码中做到这一点,可将一个app.manifest文件(应用程序清单文件),此文件的asmv1:assembly rustinfosecurity equestedPrivileges节默认请求的执行级别是以调用代码的用户来运行。

    <requestedExecutionLevel level="asInvoker" uiAccess="false" />

    要允许访问服务方法,可把level属性设置为requireAdministrator

    <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>

    这样确保代码有足够的权限执行。

  • 相关阅读:
    HZOJ 通讯
    HZOJ 礼物
    HZOI 可怜与超市
    高二小假期集训—D5
    [BZOJ3566][SHOI2014]概率充电器
    [***]HZOI20190714 T2熟练剖分
    20190714(又一次翻车……)
    HZOI20190714 T3建造游乐场
    模板—慢速乘
    模板—十进制快速幂
  • 原文地址:https://www.cnblogs.com/lsy1991/p/10287053.html
Copyright © 2011-2022 走看看