用C#开发Windows服务

一、添加Windows服务MainService

MainService.cs

using SuperSocket.SocketBase;
using SuperSocket.SocketEngine;
using System.ServiceProcess;

namespace GpsTuQiangServiceDemo
{
    partial class MainService : ServiceBase
    {
        private IBootstrap m_Bootstrap;
        public MainService()
        {
            InitializeComponent();
            m_Bootstrap = BootstrapFactory.CreateBootstrap();
        }

        protected override void OnStart(string[] args)
        {
            if (!m_Bootstrap.Initialize())
                return;

            m_Bootstrap.Start();
        }

        protected override void OnStop()
        {
            m_Bootstrap.Stop();
            base.OnStop();
        }
        protected override void OnShutdown()
        {
            m_Bootstrap.Stop();
            base.OnShutdown();
        }
    }
}

二、添加安装程序类SocketServiceInstaller

SocketServiceInstaller.cs

using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Configuration.Install;
using System.ServiceProcess;

namespace GpsTuQiangServiceDemo
{
    [RunInstaller(true)]
    public partial class SocketServiceInstaller : System.Configuration.Install.Installer
    {
        private ServiceInstaller serviceInstaller;
        private ServiceProcessInstaller processInstaller;
        public SocketServiceInstaller()
        {
            InitializeComponent();

            processInstaller = new ServiceProcessInstaller();
            serviceInstaller = new ServiceInstaller();

            processInstaller.Account = ServiceAccount.LocalSystem;
            serviceInstaller.StartType = ServiceStartMode.Automatic;
            serviceInstaller.ServiceName = ConfigurationManager.AppSettings["ServiceName"];

            var serviceDisplayName = ConfigurationManager.AppSettings["ServiceDisplayName"];
            if (!string.IsNullOrEmpty(serviceDisplayName))
                serviceInstaller.DisplayName = serviceDisplayName;

            var serviceDescription = ConfigurationManager.AppSettings["ServiceDescription"];
            if (!string.IsNullOrEmpty(serviceDescription))
                serviceInstaller.Description = serviceDescription;

            var servicesDependedOn = new List<string> { "tcpip" };
            var servicesDependedOnConfig = ConfigurationManager.AppSettings["ServicesDependedOn"];

            if (!string.IsNullOrEmpty(servicesDependedOnConfig))
                servicesDependedOn.AddRange(servicesDependedOnConfig.Split(new char[] { ',', ';' }));

            serviceInstaller.ServicesDependedOn = servicesDependedOn.ToArray();

            var serviceStartAfterInstall = ConfigurationManager.AppSettings["ServiceStartAfterInstall"];
            if (!string.IsNullOrEmpty(serviceStartAfterInstall) && serviceStartAfterInstall.ToLower() == "true")
                this.AfterInstall += new InstallEventHandler(ProjectInstaller_AfterInstall);

            Installers.Add(serviceInstaller);
            Installers.Add(processInstaller);
        }
        private void ProjectInstaller_AfterInstall(object sender, InstallEventArgs e)
        {
            ServiceController sc = new ServiceController(serviceInstaller.ServiceName);
            sc.Start();
        }
    }
}

三、添加自安装类SelfInstaller

using System.Configuration.Install;
using System.Reflection;

namespace GpsTuQiangServiceDemo
{
    public static class SelfInstaller
    {
        private static readonly string _exePath = Assembly.GetExecutingAssembly().Location;

        public static bool InstallMe()
        {
            try
            {
                ManagedInstallerClass.InstallHelper(new string[] { _exePath });
            }
            catch
            {
                return false;
            }
            return true;
        }

        public static bool UninstallMe()
        {
            try
            {
                ManagedInstallerClass.InstallHelper(new string[] { "/u", _exePath });
            }
            catch
            {
                return false;
            }
            return true;
        }
    }
}

四、程序入口调用服务

using SuperSocket.Common;
using SuperSocket.SocketBase;
using SuperSocket.SocketEngine;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.ServiceProcess;

namespace GpsTuQiangServiceDemo
{
    class Program
    {
        private static bool setConsoleColor;
        private static Dictionary<string, ControlCommand> m_CommandHandlers = new Dictionary<string, ControlCommand>(StringComparer.OrdinalIgnoreCase);
        static void Main(string[] args)
        {
            string exeArg = string.Empty;

            if ((!Platform.IsMono && !Environment.UserInteractive)//Windows Service
                || (Platform.IsMono && !AppDomain.CurrentDomain.FriendlyName.Equals(Path.GetFileName(Assembly.GetEntryAssembly().CodeBase))))//MonoService
            {
                RunAsService();
                return;
            }

            if (args == null || args.Length < 1)
            {
                Console.WriteLine("Welcome to GpsTuQiangServiceDemo!");

                Console.WriteLine("Please press a key to continue...");
                Console.WriteLine("-[r]: Run this application as a console application;");
                Console.WriteLine("-[i]: Install this application as a Windows Service;");
                Console.WriteLine("-[u]: Uninstall this Windows Service application;");

                while (true)
                {
                    exeArg = Console.ReadKey().KeyChar.ToString();
                    Console.WriteLine();

                    if (Run(exeArg, null))
                        break;
                }
            }
            else
            {
                exeArg = args[0];

                if (!string.IsNullOrEmpty(exeArg))
                    exeArg = exeArg.TrimStart('-');

                Run(exeArg, args);
            }
        }
        private static bool Run(string exeArg, string[] startArgs)
        {
            switch (exeArg.ToLower())
            {
                case ("i"):
                    SelfInstaller.InstallMe();
                    return true;

                case ("u"):
                    SelfInstaller.UninstallMe();
                    return true;

                case ("r"):
                    RunAsConsole();
                    return true;

                default:
                    Console.WriteLine("Invalid argument!");
                    return false;
            }
        }
        static void CheckCanSetConsoleColor()
        {
            try
            {
                Console.ForegroundColor = ConsoleColor.Green;
                Console.ResetColor();
                setConsoleColor = true;
            }
            catch
            {
                setConsoleColor = false;
            }
        }
        private static void SetConsoleColor(ConsoleColor color)
        {
            if (setConsoleColor)
                Console.ForegroundColor = color;
        }
        static void RunAsConsole()
        {
            Console.WriteLine("Welcome to GpsTuQiangServiceDemo!");

            CheckCanSetConsoleColor();

            Console.WriteLine("Initializing...");

            IBootstrap bootstrap = BootstrapFactory.CreateBootstrap();

            if (!bootstrap.Initialize())
            {
                SetConsoleColor(ConsoleColor.Red);

                Console.WriteLine("Failed to initialize SuperSocket ServiceEngine! Please check error log for more information!");
                Console.ReadKey();
                return;
            }

            Console.WriteLine("Starting...");

            var result = bootstrap.Start();

            Console.WriteLine("-------------------------------------------------------------------");

            foreach (var server in bootstrap.AppServers)
            {
                if (server.State == ServerState.Running)
                {
                    SetConsoleColor(ConsoleColor.Green);
                    Console.WriteLine("- {0} has been started", server.Name);
                }
                else
                {
                    SetConsoleColor(ConsoleColor.Red);
                    Console.WriteLine("- {0} failed to start", server.Name);
                }
            }

            Console.ResetColor();
            Console.WriteLine("-------------------------------------------------------------------");

            switch (result)
            {
                case (StartResult.None):
                    SetConsoleColor(ConsoleColor.Red);
                    Console.WriteLine("No server is configured, please check you configuration!");
                    Console.ReadKey();
                    return;

                case (StartResult.Success):
                    Console.WriteLine("The SuperSocket ServiceEngine has been started!");
                    break;

                case (StartResult.Failed):
                    SetConsoleColor(ConsoleColor.Red);
                    Console.WriteLine("Failed to start the SuperSocket ServiceEngine! Please check error log for more information!");
                    Console.ReadKey();
                    return;

                case (StartResult.PartialSuccess):
                    SetConsoleColor(ConsoleColor.Red);
                    Console.WriteLine("Some server instances were started successfully, but the others failed! Please check error log for more information!");
                    break;
            }

            Console.ResetColor();
            Console.WriteLine("Enter key 'quit' to stop the ServiceEngine.");

            RegisterCommands();

            ReadConsoleCommand(bootstrap);

            bootstrap.Stop();

            Console.WriteLine("The SuperSocket ServiceEngine has been stopped!");
        }
        static void ReadConsoleCommand(IBootstrap bootstrap)
        {
            var line = Console.ReadLine();

            if (string.IsNullOrEmpty(line))
            {
                ReadConsoleCommand(bootstrap);
                return;
            }

            if ("quit".Equals(line, StringComparison.OrdinalIgnoreCase))
                return;

            var cmdArray = line.Split(' ');

            if (!m_CommandHandlers.TryGetValue(cmdArray[0], out ControlCommand cmd))
            {
                Console.WriteLine("Unknown command");
                ReadConsoleCommand(bootstrap);
                return;
            }

            try
            {
                if (cmd.Handler(bootstrap, cmdArray))
                    Console.WriteLine("Ok");
            }
            catch (Exception e)
            {
                Console.WriteLine("Failed. " + e.Message + Environment.NewLine + e.StackTrace);
            }

            ReadConsoleCommand(bootstrap);
        }
        private static void AddCommand(string name, string description, Func<IBootstrap, string[], bool> handler)
        {
            var command = new ControlCommand
            {
                Name = name,
                Description = description,
                Handler = handler
            };

            m_CommandHandlers.Add(command.Name, command);
        }
        static bool ListCommand(IBootstrap bootstrap, string[] arguments)
        {
            foreach (var s in bootstrap.AppServers)
            {
                if (s is IProcessServer processInfo && processInfo.ProcessId > 0)
                    Console.WriteLine("{0}[PID:{1}] - {2}", s.Name, processInfo.ProcessId, s.State);
                else
                    Console.WriteLine("{0} - {1}", s.Name, s.State);
            }

            return false;
        }
        static bool StartCommand(IBootstrap bootstrap, string[] arguments)
        {
            var name = arguments[1];

            if (string.IsNullOrEmpty(name))
            {
                Console.WriteLine("Server name is required!");
                return false;
            }

            var server = bootstrap.AppServers.FirstOrDefault(s => s.Name.Equals(name, StringComparison.OrdinalIgnoreCase));

            if (server == null)
            {
                Console.WriteLine("The server was not found!");
                return false;
            }

            server.Start();

            return true;
        }
        static bool StopCommand(IBootstrap bootstrap, string[] arguments)
        {
            var name = arguments[1];

            if (string.IsNullOrEmpty(name))
            {
                Console.WriteLine("Server name is required!");
                return false;
            }

            var server = bootstrap.AppServers.FirstOrDefault(s => s.Name.Equals(name, StringComparison.OrdinalIgnoreCase));

            if (server == null)
            {
                Console.WriteLine("The server was not found!");
                return false;
            }

            server.Stop();

            return true;
        }
        private static void RegisterCommands()
        {
            AddCommand("List", "List all server instances", ListCommand);
            AddCommand("Start", "Start a server instance: Start {ServerName}", StartCommand);
            AddCommand("Stop", "Stop a server instance: Stop {ServerName}", StopCommand);
        }
        
        static void RunAsService()
        {
            ServiceBase[] servicesToRun;

            servicesToRun = new ServiceBase[] { new MainService() };

            ServiceBase.Run(servicesToRun);
        }
    }
}
原文地址:https://www.cnblogs.com/xinzheng/p/8477881.html