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

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

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

在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