开发 Windows 服务应用

Posted bosaidongmomo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了开发 Windows 服务应用相关的知识,希望对你有一定的参考价值。

前言

不要用sc create 来创建windows服务了。
正经windows的安装参考msdn doc
开发 Windows 服务应用

window服务的制作教程

在Visual Studio 2015 中选择下列工程文件并创建.

会生成如下页面.

绿色部分负责安装服务,红色部分负责编写代码.
在绿色部分点属性,可以修改服务名称.

将其修改为 Account LocalSystem

https://docs.microsoft.com/zh-cn/dotnet/framework/windows-services/how-to-install-and-uninstall-services

对于 32 位版的 .NET Framework 4 或 4.5 以及更高版本,如果 Windows 安装目录是 C: \\ Windows,则默认路径是 C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\ InstallUtil.exe 。
对于 64 位版的 .NET Framework 4 或 4.5 以及更高版本,默认路径是 C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\InstallUtil.exe。
cd C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319
installUtil "c:\\users\\administrator\\documents\\visual studio 2015\\Projects\\MyService\\MyService\\bin\\Debug\\MyService.exe"

安装

Microsoft (R) .NET Framework 安装实用工具版本 4.8.4084.0
版权所有 (C) Microsoft Corporation。保留所有权利。


正在运行事务处理安装。

正在开始安装的“安装”阶段。
查看日志文件的内容以获得 c:\\users\\administrator\\documents\\visual studio 2015\\Projects\\MyService\\MyService\\bin\\Debug\\MyService.exe 程序集的进度。
该文件位于 c:\\users\\administrator\\documents\\visual studio 2015\\Projects\\MyService\\MyService\\bin\\Debug\\MyService.InstallLog。
正在安装程序集“c:\\users\\administrator\\documents\\visual studio 2015\\Projects\\MyService\\MyService\\bin\\Debug\\MyService.exe”。
受影响的参数是:
   logtoconsole =
   logfile = c:\\users\\administrator\\documents\\visual studio 2015\\Projects\\MyService\\MyService\\bin\\Debug\\MyService.InstallLog
   assemblypath = c:\\users\\administrator\\documents\\visual studio 2015\\Projects\\MyService\\MyService\\bin\\Debug\\MyService.exe
正在安装服务 Service1...
已成功安装服务 Service1。
正在日志 Application 中创建 EventLog 源 Service1...

“安装”阶段已成功完成,正在开始“提交”阶段。
查看日志文件的内容以获得 c:\\users\\administrator\\documents\\visual studio 2015\\Projects\\MyService\\MyService\\bin\\Debug\\MyService.exe 程序集的进度。
该文件位于 c:\\users\\administrator\\documents\\visual studio 2015\\Projects\\MyService\\MyService\\bin\\Debug\\MyService.InstallLog。
正在提交程序集“c:\\users\\administrator\\documents\\visual studio 2015\\Projects\\MyService\\MyService\\bin\\Debug\\MyService.exe”。
受影响的参数是:
   logtoconsole =
   logfile = c:\\users\\administrator\\documents\\visual studio 2015\\Projects\\MyService\\MyService\\bin\\Debug\\MyService.InstallLog
   assemblypath = c:\\users\\administrator\\documents\\visual studio 2015\\Projects\\MyService\\MyService\\bin\\Debug\\MyService.exe

“提交”阶段已成功完成。

已完成事务处理安装。

C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319>

然后net start [服务名]就好啦。

WriteLog 日志编写

private static void WriteLog(string text)
        
            string logPath = runtimePath + "WatchDog_" + DateTime.Now.ToString("yyyy-MM-dd") + ".log";

            StreamWriter streamWriter = new StreamWriter(logPath, true);

            streamWriter.WriteLine(text);
            //刷新缓存
            streamWriter.Flush();
            //关闭流
            streamWriter.Close();
        

ListenToStart

var list = Process.GetProcesses().ToList();
var nginx = list.Where(n => n.ProcessName.Contains("nginx")).ToList().Count;

获取进程中是否存在,如果不存在就重启。
整体代码如下。
由于windowsService不怎么好调试、建议写控制台管理程序先测试一遍,再进行处理。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using System.Timers;

namespace MyWindowsService

    public partial class WatchDog : ServiceBase
    
        public static string runtimePath = AppDomain.CurrentDomain.BaseDirectory;
        public WatchDog()
        
            InitializeComponent();
        
        private static void WriteLog(string text)
        
            string logPath = runtimePath + "WatchDog_" + DateTime.Now.ToString("yyyy-MM-dd") + ".log";

            StreamWriter streamWriter = new StreamWriter(logPath, true);

            streamWriter.WriteLine(text);
            //刷新缓存
            streamWriter.Flush();
            //关闭流
            streamWriter.Close();
        
        public static void ListenToStart(object source, ElapsedEventArgs e)
        
            string logPath = runtimePath + "WatchDog_" + DateTime.Now.ToString("yyyy-MM-dd") + ".log";

            var list = Process.GetProcesses().ToList();
            var nginx = list.Where(n => n.ProcessName.Contains("nginx")).ToList().Count;
            // 如果nginx 在进程中存在
            if (nginx > 0)
            
                // 什么都不做
            
            else
            
                // 否则
                // 启动进程
                Process process = new Process();
                process.StartInfo.FileName = runtimePath + "StartNginx.bat";
                process.StartInfo.Arguments = "";
                WriteLog(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ",nginx服务重启");
                process.Start();
            
            var redis = list.Where(n => n.ProcessName.Contains("redis-server")).ToList().Count;
            // 如果redis 在进程中存在
            if (redis > 0)
            
                // 什么都不做
            
            else
            
                // 否则
                // 启动进程
                Process process = new Process();
                process.StartInfo.FileName = runtimePath + "StartRedis.bat";
                process.StartInfo.Arguments = "";
                WriteLog(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ",redis服务重启");
                process.Start();
            
            var java = 0;
            Process p = new Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardInput = true;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.CreateNoWindow = true;
            p.Start();
            //查看本机端口占用情况
            p.StandardInput.WriteLine("netstat -an| findstr -i \\":8088\\" | findstr -i \\"LISTENING\\"");
            p.StandardInput.WriteLine("exit");
            //
            StreamReader reader = p.StandardOutput;//截取输出流
            string strLine = reader.ReadLine();//每次读取一行
            while (!reader.EndOfStream)
            
                // strAllInfo += strLine + "\\r\\n";
                strLine = reader.ReadLine();
                if (strLine.Contains("TCP") || strLine.Contains("UDP"))
                    java = 1;
            
            // 如果mysql 在进程中存在
            if (java > 0)
            
                // 什么都不做
            
            else
            
                // 否则
                // 启动进程
                Process process = new Process();
                process.StartInfo.FileName = runtimePath + "StartJava.bat";
                process.StartInfo.Arguments = "";
                WriteLog(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ",java服务重启");
                process.Start();
            
        
        protected override void OnStart(string[] args)
        
            System.Timers.Timer timer = new System.Timers.Timer();
            timer.Enabled = true;
            timer.Interval = 60000; //执行间隔时间,单位为毫秒; 这里实际间隔为1分钟  
            timer.Start();
            timer.Elapsed += new System.Timers.ElapsedEventHandler(ListenToStart); 
        

        protected override void OnStop()
        
            Process p = new Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardInput = true;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.CreateNoWindow = true;
            p.Start();
            //查看本机端口占用情况
            p.StandardInput.WriteLine("netstat -ano | findstr 8088");
            p.StandardInput.WriteLine("exit");
            //
            StreamReader reader = p.StandardOutput;//截取输出流
            string strLine = reader.ReadLine();//每次读取一行
            while (!reader.EndOfStream)
            
                strLine = reader.ReadLine();
                if (strLine.Contains("TCP") || strLine.Contains("UDP"))
                
                    string[] ee = strLine.Split(' ');
                    string port = ee.LastOrDefault();
                    Process pr = new Process();
                    pr.StartInfo.FileName = "cmd.exe";
                    pr.StartInfo.UseShellExecute = false;
                    pr.StartInfo.RedirectStandardInput = true;
                    pr.StartInfo.RedirectStandardOutput = true;
                    pr.StartInfo.RedirectStandardError = true;
                    pr.StartInfo.CreateNoWindow = true;
                    pr.Start();
                    //查看本机端口占用情况 杀死进程
                    pr.StandardInput.WriteLine("taskkill /pid " + port + " -t -f");
                    pr.StandardInput.WriteLine("exit");
                
                    
            
        
    


以上是关于开发 Windows 服务应用的主要内容,如果未能解决你的问题,请参考以下文章

Windows 服务开发 以及 重启IIS应用池

ASP.NET MVC 中应用Windows服务以及Webservice服务开发分布式定时器

适用于 Windows 8.1 应用商店应用的蓝牙低功耗服装服务设备发现和开发

如何将 elixir 应用程序从 Windows 开发机器部署到 Ubuntu 服务器

开发一个简单的Windows系统托盘桌面应用程序来使用.NET Web服务

如何从另一个桌面应用程序控制 Windows 服务