C#之服务安装记录(借助Nssm工具实现)

将exe程序做成进程服务

说明

  1. 本次使用的开发语言为C#
  2. 借助服务安装工具为nssm(C++开发的)

对Nssm进行一个简单的封装

using System.Diagnostics;
using System.Text;
using System.Threading.Channels;
using Model.Enums;

namespace Nssm;

public static class NssmExeHelper
{
    private static string NssmExeFile { get; set; }

    static NssmExeHelper()
    {
        Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
        const string baseDir = @"NssmExe";
        NssmExeFile = Path.Combine(baseDir, Environment.Is64BitOperatingSystem ? @"win64\nssm.exe" : @"win32\nssm.exe");
    }

    /// <summary>
    /// 加载自定义nssm执行程序
    /// </summary>
    /// <param name="nssmExe"></param>
    public static void LoadNssmExe(string nssmExe)
    {
        NssmExeFile = nssmExe;
    }

    private static Process Create()
    {
        var process = new Process();
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.FileName = NssmExeFile;
        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.RedirectStandardInput = true;
        process.StartInfo.RedirectStandardError = true;
        return process;
    }

    public static bool InstallService(string serviceName, string exeFile, string param = "")
    {
        if (GetServiceStatus(serviceName) != ServiceStatusEnum.NotInstalled) return false;
        var process = Create();
        process.StartInfo.Arguments = $" install {serviceName} {exeFile} {param}";
        process.Start();
        var msg = process.StandardOutput.ReadLine();
        if (string.IsNullOrEmpty(msg))
        {
            // var errorMsg = process.StandardError.ReadLine()?.Replace("\0", "");
            // throw new Exception(errorMsg);
            return false;
        }

        Console.WriteLine(msg.Replace("\0", ""));
        process.Close();
        return true;
    }

    public static void RemoveService(string serviceName)
    {
        var process = Create();
        process.StartInfo.Arguments = $" remove {serviceName} confirm";
        process.Start();
        var msg = process.StandardOutput.ReadLine();
        if (string.IsNullOrEmpty(msg))
        {
            var errorMsg = process.StandardError.ReadLine()?.Replace("\0", "");
            throw new Exception(errorMsg);
        }

        Console.WriteLine(msg.Replace("\0", ""));
        process.Close();
    }

    /// <summary>
    /// 启动服务
    /// </summary>
    /// <param name="serviceName"></param>
    /// <param name="errMsg"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    public static bool StartService(string serviceName, out string errMsg)
    {
        errMsg = string.Empty;
        var status = GetServiceStatus(serviceName);
        if (status == ServiceStatusEnum.NotInstalled) throw new Exception("服务未安装");
        if (status == ServiceStatusEnum.Stopped)
        {
            return ServiceHandle("start", serviceName, out errMsg);
        }

        if (status == ServiceStatusEnum.Running)
        {
            return true;
        }

        errMsg = $"当前服务状态未停止:{status}";
        return false;
    }

    /// <summary>
    /// 停止服务
    /// </summary>
    /// <param name="serviceName"></param>
    /// <param name="errMsg"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    public static bool StopService(string serviceName, out string errMsg)
    {
        errMsg = string.Empty;
        var status = GetServiceStatus(serviceName);
        if (status == ServiceStatusEnum.NotInstalled) throw new Exception("服务未安装");
        if (status == ServiceStatusEnum.Running)
        {
            return ServiceHandle("stop", serviceName, out errMsg);
        }

        if (status == ServiceStatusEnum.Stopped)
        {
            return true;
        }

        errMsg = $"当前服务状态:{status}";
        return false;
    }

    /// <summary>
    /// 服务执行核心逻辑
    /// </summary>
    /// <param name="cmd"></param>
    /// <param name="serviceName"></param>
    /// <param name="resultMsg"></param>
    /// <returns></returns>
    private static bool ServiceHandle(string cmd, string serviceName, out string resultMsg)
    {
        resultMsg = string.Empty;
        var process = Create();
        process.StartInfo.Arguments = $" {cmd} {serviceName} ";
        process.Start();
        var msg = process.StandardOutput.ReadLine();
        if (string.IsNullOrEmpty(msg))
        {
            var errorMsg = process.StandardError.ReadLine()?.Replace("\0", "");
            resultMsg = errorMsg!;
            return false;
        }

        resultMsg = msg.Replace("\0", "");
        process.Close();
        return true;
    }


    /// <summary>
    /// 查看服务运行状态
    /// </summary>
    /// <param name="serviceName"></param>
    /// <param name="resultMsg"></param>
    /// <returns></returns>
    private static bool LookServiceStatus(string serviceName, out string resultMsg)
    {
        return ServiceHandle("status", serviceName, out resultMsg);
    }

    /// <summary>
    /// 获取服务状态
    /// </summary>
    /// <param name="serviceName"></param>
    /// <returns></returns>
    public static ServiceStatusEnum GetServiceStatus(string serviceName)
    {
        if (!LookServiceStatus(serviceName, out var msg)) return ServiceStatusEnum.NotInstalled;
        switch (msg.ToLower())
        {
            case "service_stopped":
                return ServiceStatusEnum.Stopped;
            case "service_running":
                return ServiceStatusEnum.Running;
            case "service_paused":
                return ServiceStatusEnum.Paused;
            default:
                return ServiceStatusEnum.UnknownError;
        }
    }

    /// <summary>
    /// 设置服务的控制台输入重定向到文件
    /// </summary>
    /// <param name="serviceName"></param>
    /// <param name="stdOutLog"></param>
    /// <param name="stdErrLog"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    public static bool SetServiceOutLog(string serviceName, string stdOutLog, string stdErrLog)
    {
        var status = GetServiceStatus(serviceName);
        if (status == ServiceStatusEnum.NotInstalled) throw new Exception("服务未安装");
        var process = Create();
        process.StartInfo.Arguments = $" set {serviceName} AppStdout  {stdOutLog} ";
        process.Start();
        process.StartInfo.Arguments = $" set {serviceName} AppStderr {stdErrLog}";
        process.Start();
        process.Close();
        return true;
    }


}

服务状态的枚举类

/// <summary>
/// 服务状态枚举
/// </summary>
public enum ServiceStatusEnum : byte
{
    UnknownError,
    NotInstalled,
    Stopped,
    Running,
    Paused,
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

詩不诉卿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值