• C#对Windows服务的创建、安装和卸载


    开发工具:VS2019

    目的:开启一个服务监听端口进行以太网通讯 

    一.创建 Windows服务项目

     1.创建项目

        创建成功后,如下图所示

       将 Service1.cs 改名为  BridgeService.cs 

       双击 BridgeService.cs 后如下图所示

    2.添加安装程序 

    在上图中按中鼠标右键,添加安装程序

    添加完成后,在项目中自动生成  ProjectInstaller.cs

    双击  ProjectInstaller.cs 得到下图界面

    在项目中, ServiceProcessInstaller 为每个服务应用程序创建一个实例,并 ServiceInstaller 为应用程序中的每个服务创建一个实例。 在项目安装程序类构造函数中,使用和实例设置服务的安装 ServiceProcessInstaller 属性 ServiceInstaller ,并将实例添加到集合中 Installers 。 

    3.配置参数 

    查看 serviceInstaller1 的属性

    • ServiceName:表示该服务显示的名称
    • StartType:设置为开机自动启动 
    • Description:表示对服务的描述

    4.添加服务相关事件 

    using System.ServiceProcess;
    
    namespace BService
    {
        public partial class BridgeService : ServiceBase
        {
            public BridgeService()
            {
                InitializeComponent();
            }
    
            /// <summary>
            /// 启动服务时发生
            /// </summary>
            /// <param name="args"></param>
            protected override void OnStart(string[] args)
            {
            }
    
            /// <summary>
            /// 停止服务时发生
            /// </summary>
            protected override void OnStop()
            {
            }
    
        }
    }
    

    5.编写所需的代码

    using System;
    using System.Collections.Generic;
    using System.Net;
    using System.Net.Sockets;
    using System.ServiceProcess;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace BService
    {
        public partial class BridgeService : ServiceBase
        {
            public BridgeService()
            {
                InitializeComponent();
            }
    
            protected override void OnStart(string[] args)
            {
                RunLog.WriteLine("提示:开启服务");
                _tokenSource = new CancellationTokenSource();
                _tcpClient = new TcpClient();
                Task.Factory.StartNew(listen, _tokenSource.Token);
                Task.Factory.StartNew(read, _tokenSource.Token);
                RunLog.WriteLine("提示:开启监听端口5000和开启接收数据");
            }
    
            protected override void OnStop()
            {
                _tokenSource.Cancel();
                RunLog.WriteLine("提示:停止服务");
            }
    
            CancellationTokenSource _tokenSource = new CancellationTokenSource();
            TcpClient _tcpClient;
            void listen()
            {
                Socket newSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPEndPoint localEP = new IPEndPoint(IPAddress.Any, 5000);
                try
                {
                    newSocket.Bind(localEP);
                    newSocket.Listen(10);
                    while (!_tokenSource.IsCancellationRequested)
                    {
                        Socket socket = newSocket.Accept();
                        EndPoint endPoint = socket.RemoteEndPoint;
                        IPEndPoint ipPoint = (IPEndPoint)endPoint;
                        RunLog.WriteLine("已连接到 {0}:{1}", ipPoint.Address, ipPoint.Port);
                        _tcpClient.Client = socket;
                    }
                }
                catch (Exception ee)
                {
                    RunLog.WriteLine("错误:监听异常--{0}", ee.Message);
                }
            }
    
            void read()
            {
                try
                {
                    List<byte> listData = new List<byte>();
                    bool haveData = false;
                    while (!_tokenSource.IsCancellationRequested)
                    {
                        if (_tcpClient.Connected)
                        {
                            int length = _tcpClient.Available;
                            if (length != 0)
                            {
                                byte[] bData = new byte[length];
                                _tcpClient.GetStream().Read(bData, 0, length);
                                listData.AddRange(bData);
                                haveData = true;
                            }
                            else if (haveData)
                            {
                                RunLog.WriteLine("提示:接收到数据:{0}", Encoding.Default.GetString(listData.ToArray()));
                                listData = new List<byte>();
                                haveData = false;
                            }
                        }
                        Thread.Sleep(10);
                    }
                }
                catch (Exception ee)
                {
                    RunLog.WriteLine("错误:读取异常--{0}", ee.Message);
                }
            }
    
    
        }
    }
    
    using System;
    using System.IO;
    using System.Text;
    
    namespace BService
    {
        public class RunLog
        {
            static Object _lock = new object();
    
            public static void WriteLine(string format, params object[] args)
            {
                lock (_lock)
                {
                    string text = format;
                    if (args.Length != 0)
                    {
                        text = string.Format(format, args);
                    }
    
                    string fileName = string.Format(@"D:/BService.log");
                    text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + "   " + text;
                    try
                    {
                        FileInfo info = new FileInfo(fileName);
                        bool isSet = false;
                        if (info.Exists)
                        {
                            info.IsReadOnly = false;
                            isSet = true;
                        }
                        using (StreamWriter sw = new StreamWriter(fileName, true, Encoding.Default))
                        {
                            sw.WriteLine(text);
                            sw.Close();
                        }
                        if (isSet)
                        {
                            info.IsReadOnly = true;
                        }
                    }
                    catch
                    {
                    }
                }
            }
    
        }
    }
    

     二、多服务的创建

    在一个项目中添加多个服务,可以跳过 

     1.添加新服务

      在 BService项目中添加新项 (MyService.cs 服务)

       

    2.添加事件

    using System.ServiceProcess;
    
    namespace BService
    {
        public partial class MyService : ServiceBase
        {
            public MyService()
            {
                InitializeComponent();
            }
    
            protected override void OnStart(string[] args)
            {
                RunLog.WriteLine("提示:开启服务{0}", "MyService");
            }
    
            protected override void OnStop()
            {
                RunLog.WriteLine("提示:停止服务{0}", "MyService");
            }
    
        }
    }
    

    3.添加ServiceInstaller 

     

    4.配置参数

    5.多服务的重点设置 

    修改Program ,在 ServiceBase 中添加 MyService

    using System.ServiceProcess;
    
    namespace BService
    {
        static class Program
        {
            /// <summary>
            /// 应用程序的主入口点。
            /// </summary>
            static void Main()
            {
                ServiceBase[] ServicesToRun;
                ServicesToRun = new ServiceBase[]
                {
                    new BridgeService(),
                    new MyService()
                };
                ServiceBase.Run(ServicesToRun);
            }
        }
    }
    

    在ProjectInstaller.Designer.cs 中将 serviceInstaller2 添加到 Installers中

    修改了这两个地方才能同时安装两个服务 

    三、启动服务 

    1.建立操作窗体 

    另起 Winform 项目 ServiceClient,建立新的窗体

    2.添加引用 

    右键项目添加引用:将BService添加到该项目中 ,以方便调试

    3.编写按钮事件

    using System;
    using System.Collections;
    using System.Configuration.Install;
    using System.ServiceProcess;
    using System.Windows.Forms;
    
    namespace ServiceClient
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            string _serviceFilePath = "BService.exe";
            string[] _serviceNames = new string[] { "BridgeService", "MyService" };
    
            //事件:安装服务
            private void button1_Click(object sender, EventArgs e)
            {
                foreach (string name in _serviceNames)
                {
                    if (IsServiceExisted(name))
                    {
                        UninstallService(_serviceFilePath);
                        break;
                    }
                }
                InstallService(_serviceFilePath);
            }
    
            //事件:启动服务
            private void button2_Click(object sender, EventArgs e)
            {
                foreach (string name in _serviceNames)
                {
                    if (IsServiceExisted(name))
                    {
                        ServiceStart(name);
                    }
                }
            }
    
            //事件:停止服务
            private void button3_Click(object sender, EventArgs e)
            {
                foreach (string name in _serviceNames)
                {
                    if (IsServiceExisted(name))
                    {
                        ServiceStop(name);
                    }
                }
            }
    
            //事件:卸载服务
            private void button4_Click(object sender, EventArgs e)
            {
                bool isHave = false;
                foreach (string name in _serviceNames)
                {
                    if (IsServiceExisted(name))
                    {
                        ServiceStop(name);
                        isHave = true;
                    }
                }
                if (isHave)
                {
                    UninstallService(_serviceFilePath);
                }
            }
    
            //判断服务是否存在
            private bool IsServiceExisted(string serviceName)
            {
                ServiceController[] services = ServiceController.GetServices();
                foreach (ServiceController sc in services)
                {
                    if (sc.ServiceName.ToLower() == serviceName.ToLower())
                    {
                        return true;
                    }
                }
                return false;
            }
    
            //安装服务
            private void InstallService(string serviceFilePath)
            {
                using (AssemblyInstaller installer = new AssemblyInstaller())
                {
                    installer.UseNewContext = true;
                    installer.Path = serviceFilePath;
                    IDictionary savedState = new Hashtable();
                    installer.Install(savedState);
                    installer.Commit(savedState);
                }
            }
    
            //卸载服务
            private void UninstallService(string serviceFilePath)
            {
                using (AssemblyInstaller installer = new AssemblyInstaller())
                {
                    installer.UseNewContext = true;
                    installer.Path = serviceFilePath;
                    installer.Uninstall(null);
                }
            }
    
            //启动服务
            private void ServiceStart(string serviceName)
            {
                using (ServiceController control = new ServiceController(serviceName))
                {
                    if (control.Status == ServiceControllerStatus.Stopped)
                    {
                        control.Start();
                    }
                }
            }
    
            //停止服务
            private void ServiceStop(string serviceName)
            {
                using (ServiceController control = new ServiceController(serviceName))
                {
                    if (control.Status == ServiceControllerStatus.Running)
                    {
                        control.Stop();
                    }
                }
            }
    
        }
    }
    
    

    4.查看服务 

    启动后,可以在计算机管理中查看安装的服务和服务当前的状态 

    四、服务使用的注意点 

    1.文件路径 

    服务的本体虽然是在 ServiceClient中,但是在服务中对文件的操作路径不是在 ServiceClient中,所以在服务中若要对文件进行操作,路径最好是绝对路径,如上述服务中的 Log 路径

    我的电脑 win7-64位:C:\Windows\SysWOW64 

    2.服务调试 

    当服务启动后,如何对服务进行调试呢?

    在VS中选择调试中的附加到进程

    显示所有用户的进程,找到 BService.exe ,然后点击附加就可以监控和调试 服务代码了 

    五、总结 

    同一个项目中有两个服务时,安装可以成功但是在启动时有时会报错:错误1083:配置成在该可执行程序中运行的这个服务不能执行该服务 。原因目前不清楚,所以尽量不要将两个服务放在一个项目中,可以分开单独创建。

  • 相关阅读:
    初识Python
    MySql的前戏
    abstract class 和 interface 有什么区别?(抽象类和接口的区别)
    java方法签名
    final
    OverLoad 和 Override 的区别
    WebService (什么是WebService ,有哪些优点? WebService由什么组成?分别对应的含义?)
    人民币
    快速排序
    动态反射
  • 原文地址:https://www.cnblogs.com/bridgew/p/16138064.html
Copyright © 2020-2023  润新知