Nssm打包.netcore控制台程序到Windows服务,实现长Ping服务器

需求:应客户需求,现场服务器和客户端之间网络总是不稳定。导致客户端总是和服务器断开连接。为了监测网络,且为了不容易让用户误操作停止监测,所以采用控制台程序打包成windows服务的方式实现。并且加一个winform程序,让客户安装卸载此服务。

实现不间断ping服务器IP,并记录日志
csharp 复制代码
public async Task StartAsync()
{
    Serilog.Log.Information($"Service Started");
    List<string> addressesToPing = _configuration.GetSection("Ips").Get<List<string>>();
    await Task.WhenAll(addressesToPing.Select(PingAddressAsync));
}
public void Stop()
{
    Serilog.Log.Information($"Service Stoped");
}

private async Task PingAddressAsync(string address)
{
    using var ping = new System.Net.NetworkInformation.Ping();
    while (true)
    {
        try
        {
            Serilog.Log.Information($"Pinging {address}... ");
            var reply = await ping.SendPingAsync(address);

            if (reply.Status == IPStatus.Success)
            {
                Serilog.Log.Information($"来自 {reply.Address} 的回复: 时间={reply.RoundtripTime}ms TTL={reply.Options.Ttl}");
            }
            else
            {
                Serilog.Log.Information($"Ping {address} : {reply.Status}");
            }

            // 为了控制输出频率和资源占用,添加短暂停顿
            await Task.Delay(700); // 每秒发送一次
        }
        catch (System.Exception ex)
        {
            Serilog.Log.Error($"异常:{ex.Message}");
        }
    }
}
Winform程序使用Nssm安装windows服务

也是用了topshelf,但是在使用中发现了一些问题没有解决,顾采用Nssm。

csharp 复制代码
/// <summary>
/// 安装服务
/// </summary>
private void InstallService()
{

    List<string> cmdArray = new List<string>();
    var cmd = $@"{nssm} install {ServiceName} {CurrentDirectory}Ping.exe";
    //::执行安装服务指令5008
    cmdArray.Add(cmd);
    //::监控日志
    cmd = $@"{nssm} set {ServiceName} AppStdout {CurrentDirectory}nssm.log";
    cmdArray.Add(cmd);
    cmd = $@"{nssm} set {ServiceName} AppStderr {CurrentDirectory}nssm.log";
    cmdArray.Add(cmd);
    //::详情Tab(例如:服务的描述信息)
    cmd = $@"{nssm} set {ServiceName} DisplayName {ServiceName}";
    cmdArray.Add(cmd);
    cmd = $@"{nssm} set {ServiceName} Description {Description}";
    cmdArray.Add(cmd);
    cmd = $@"{nssm} set {ServiceName} Start SERVICE_AUTO_START";
    cmdArray.Add(cmd);
    //::安装完成后,启动前的服务状态
    cmd = $@"{nssm} status {ServiceName}";
    cmdArray.Add(cmd);
    cmd = $@"{nssm} start {ServiceName}";
    cmdArray.Add(cmd);
    //::启动服务后的服务状态
    cmd = $@"{nssm} status {ServiceName}";
    cmdArray.Add(cmd);
    ExcuteDosCommand(cmdArray);
}

/// <summary>
/// 执行cmd命令
/// </summary>
/// <param name="cmdArray"></param>
private void ExcuteDosCommand(List<string> cmdArray)
{
    Process p = new Process();
    p.StartInfo.FileName = "cmd";
    p.StartInfo.UseShellExecute = false;
    p.StartInfo.RedirectStandardInput = true;
    p.StartInfo.RedirectStandardOutput = true;
    p.StartInfo.RedirectStandardError = true;
    p.StartInfo.CreateNoWindow = false;
    p.OutputDataReceived += new DataReceivedEventHandler(sortProcess_OutputDataReceived);
    p.ErrorDataReceived += sortProcess_OutputDataReceived;
    try
    {
        p.Start();
        using (StreamWriter cmdWriter = p.StandardInput)
        {
            p.BeginOutputReadLine();
            p.BeginErrorReadLine();
            foreach (var cmd in cmdArray)
            {
                p.StandardInput.WriteLine(cmd);
            }
        }
        p.WaitForExit();
        //if (p.ExitCode == 0)
        //{
        //    MessageBox.Show("操作成功。");
        //}
        //else
        //{
        //    MessageBox.Show($"服务安装失败 with exit code {p.ExitCode}.");
        //}
    }
    catch (Exception ex)
    {
        MessageBox.Show("执行命令失败,请检查输入的命令是否正确!");
    }
    finally
    {

        p.Close();
    }
}

private void sortProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
    if (!String.IsNullOrEmpty(e.Data))
    {
        this.BeginInvoke(new Action(() =>
        {
            richTextBox1.AppendText(e.Data + Environment.NewLine);
        }));
    }
}

/// <summary>
/// 刷新服务列表
/// </summary>
private void RefWindowsServices()
{
    // 获取系统服务列表
    ServiceController[] services = ServiceController.GetServices();
    var service = services.FirstOrDefault(t => t.ServiceName == ServiceName);
    if (service != null)
    {
        this.label1.Text = "服务状态:" + service.Status.ToString();
    }
    else
    {
        this.label1.Text = "未发现服务";
    }
}

附下载源码地址:源码

相关推荐
斜月三4 小时前
windows部署多实例filebeat监控相同路径下文件
windows·filebeat
尽兴-8 小时前
如何将多个.sql文件合并成一个:Windows和Linux/Mac详细指南
linux·数据库·windows·sql·macos
chilavert31811 小时前
技术演进中的开发沉思-30 MFC系列:五大机制
c++·windows
荔枝吻1 天前
【保姆级喂饭教程】Windows下安装Git Flow
windows·git·git flow
深盾科技1 天前
深入解析 .NET 泛型:从原理到实战优化
windows·.net
石头wang1 天前
如何在idea里快速地切换Windows CMD、git bash、powershell
windows·git·bash·intellij-idea
天高云淡ylz2 天前
各类电子设备镜像格式及文件系统统计
linux·windows·risc-v
LCG元2 天前
Windows实时内核驱动的数据捕获接口:高精度时钟与零拷贝的架构剖析
windows·架构
行者游学2 天前
windows grpcurl
windows
goxingman2 天前
Spring Data JPA基本方法调用规律
windows