C# 控制创建的windows服务(安装、卸载、启动、停止)

功能描述:实时从数据库获取数据做相关处理

步骤:

1 创建服务;

2 创建控制服务应用程序;

 

一:创建服务

1   新建-Windows Service,出现如图

2  右键-添加安装程序

出现

分别设置相关服务信息略

3 编写服务相关代码,Service1.cs类,此处实现每隔10分钟从数据库读取数据进行逻辑处理

public partial class Service1 : ServiceBase
    {
        System.Timers.Timer t = null;
        
        public Service1()
        {
            t = new System.Timers.Timer(10*60*1000);
            t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed);
            InitializeComponent();
        }

        void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            //获取学员
            //模拟数据
            for(int i=0;i<1000;i++)
            {
                 ///
                Thread.Sleep(5000);
            }
        }

        protected override void OnStart(string[] args)
        {
            t.Start();
        }

        protected override void OnStop()
        {
            t.Stop();
            t.Dispose();
        }
    }

4 安装服务

    4-1 此处通过vs 工具命令行InstallUtil 服务路径/xxx.exe、InstallUtil /u 服务路径/xxx.exe分别进行安装、卸载

     问题:太过繁琐,安装客户端麻烦(可以通过新建安装包进行安装卸载服务,但如果更改服务代码需要安装卸麻烦)

    4-2 通过打包安装程序进行安装卸载服务:

     问题:有时候某些原因卸载不彻底,如果改动服务代码太繁琐

二  控制服务程序

1 解决方案如图

  分别对应:SendMsgService:服务、ServiceControl服务控制应用程序、ServiceManager服务帮助类

一处模拟实时获取数据,此处通过配置文件,可以进行包括时间间隔、数据库配置等更改

2 详细

  ServiceManager服务帮助类

  

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceProcess;
using System.Runtime.InteropServices;
using System.Collections.Specialized;
using System.IO;

namespace ServiceManager
{
    public class IniHelper
    {
        public string FileName; //INI文件名

        //声明读写INI文件的API函数
        [DllImport("kernel32")]
        private static extern bool WritePrivateProfileString(string section, string key, string val, string filePath);
        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section, string key, string def, byte[] retVal, int size, string filePath);

        //类的构造函数,传递INI文件名
        public IniHelper(string iniFileName)
        {
            // 判断文件是否存在
            FileInfo fileInfo = new FileInfo(iniFileName);
            if ((!fileInfo.Exists))
            {
                fileInfo.Create();
            }

            //必须是完全路径,不能是相对路径
            FileName = fileInfo.FullName;
        }

        //写INI文件
        public void WriteString(string Section, string Ident, string Value)
        {
            if (!WritePrivateProfileString(Section, Ident, Value, FileName))
            {
                throw (new ApplicationException("写Ini文件出错"));
            }
        }

        //读取INI文件指定
        public string GetString(string Section, string Ident, string Default)
        {
            Byte[] Buffer = new Byte[65535];
            int bufLen = GetPrivateProfileString(Section, Ident, Default, Buffer, Buffer.GetUpperBound(0), FileName);
            //必须设定0(系统默认的代码页)的编码方式,否则无法支持中文
            string s = Encoding.GetEncoding(0).GetString(Buffer);
            s = s.Substring(0, bufLen);
            return s.Trim();
        }

        //读整数
        public int GetInteger(string Section, string Ident, int Default)
        {
            string intStr = GetString(Section, Ident, Convert.ToString(Default));
            try
            {
                return Convert.ToInt32(intStr);
            }
            catch
            {
                return Default;
            }
        }

        //写整数
        public void WriteInteger(string Section, string Ident, int Value)
        {
            WriteString(Section, Ident, Value.ToString());
        }

        //读布尔
        public bool GetBool(string Section, string Ident, bool Default)
        {
            try
            {
                return Convert.ToBoolean(GetString(Section, Ident, Convert.ToString(Default)));
            }
            catch
            {
                return Default;
            }
        }

        //写Bool
        public void WriteBool(string Section, string Ident, bool Value)
        {
            WriteString(Section, Ident, Convert.ToString(Value));
        }

        //从Ini文件中,将指定的Section名称中的所有Ident添加到列表中
        public void GetSection(string Section, StringCollection Idents)
        {
            Byte[] Buffer = new Byte[16384];

            int bufLen = GetPrivateProfileString(Section, null, null, Buffer, Buffer.GetUpperBound(0), FileName);
            //对Section进行解析
            GetStringsFromBuffer(Buffer, bufLen, Idents);
        }

        private void GetStringsFromBuffer(Byte[] Buffer, int bufLen, StringCollection Strings)
        {
            Strings.Clear();
            if (bufLen != 0)
            {
                int start = 0;
                for (int i = 0; i < bufLen; i++)
                {
                    if ((Buffer[i] == 0) && ((i - start) > 0))
                    {
                        String s = Encoding.GetEncoding(0).GetString(Buffer, start, i - start);
                        Strings.Add(s);
                        start = i + 1;
                    }
                }
            }
        }

        //从Ini文件中,读取所有的Sections的名称
        public void GetSections(StringCollection SectionList)
        {
            //Note:必须得用Bytes来实现,StringBuilder只能取到第一个Section
            byte[] Buffer = new byte[65535];
            int bufLen = 0;
            bufLen = GetPrivateProfileString(null, null, null, Buffer,
            Buffer.GetUpperBound(0), FileName);
            GetStringsFromBuffer(Buffer, bufLen, SectionList);
        }

        //读取指定的Section的所有Value到列表中
        public void GetSectionValues(string Section, NameValueCollection Values)
        {
            StringCollection KeyList = new StringCollection();
            GetSection(Section, KeyList);
            Values.Clear();
            foreach (string key in KeyList)
            {
                Values.Add(key, GetString(Section, key, ""));
            }
        }

        //清除某个Section
        public void EraseSection(string Section)
        {
            if (!WritePrivateProfileString(Section, null, null, FileName))
            {
                throw (new ApplicationException("无法清除Ini文件中的Section"));
            }
        }

        //删除某个Section下的键
        public void DeleteKey(string Section, string Ident)
        {
            WritePrivateProfileString(Section, Ident, null, FileName);
        }

        //检查某个Section下的某个键值是否存在
        public bool ValueExists(string Section, string Ident)
        {
            StringCollection Idents = new StringCollection();
            GetSection(Section, Idents);
            return Idents.IndexOf(Ident) > -1;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.ServiceProcess;

namespace ServiceManager
{
    public class ServiceHelper
    {
        #region DLLImport
        [DllImport("advapi32.dll")]
        public static extern IntPtr OpenSCManager(string lpMachineName, string lpSCDB, int scParameter);
        [DllImport("Advapi32.dll")]
        public static extern IntPtr CreateService(IntPtr SC_HANDLE, string lpSvcName, string lpDisplayName,
        int dwDesiredAccess, int dwServiceType, int dwStartType, int dwErrorControl, string lpPathName,
        string lpLoadOrderGroup, int lpdwTagId, string lpDependencies, string lpServiceStartName, string lpPassword);
        [DllImport("advapi32.dll")]
        public static extern void CloseServiceHandle(IntPtr SCHANDLE);
        [DllImport("advapi32.dll")]
        public static extern int StartService(IntPtr SVHANDLE, int dwNumServiceArgs, string lpServiceArgVectors);
        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern IntPtr OpenService(IntPtr SCHANDLE, string lpSvcName, int dwNumServiceArgs);
        [DllImport("advapi32.dll")]
        public static extern int DeleteService(IntPtr SVHANDLE);
        [DllImport("kernel32.dll")]
        public static extern int GetLastError();
        #endregion DLLImport


        //服务名称
        private string sname;
        //服务程序绝对路径
        private string spath;

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="serviceName">服务名称</param>
        /// <param name="serviceFilePath">服务程序绝对路径</param>
        public ServiceHelper(string serviceName, string serviceFilePath)
        {
            this.sname = serviceName;
            this.spath = serviceFilePath;
        }

        /// <summary>
        /// 服务是否已安装
        /// </summary>
        /// <returns></returns>
        public bool IsInstalled()
        {
            return ServiceController.GetServices().Any(x => string.Compare(x.ServiceName, sname, true) == 0);
        }

        /// <summary>
        /// 服务是否正在运行
        /// </summary>
        /// <returns></returns>
        public bool IsRunning()
        {
            if (IsInstalled())
            {
                var control = new ServiceController(sname);
                control.Refresh();
                return control.Status == ServiceControllerStatus.Running;
            }

            return false;
        }

        /// <summary>
        /// 安装服务
        /// </summary>
        /// <returns></returns>
        public void Install()
        {
            if (IsInstalled())
            {
                return;
            }

            #region Constants declaration.

            int SC_MANAGER_CREATE_SERVICE = 0x0002;
            int SERVICE_WIN32_OWN_PROCESS = 0x00000010;
            int SERVICE_ERROR_NORMAL = 0x00000001;
            int STANDARD_RIGHTS_REQUIRED = 0xF0000;
            int SERVICE_QUERY_CONFIG = 0x0001;
            int SERVICE_CHANGE_CONFIG = 0x0002;
            int SERVICE_QUERY_STATUS = 0x0004;
            int SERVICE_ENUMERATE_DEPENDENTS = 0x0008;
            int SERVICE_START = 0x0010;
            int SERVICE_STOP = 0x0020;
            int SERVICE_PAUSE_CONTINUE = 0x0040;
            int SERVICE_INTERROGATE = 0x0080;
            int SERVICE_USER_DEFINED_CONTROL = 0x0100;
            int SERVICE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG |
                SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_START | SERVICE_STOP |
                SERVICE_PAUSE_CONTINUE | SERVICE_INTERROGATE | SERVICE_USER_DEFINED_CONTROL);
            int SERVICE_AUTO_START = 0x00000002;
            #endregion Constants declaration.

            IntPtr sc_handle = OpenSCManager(null, null, SC_MANAGER_CREATE_SERVICE);
            if (sc_handle.ToInt32() != 0)
            {
                IntPtr svc_handle = CreateService(sc_handle, sname, sname,
                    SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,
                    SERVICE_ERROR_NORMAL, spath, null, 0, null, null, null);
                CloseServiceHandle(svc_handle);
            }
            CloseServiceHandle(sc_handle);
        }

        /// <summary>
        /// 卸载服务
        /// </summary>
        public void UnInstall()
        {
            if (IsInstalled())
            {
                if (IsRunning())
                {
                    this.Stop();
                }

                int GENERIC_WRITE = 0x40000000;
                IntPtr sc_hndl = OpenSCManager(null, null, GENERIC_WRITE);
                if (sc_hndl.ToInt32() != 0)
                {
                    int DELETE = 0x10000;
                    IntPtr svc_hndl = OpenService(sc_hndl, sname, DELETE);
                    if (svc_hndl.ToInt32() != 0)
                    {
                        DeleteService(svc_hndl);
                    }
                    CloseServiceHandle(svc_hndl);
                }
                CloseServiceHandle(sc_hndl);
            }
        }

        /// <summary>
        /// 启动服务
        /// </summary>
        public void Start()
        {
            if (IsRunning())
            {
                return;
            }
            try
            {
                var control = new ServiceController(sname);
                control.Start();
                control.WaitForStatus(ServiceControllerStatus.Running);
                control.Refresh();
            }
            catch (Exception ex)
            {
                
                throw;
            }
          
        }

        /// <summary>
        /// 停止服务
        /// </summary>
        public void Stop()
        {
            if (IsRunning())
            {
                var control = new ServiceController(sname);
                control.Stop();
                control.WaitForStatus(ServiceControllerStatus.Stopped);
                control.Refresh();
            }
        }
    }
}

ps:需引用dll

  SendMsgService服务

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

namespace SendMsgService
{
    public class Logger
    {
        private string logRoot = "c:\\";

        public string LogRoot
        {
            get { return logRoot; }
            set { logRoot = value; }
        }

        private object syslock = new object();

        public void WriteLog(string msg)
        {
            lock (syslock)
            {
                string filename = Path.Combine(logRoot, DateTime.Today.ToString("yyyy-MM-dd") + ".log");
                StreamWriter sw = File.AppendText(filename);
                sw.WriteLine(string.Format("{0}\t{1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), msg));
                sw.Close();
            }
        }
    }
}

 

  

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.IO;
using System.Configuration;
using System.Data.OracleClient;
using System.Threading;
using ServiceManager;

namespace SendMsgService
{
    public partial class Service1 : ServiceBase
    {
        private string Account = "";
        private string Pwd = "";
        //数据库连接字符串
        private string ConStr = "";
        private string iniFileName = "config.ini";
        private string logRoot = "c:\\";
        private Logger logger;
        System.Timers.Timer t = null;
        
        public Service1()
        {
            //获取根目录下ini配置文件
            iniFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, iniFileName);
            IniHelper ini = new IniHelper(iniFileName);
            Account = ini.GetString("SetInfo", "Account", "");
            Pwd = ini.GetString("SetInfo", "Pwd", "");
            ConStr = ini.GetString("SetInfo", "ConStr", "");
            logRoot = ini.GetString("Logger", "dir", "log");
            if (logRoot.Length > 2 && logRoot[1] != ':')
            {
                logRoot = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, logRoot);
            }
            if (!Directory.Exists(logRoot))
            {
                Directory.CreateDirectory(logRoot);
            }

            logger = new Logger();
            logger.LogRoot = logRoot;

            t = new System.Timers.Timer(Convert.ToInt32(ini.GetString("SetInfo", "TimeTick", "")));
            t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed);
            InitializeComponent();
        }

        void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
                //逻辑部分
                ///
                //日志
                logger.WriteLog("");
                logger.WriteLog("-------------------");
                Thread.Sleep(5000);
        }

        protected override void OnStart(string[] args)
        {
            t.Start();
        }

        protected override void OnStop()
        {
            t.Stop();
            t.Dispose();
        }
    }
}

  ServiceControl服务控制

  

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ServiceManager;
using System.IO;
using System.Diagnostics;

namespace ServiceControl
{
    public partial class MainForm : Form
    {
        private ServiceHelper service;
        private string iniFileName = "config.ini";
        private string logPath;

        public MainForm()
        {
            InitializeComponent();

            //初始化
            IniHelper ini = new IniHelper(iniFileName);
            //获取服务名、服务对应可执行文件即此处SendMsgService
            string sname = ini.GetString("Service_Info", "ServiceName", "Service");
            string spath = ini.GetString("Service_Info", "ServiceFilePath", "SendMsgService.exe");
            logPath = ini.GetString("Logger", "DirRoot", "log");

            FileInfo sfi = new FileInfo(spath);
            if (sfi.Exists)
            {
                service = new ServiceHelper(sname, sfi.FullName);
                this.UpdateButtonStatus();
            }
            else
            {
                MessageBox.Show(string.Format("服务程序不存在,请检查配置文件!\n{0}", sfi.FullName), "错误");
                this.Enabled = false;
            }
        }

        private void UpdateButtonStatus()
        {
            if (service.IsInstalled())
            {
                btnInstall.Text = "卸载";
                btnStart.Enabled = true;
                if (service.IsRunning())
                {
                    btnStart.Text = "停止";
                }
                else
                {
                    btnStart.Text = "启动";
                }
            }
            else
            {
                btnStart.Enabled = false;
                btnInstall.Text = "安装";
            }
            btnInstall.Enabled = true;
            btnLog.Enabled = true;
        }

        private void btnInstall_Click_1(object sender, EventArgs e)
        {
            btnInstall.Enabled = false;
            if (service.IsInstalled())
            {
                service.UnInstall();
            }
            else
            {
                service.Install();
            }

            this.UpdateButtonStatus();
        }

        private void btnStart_Click_1(object sender, EventArgs e)
        {
            btnStart.Enabled = false;
            if (service.IsRunning())
            {
                service.Stop();
            }
            else
            {
                service.Start();
            }
            this.UpdateButtonStatus();
        }

        private void btnLog_Click_1(object sender, EventArgs e)
        {
            this.Enabled = false;
            Process.Start("explorer.exe", logPath);
            this.Enabled = true;
        }
    }
}

 

SendMsgService:服务、ServiceControl服务控制应用程序、ServiceManager服务帮助类 编译生成文件需设置在同一文件夹下

 

  config.ini配置文件

  

此处SendMsgService.exe即为服务程序集名称

编译 生成,测试

 

转载于:https://www.cnblogs.com/itliyi/archive/2012/12/21/2828170.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值