.NET进程守护服务

一、新建一个Windows服务项目,取名ProcessDaemonServiceTest

用到是.NET Framework 4的框架 

.NET进程守护服务_第1张图片

新建后的样式:

.NET进程守护服务_第2张图片 二、右击Service1.cs文件查看代码

.NET进程守护服务_第3张图片

三、添加应用程序配置文件App.config,在文件里增加如下配置

.NET进程守护服务_第4张图片



  
    
  
  
    
    
    
  

 四、在Service1.cs代码文件中引入【Cjwdev.WindowsApi】程序集

using Cjwdev.WindowsApi;

五、编写服务

1、在构造函数里处理配置消息,读取配置的路径

//存放路径的数组
private static string[] appStartPath = new string[] { };
NameValueCollection appsettings = ConfigurationManager.AppSettings;
string[] names = ConfigurationManager.AppSettings.AllKeys;

public Service1()
{
    List asp = appStartPath.ToList();
    for (int i = 0; i < appsettings.Count; i++)
    {
        string key = names[i];
        if (key.Contains("Path"))
        {
            string path = ConfigurationManager.AppSettings[key];
            asp.Add(path);
        }
    }
    appStartPath = asp.ToArray();

    InitializeComponent();
}

2、编写打开exe程序的事件方法

private void OpenExe(object sender, System.Timers.ElapsedEventArgs e)
{
    //句柄
    IntPtr userTokenHandle = IntPtr.Zero;
    ApiDefinitions.WTSQueryUserToken(ApiDefinitions.WTSGetActiveConsoleSessionId(), ref userTokenHandle);

    ApiDefinitions.PROCESS_INFORMATION procInfo = new ApiDefinitions.PROCESS_INFORMATION();
    ApiDefinitions.STARTUPINFO startInfo = new ApiDefinitions.STARTUPINFO();
    startInfo.cb = (uint)System.Runtime.InteropServices.Marshal.SizeOf(startInfo);

    //使用循环,校验程序是否以及打开(exe程序名与进程名需要一致),如果未打开则调用方法CreateProcessAsUser打开
    for (int i = 0; i < appStartPath.Length; i++)
    {
        string appName = appStartPath[i].Split('\\')[appStartPath[i].Split('\\').Length - 1].Split('.')[0];
        //是否打开的标志位
        bool runFlag = false;
        Process[] myProcesses = Process.GetProcesses();
        //进程名是否存在
        foreach (Process myProcess in myProcesses)
        {
            if (myProcess.ProcessName.CompareTo(appName) == 0)
            {
                runFlag = true;
            }
        }
        if (!runFlag)
        {
            ApiDefinitions.CreateProcessAsUser(
                userTokenHandle,//句柄
                appStartPath[i],//路径
                "",//命令
                IntPtr.Zero,
                IntPtr.Zero,
                false,
                0,
                IntPtr.Zero,
                null,
                ref startInfo,
                out procInfo);
        }
    }
    if (userTokenHandle != IntPtr.Zero)
        //关闭句柄
        ApiDefinitions.CloseHandle(userTokenHandle);
}

3、在OnStart方法中创建Timer定时器,添加事件,调用OpenExe方法,并启动

protected override void OnStart(string[] args)
{
    //定时器
    System.Timers.Timer timer;

    timer = new System.Timers.Timer();
    //设置计时器事件间隔执行时间
    timer.Interval = Convert.ToInt32(ConfigurationManager.AppSettings["Time"]);
    //添加绑定事件,达到间隔时发生
    timer.Elapsed += new System.Timers.ElapsedEventHandler(OpenExe);
    //启动定时器
    timer.Enabled = true;
}

Service1.cs完整代码:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using Cjwdev.WindowsApi;
using System.Configuration;
using System.Collections.Specialized;

namespace ProcessDaemonServiceTest
{
    public partial class Service1 : ServiceBase
    {
        private static string[] appStartPath = new string[] { };
        NameValueCollection appsettings = ConfigurationManager.AppSettings;
        string[] names = ConfigurationManager.AppSettings.AllKeys;
        //定时器
        System.Timers.Timer timer = new System.Timers.Timer();

        public Service1()
        {
            List asp = appStartPath.ToList();
            for (int i = 0; i < appsettings.Count; i++)
            {
                string key = names[i];
                if (key.Contains("Path"))
                {
                    string path = ConfigurationManager.AppSettings[key];
                    asp.Add(path);
                }
            }
            appStartPath = asp.ToArray();

            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            //设置计时器事件间隔执行时间
            timer.Interval = Convert.ToInt32(ConfigurationManager.AppSettings["Time"]);
            //添加绑定事件,达到间隔时发生
            timer.Elapsed += new System.Timers.ElapsedEventHandler(OpenExe);
            //启动定时器
            timer.Enabled = true;
        }

        protected override void OnStop()
        {
            timer.Enabled = false;
        }

        private void OpenExe(object sender, System.Timers.ElapsedEventArgs e)
        {
            //句柄
            IntPtr userTokenHandle = IntPtr.Zero;
            ApiDefinitions.WTSQueryUserToken(ApiDefinitions.WTSGetActiveConsoleSessionId(), ref userTokenHandle);

            ApiDefinitions.PROCESS_INFORMATION procInfo = new ApiDefinitions.PROCESS_INFORMATION();
            ApiDefinitions.STARTUPINFO startInfo = new ApiDefinitions.STARTUPINFO();
            startInfo.cb = (uint)System.Runtime.InteropServices.Marshal.SizeOf(startInfo);

            //使用循环,校验程序是否以及打开(exe程序名与进程名需要一致),如果未打开则调用方法CreateProcessAsUser打开
            for (int i = 0; i < appStartPath.Length; i++)
            {
                string appName = appStartPath[i].Split('\\')[appStartPath[i].Split('\\').Length - 1].Split('.')[0];
                //是否打开的标志位
                bool runFlag = false;
                Process[] myProcesses = Process.GetProcesses();
                //进程名是否存在
                foreach (Process myProcess in myProcesses)
                {
                    if (myProcess.ProcessName.CompareTo(appName) == 0)
                    {
                        runFlag = true;
                    }
                }
                if (!runFlag)
                {
                    ApiDefinitions.CreateProcessAsUser(
                        userTokenHandle,//句柄
                        appStartPath[i],//路径
                        "",//命令
                        IntPtr.Zero,
                        IntPtr.Zero,
                        false,
                        0,
                        IntPtr.Zero,
                        null,
                        ref startInfo,
                        out procInfo);
                }
            }
            if (userTokenHandle != IntPtr.Zero)
                ApiDefinitions.CloseHandle(userTokenHandle);
        }
    }
}

Program.cs程序入口:

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;

namespace ProcessDaemonServiceTest
{
    static class Program
    {
        /// 
        /// 应用程序的主入口点。
        /// 
        static void Main()
        {
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[]
            {
                new Service1()
            };
            ServiceBase.Run(ServicesToRun);
        }
    }
}

六、为服务添加安装程序

点击Service1.cs,在左侧界面内右击,选择“添加安装程序”

.NET进程守护服务_第5张图片

会生成ProjectInstaller.cs文件,同时生产serviceProcessInstaller1和serviceInstaller1两个组件

.NET进程守护服务_第6张图片

1、设置serviceInstaller1组件的属性,右击它选择属性

.NET进程守护服务_第7张图片

默认属性如下:

 .NET进程守护服务_第8张图片

其中:

        Name:表示控件的名称

        Description:是安装后的描述

        DisplayName:显示的名称

        ServiceName: 指示系统用于标识此服务的名称。此属性必须与要安装的服务的 ServiceBase.ServiceName 相同

        StartType:表示服务的启动方式。默认为 Manual,指定在重新启动后服务将不会自动启动。Automatic:自动启动。Disabled:禁用

设置 StartType 来指定该服务是在重新启动后自动启动,还是必须由用户手动启动。服务还可以被禁用,指定在启用以前不能被手动或以编程方式启动。

 2、设置serviceProcessInstaller1的属性,右击它选择属性

.NET进程守护服务_第9张图片

.NET进程守护服务_第10张图片 

        其中:        

        Account:获取或设置运行该服务应用程序时所使用的帐户类型 

        LocalService:充当本地计算机上非特权用户的帐户,该帐户将匿名凭据提供给所有远程服务器

        NetworkService:提供广泛的本地特权的帐户,该帐户将计算机的凭据提供给所有远程服务器

        LocalSystem:服务控制管理员使用的帐户,它具有本地计算机上的许多权限并作为网络上的计算机

        User:由网络上特定的用户定义的帐户。如果为 ServiceProcessInstaller.Account 成员指定 User,则会使系统在安装服务时提示输入有效的用户名和密码,除非您为 ServiceProcessInstaller 实例的 Username 和 Password 这两个属性设置值

七、注册、启动、停止和卸载服务

使用CMD调用安装程序工具【InstallUtil.exe】注册服务,需要以管理员身份运行CMD

1、注册服务 

使用指令:InstallUtil.exe ProcessDaemonServiceTest.exe

.NET进程守护服务_第11张图片

.NET进程守护服务_第12张图片 2、启动服务

使用命令:net start 服务名

.NET进程守护服务_第13张图片 

3、 停止服务

使用命令:net stop 服务名

.NET进程守护服务_第14张图片

4、卸载服务

使用指令:InstallUtil.exe -u ProcessDaemonServiceTest.exe

.NET进程守护服务_第15张图片 

你可能感兴趣的:(.net)