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

附下载源码地址:源码

相关推荐
EnCi Zheng1 天前
SpringBoot + PostgreSQL 密码认证失败 Windows 系统解决方案
windows·spring boot·postgresql
Damon小智1 天前
玩转CodeX:CodeX安装教程(Windows+Linux+MacOS)
linux·windows·macos·ai·ai编程·codex·gpt-5
用户31187945592181 天前
DOpusInstall-13.2.exe 安装方法,简单几步完成
windows
张某人的胡思乱想1 天前
Create/Assemble/Link x64 Windows
windows
ThisIsMirror1 天前
CompletableFuture并行任务超时处理模板
java·windows·python
say_fall1 天前
精通C语言(2.结构体)(内含彩虹)
c语言·开发语言·windows
长源Gingko1 天前
Windows中在QTCreator中调试,提示缺少debug information files问题的解决
windows·qt
white-persist1 天前
MCP协议深度解析:AI时代的通用连接器
网络·人工智能·windows·爬虫·python·自动化
影子24011 天前
Windows Server2016 服务器安装JDK,一直卡在“应用程序正在为首次使用作准备,请稍候” ,导致jdk安装失败解决方案
运维·服务器·windows·jdk
wan5555cn1 天前
Windows 11系统鼠标键盘被禁用问题的全面解决方案
windows·笔记·深度学习·计算机外设