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 = "未发现服务";
    }
}

附下载源码地址:源码

相关推荐
技术不好的崎鸣同学5 小时前
第一章:PEB结构解析与内存定位
windows·安全·系统安全
江湖人称菠萝包9 小时前
【Windows】《深入浅出Windows API程序设计:编程基础篇》笔记-Chapter1-基础知识
windows·笔记
白山编程大哥9 小时前
Java 迭代器接口详解:从 Iterator 到 ListIterator 的完整指南
java·开发语言·windows
一叶龙洲10 小时前
Ubuntu从图标到卸载应用
linux·windows·ubuntu
江湖人称菠萝包10 小时前
【Windows】《深入浅出Windows API程序设计:编程基础篇》笔记-Chapter2-Windows窗口程序
windows·笔记
奈斯先生Vector11 小时前
AIGC 视频生成实战:用 Kling Video 拆解文生视频、图生视频与完整工作流
开发语言·人工智能·windows·python·aigc·音视频
暖焰核心12 小时前
迭代器与模板的结合——stl的list
c++·windows·list
2401_8616786212 小时前
Git 在 Windows 使用
windows·git·elasticsearch
en.en..15 小时前
LVGL 普通函数指针与结构体函数指针原理
linux·windows·microsoft
今夕资源网15 小时前
Windows 本地 HTTPS 配置教程:使用 CertTool 创建自签名证书并部署到宝塔
windows·网络协议·https