LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

C# 设置指定程序为Windows系统服务方式运行,或者关闭指定程序在Windows系统服务

admin
2025年6月2日 18:49 本文热度 413

在C#中管理Windows服务(安装、启动、停止、卸载)需要使用System.ServiceProcess命名空间以及可能的进程调用(如sc.exe)。以下代码示例分为两部分:将程序安装为服务停止/卸载服务

1、将程序安装为Windows服务

2、停止并卸载Windows服务

前提条件:目标程序必须实现Windows服务逻辑(如继承自ServiceBase的.NET程序或符合Windows服务标准的可执行文件)。

public class exeSysService

{

    // 使用sc.exe安装服务

    public static void InstallService(string serviceName, string executablePath)

    {

        Process process = new Process();

        ProcessStartInfo startInfo = new ProcessStartInfo

        {

            FileName = "sc.exe",

            Arguments = $"create \"{serviceName}\" binPath= \"{executablePath}\" start= auto",

            WindowStyle = ProcessWindowStyle.Hidden,

            Verb = "runas" // 请求管理员权限

        };

        process.StartInfo = startInfo;

        process.Start();

        process.WaitForExit();


        if (process.ExitCode == 0)

        {

            Console.WriteLine("服务安装成功!");

            StartService(serviceName); // 安装后启动服务

        }

        else

        {

            Console.WriteLine($"服务安装失败,错误代码: {process.ExitCode}");

        }

    }


    // 启动服务

    private static void StartService(string serviceName)

    {

        using (ServiceController service = new ServiceController(serviceName))

        {

            if (service.Status != ServiceControllerStatus.Running)

            {

                service.Start();

                service.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(30));

                Console.WriteLine("服务已启动!");

            }

        }

    }



    // 停止并卸载服务

    public static void UninstallService(string serviceName)

    {

        StopService(serviceName); // 先停止服务


        Process process = new Process();

        ProcessStartInfo startInfo = new ProcessStartInfo

        {

            FileName = "sc.exe",

            Arguments = $"delete \"{serviceName}\"",

            WindowStyle = ProcessWindowStyle.Hidden,

            Verb = "runas" // 请求管理员权限

        };

        process.StartInfo = startInfo;

        process.Start();

        process.WaitForExit();


        if (process.ExitCode == 0)

            Console.WriteLine("服务卸载成功!");

        else

            Console.WriteLine($"服务卸载失败,错误代码: {process.ExitCode}");

    }


    // 停止服务

    private static void StopService(string serviceName)

    {

        using (ServiceController service = new ServiceController(serviceName))

        {

            if (service.CanStop && service.Status != ServiceControllerStatus.Stopped)

            {

                service.Stop();

                service.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(30));

                Console.WriteLine("服务已停止!");

            }

        }

    }

}

使用示例

// 安装服务

ServiceInstaller.InstallService(

    "MyService",          // 服务名称

    @"C:\MyApp\MyService.exe" // 可执行文件路径

);


// 卸载服务

ServiceUninstaller.UninstallService("MyService");

关键注意事项

1、管理员权限:操作服务需要以管理员身份运行程序(在Visual Studio中右键项目 → 属性 → 安全性 → 勾选“启用ClickOnce安全设置”,或在清单文件中设置requestedExecutionLevel level="requireAdministrator")。

2、服务程序要求

  • 目标程序必须是专门设计的Windows服务(如.NET中继承ServiceBase)。

  • 普通.exe程序无法直接作为服务安装(需使用NSSM等工具封装)。

3、错误处理:添加更完善的异常处理(如服务不存在时的InvalidOperationException)。

4、超时处理WaitForStatus可能因服务未及时响应而超时,需额外处理。

替代方案:使用Windows API

更高级的场景可调用Windows API(如CreateServiceOpenSCManager),需通过P/Invoke调用advapi32.dll,代码复杂度较高。推荐使用上述sc.exe方案或开源库(如Topshelf)简化开发。

在 C# 中判断 Windows 服务是否已安装,可以通过 ServiceController 类来实现。以下是完整的代码示例:

using System;

using System.ServiceProcess;

using System.Collections.Generic;


public class ServiceHelper

{

    /// <summary>

    /// 检查服务是否已安装

    /// </summary>

    /// <param name="serviceName">服务名称</param>

    /// <returns>true 表示已安装,false 表示未安装</returns>

    public static bool IsServiceInstalled(string serviceName)

    {

        try

        {

            // 获取所有服务

            ServiceController[] services = ServiceController.GetServices();

            

            // 遍历检查服务是否存在

            foreach (ServiceController service in services)

            {

                if (service.ServiceName.Equals(serviceName, StringComparison.OrdinalIgnoreCase))

                {

                    return true;

                }

            }

            return false;

        }

        catch (Exception ex)

        {

            Console.WriteLine($"检查服务时出错: {ex.Message}");

            return false;

        }

    }


    /// <summary>

    /// 检查服务是否已安装(使用 LINQ 优化版本)

    /// </summary>

    public static bool IsServiceInstalledLinq(string serviceName)

    {

        try

        {

            return Array.Exists(ServiceController.GetServices(), 

                service => service.ServiceName.Equals(serviceName, StringComparison.OrdinalIgnoreCase));

        }

        catch (Exception ex)

        {

            Console.WriteLine($"检查服务时出错: {ex.Message}");

            return false;

        }

    }


    /// <summary>

    /// 获取所有已安装服务的名称列表

    /// </summary>

    public static List<string> GetAllInstalledServices()

    {

        List<string> serviceNames = new List<string>();

        try

        {

            foreach (ServiceController service in ServiceController.GetServices())

            {

                serviceNames.Add(service.ServiceName);

            }

        }

        catch (Exception ex)

        {

            Console.WriteLine($"获取服务列表时出错: {ex.Message}");

        }

        return serviceNames;

    }

}


// 使用示例

class Program

{

    static void Main(string[] args)

    {

        string serviceName = "Winmgmt"; // Windows 管理规范服务(通常存在的服务)

        

        // 检查服务是否安装

        bool isInstalled = ServiceHelper.IsServiceInstalled(serviceName);

        Console.WriteLine($"服务 '{serviceName}' 是否已安装: {isInstalled}");

        

        // 检查不存在的服务

        string nonExisting = "MyFakeService123";

        bool notInstalled = ServiceHelper.IsServiceInstalled(nonExisting);

        Console.WriteLine($"服务 '{nonExisting}' 是否已安装: {notInstalled}");

        

        // 获取所有服务(仅显示前10个)

        Console.WriteLine("\n已安装服务列表(前10个):");

        var services = ServiceHelper.GetAllInstalledServices();

        foreach (string name in services.Take(10))

        {

            Console.WriteLine($"- {name}");

        }

    }

}

关键说明:

1、核心方法

ServiceController.GetServices()

这个方法返回本地计算机上所有 Windows 服务的数组。

2、检查服务是否存在

Array.Exists(services, s => s.ServiceName.Equals(serviceName, StringComparison.OrdinalIgnoreCase));

使用 Array.Exists 配合不区分大小写的比较来检查服务是否存在

3、错误处理

  • 方法包含 try-catch 块处理可能的异常(如访问权限不足)

  • 当服务控制管理器不可访问时返回 false

4、注意事项

  • 需要 System.ServiceProcess 程序集引用

  • 应用程序可能需要以管理员权限运行才能访问某些服务信息

  • 服务名称是系统内部名称(如 "wuauserv"),不是显示名称(如 "Windows Update")

使用场景示例:

// 在安装服务前检查是否已存在

string myService = "MyCustomService";

if (ServiceHelper.IsServiceInstalled(myService))

{

    Console.WriteLine("服务已存在,跳过安装");

}

else

{

    Console.WriteLine("服务未安装,执行安装操作");

    // 这里调用服务安装逻辑

}


// 在卸载服务前确认存在

if (ServiceHelper.IsServiceInstalled(myService))

{

    Console.WriteLine("服务存在,执行卸载");

    // 这里调用服务卸载逻辑

}

else

{

    Console.WriteLine("服务不存在,无需卸载");

}

性能考虑:

对于需要频繁检查服务状态的场景,建议缓存服务列表:

private static ServiceController[] _cachedServices;

private static DateTime _lastRefresh = DateTime.MinValue;


public static bool IsServiceInstalledCached(string serviceName, bool forceRefresh = false)

{

    try

    {

        // 每5分钟刷新一次缓存

        if (forceRefresh || _cachedServices == null || (DateTime.Now - _lastRefresh).TotalMinutes > 5)

        {

            _cachedServices = ServiceController.GetServices();

            _lastRefresh = DateTime.Now;

        }

        

        return Array.Exists(_cachedServices, 

            service => service.ServiceName.Equals(serviceName, StringComparison.OrdinalIgnoreCase));

    }

    catch (Exception ex)

    {

        Console.WriteLine($"检查服务时出错: {ex.Message}");

        return false;

    }

}

这种方法可以显著提高频繁调用的性能,同时保持数据的相对新鲜度。


该文章在 2025/6/2 18:52:24 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2025 ClickSun All Rights Reserved