.Net学习笔记《C#高级编程》之windows服务

本文深入探讨了Windows服务的组成及其实现原理,包括服务程序、服务控制程序和配置程序的功能,以及服务运行过程中的关键代码逻辑。同时,介绍了如何在代码中初始化服务状态和配置服务参数,并提供了简单的客户端调用服务进行通信的方法。最后,简要概述了服务的安装与启动流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

windows服务需要3种程序 :服务程序、服务控制程序、服务配置程序。


1:服务程序,包括主函数、service-main函数、处理程序。
服务控制管理器SCM(Service Control Manager)用于注册服务,于服务进行通信,它是windows系统的一部分。服务程序的直接关系者。
主函数向SCM注册一个service-main函数,service-main则主要向SCM注册一个处理程序。处理程序响应来自SCM的消息。
2:服务控制程序,主要向SCM发送消息,SCM响应这些消息(有些是SCM响应的,有些是注册在SCM特定服务的处理程序响应的),所以可以自定义一些消息。
3:服务配置程序,主要是环境、依赖关系、服务运行参数的配置。它主要和注册表打交到。


下面进入代码阶段:

如果进程中只有一个服务就可以删除数组。如果有多个服务运行在一个进程中,且需要初始化多个服务的某些共享状态时,则初始化必须在run()方法之前完成

static void Main()
        {
            //ServiceBase[] ServicesToRun;
            //ServicesToRun = new ServiceBase[] 
            //{ 
            //    new QuoteService() 
            //};
            //ServiceBase.Run(ServicesToRun);
            ServiceBase.Run(new QuoteService());
        }

class QuoteServer
    {
        private TcpListener listener;
        private int port;
        private string filename;
        private List<string> quotes;
        private Random random;
        private Thread listenerThread;

        #region 构造函数
        public QuoteServer()
            : this("quotes.txt")
        {
        }

        public QuoteServer(string str)
            : this(str, 7890)
        {

        }

        public QuoteServer(string str, int port)
        {
            this.filename = str;
            this.port = port;
        }
        #endregion

        #region 工具函数
        protected void ReadQuotes()
        {
            quotes = File.ReadAllLines(filename).ToList();
            random = new Random();
        }

        protected string GetRandomQuoteOfTheDay()
        {
            int index = random.Next(0, quotes.Count);
            return quotes[index];
        }


        protected void ListenerThread()
        {
            try
            {
                IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
                listener = new TcpListener(ipAddress, port);
                listener.Start();
                while (true)
                {
                    Socket clientSocket = listener.AcceptSocket();
                    string message = GetRandomQuoteOfTheDay();
                    UnicodeEncoding encoder = new UnicodeEncoding();
                    byte[] buffer = encoder.GetBytes(message);
                    clientSocket.Send(buffer, buffer.Length, 0);        //服务端口一直在发送随机消息
                    clientSocket.Close();
                }
            }
            catch (Exception ex)
            {
                Trace.TraceError(string.Format("QuotServer {0}", ex.Message));
            }
        }
        #endregion

        public void Start()
        {
            ReadQuotes();
            listenerThread = new Thread(ListenerThread);
            listenerThread.IsBackground = true;
            listenerThread.Name = "Listener";
            listenerThread.Start();
        }
        public void Stop()
        {
            listener.Stop();
        }
        public void Suspend()
        {
            listener.Stop();
        }
        public void Resume()
        {
            Start();
        }
        public void RefreshQuote()
        {
            ReadQuotes();
        }
    }

public partial class QuoteService : ServiceBase
    {
        private QuoteServer quoteServer;

        public QuoteService()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            quoteServer = new QuoteServer(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "quotes.txt"), 5678);
            quoteServer.Start();
        }

        protected override void OnStop()
        {
            quoteServer.Stop();
        }

        protected override void OnContinue()
        {
            quoteServer.Resume();
        }

        protected override void OnShutdown()
        {
            quoteServer.Stop();
        }

        protected override void OnPause()
        {
            quoteServer.Suspend();
        }

        private const int commandRefresh = 128;
        protected override void OnCustomCommand(int command)
        {
            switch (command)
            {
                case commandRefresh:
                    quoteServer.RefreshQuote();
                    break;
                default:
                    break;
            }
        }
    }


添加安装程序,再把属性中的ServiceName修改保持一致,这样就可以在服务的MMC单元中开启这个服务了。

客户端打开本机端口通信就可以了

private void OnGetQuote(object sender, RoutedEventArgs e)
        {
            const int bufferSize = 1024;
            Cursor currentCursor = this.Cursor;
            this.Cursor = Cursors.Wait;

            string serverName = Properties.Settings.Default.ServerName;
            int port = Properties.Settings.Default.PortNumber;

            TcpClient client = new TcpClient();
            NetworkStream stream = null;
            try
            {
                client.Connect(serverName, port);
                stream = client.GetStream();
                byte[] buffer = new Byte[bufferSize];
                int received = stream.Read(buffer, 0, bufferSize);
                if (received <= 0)
                {
                    return;
                }
                textQuote.Text = Encoding.Unicode.GetString(buffer).Trim('\0');
            }
            catch (SocketException ex)
            {
                MessageBox.Show(ex.Message, "Error Quote of the day",
                      MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally
            {
                if (stream != null)
                {
                    stream.Close();
                }

                if (client.Connected)
                {
                    client.Close();
                }
            }
            this.Cursor = currentCursor;

        }

试了一下,服务里面直接弹出windows消息框是不可以的。有待研究。

就先到这里吧,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值