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

附下载源码地址:源码

相关推荐
sukalot3 小时前
Windows 图形显示驱动开发-WDDM 2.4功能-GPU 半虚拟化(三)
windows·驱动开发
全栈小55 小时前
【C#】.net core 6.0 依赖注入常见问题之一,在构造函数使用的类,都需要注入到容器里,否则会提示如下报错,让DeepSeek找找原因,看看效果
c#·.netcore·依赖注入·deepseek
云徒川17 小时前
【设计模式】过滤器模式
windows·python·设计模式
virelin_Y.lin18 小时前
系统与网络安全------Windows系统安全(4)
windows·web安全·系统安全·账号安全
学也不会20 小时前
d202541
windows
厦门德仔21 小时前
【C#】C#字符串拼接的6种方式及其性能分析对比
服务器·windows·c#
网络探索者1 天前
DirectX修复工具(DirectX Repair)官网免费下载
windows
心灵宝贝1 天前
SQLyog一款被遗忘的MySQL管理利器深度解析
windows
Doris Liu.1 天前
如何检测代码注入(Part 2)
windows·python·安全·网络安全·网络攻击模型
bjxiaxueliang1 天前
一文详解QT环境搭建:Windows使用CLion配置QT开发环境
开发语言·windows·qt