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 小时前
ubuntu+windows双系统切换后蓝牙设备无法连接
windows·ubuntu
九鼎科技-Leo9 小时前
什么是 WPF 中的依赖属性?有什么作用?
windows·c#·.net·wpf
Yang.9911 小时前
基于Windows系统用C++做一个点名工具
c++·windows·sql·visual studio code·sqlite3
我不瘦但很逗12 小时前
Windows下使用DBeaver连接云数据库(MySQL)
数据库·windows
ashane131413 小时前
Java list
java·windows·list
万里沧海寄云帆13 小时前
Word 插入分节符页码更新问题
windows·microsoft·word
dot.Net安全矩阵14 小时前
.NET 通过模块和驱动收集本地EDR的工具
windows·安全·web安全·.net·交互
编程修仙16 小时前
Collections工具类
linux·windows·python
程序员小羊!17 小时前
高级 SQL 技巧讲解
windows
xiangshangdemayi19 小时前
Windows环境GeoServer打包Docker极速入门
windows·docker·容器·geoserver·打包·数据挂载