部署 C# 服务器应用程序

本文关键字:应用程序 服务器 部署 | 更新日期: 2023-09-27 18:30:51

我最近完成了在 C# 中创建一个多线程服务器作为控制台应用程序的创建。 最初,它运行在通过端口转发暴露给互联网的公司计算机上。 但是,我相信随着客户端的增加,它可能需要推送到真实的服务器设置。 我以前从未这样做过,所以我想知道:

必须执行哪些操作才能将此类 C# 控制台应用程序部署到服务器上? 是否需要将其转换为服务? 我可以得到一个VPS并在其上运行它吗?

我真的很感激任何答案或建议,谢谢

部署 C# 服务器应用程序

在 c# 中,编写 Windows 服务非常简单。我喜欢将控制台应用程序和服务结合起来。 我将其结合起来,因为出于调试原因,控制台应用程序更好,而对于生产应用程序,服务更好。作为服务基础,我总是使用:

课程.cs:

#define __USE_AS_CONSOLE___
using MyService.Service;
using System;
using System.Collections.Generic;
using System.Configuration.Install;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Diagnostics;
namespace MyService
{
    public class Program
    {
        #region Private Member
        private static ASServiceBase myServiceBase;
        private static string serviceName;
        #endregion
        #region Console
        const bool ShowConsole = true;
        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern bool AllocConsole();
        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern bool FreeConsole();
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern bool SetDllDirectory(string lpPathName);
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern bool AddDllDirectory(string lpPathName);
        #endregion
        static void Main(string[] args)
        {
            AppDomain.CurrentDomain.AssemblyResolve += ResolveError;
            string installCommand = "";
            serviceName = GetServiceName();
            foreach(string arg in args)
            {
                if (arg.ToLower().StartsWith("/install"))
                {
                    installCommand = "/install";
                }
                else if (arg.ToLower().StartsWith("/uninstall"))
                {
                    installCommand = "/uninstall";
                }
            }
            if (System.Environment.UserInteractive)
            {
                string parameter = "";
                foreach (string arg in args)
                {
                    parameter += arg;
                    if (!arg.EndsWith(" "))
                    {
                        parameter += "";
                    }
                }
                switch (installCommand)
                {
                    case "/install":
                        if (!IsAdministrator())
                        {
                            System.Console.WriteLine("Die Anwendung muss als Administrator installiert werden.");
                            System.Console.ReadLine();
                            return;
                        }
                        ManagedInstallerClass.InstallHelper(new string[] { Assembly.GetExecutingAssembly().Location });
                        return;
                        break;
                    case "/uninstall":
                        if (!IsAdministrator())
                        {
                            System.Console.WriteLine("Die Anwendung muss als Administrator installiert werden.");
                            System.Console.ReadLine();
                            return;
                        }
                        ManagedInstallerClass.InstallHelper(new string[] { "/u", Assembly.GetExecutingAssembly().Location });
                        return;
                        break;
                }
                AllocConsole();
                myServiceBase = new ASServiceBase();
                myServiceBase.Start();
                System.Console.ReadLine();
            }
            else
            {
                // ===============================================
                // Start Console
                AllocConsole();
                System.Console.WriteLine("Version 1.0");
                myServiceBase = new ASServiceBase();
                //Start service
                System.ServiceProcess.ServiceBase.Run(myServiceBase);
            }
        }
        public static bool IsAdministrator()
        {
            var identity = WindowsIdentity.GetCurrent();
            var principal = new WindowsPrincipal(identity);
            return principal.IsInRole(WindowsBuiltInRole.Administrator);
        }
        #region [Resolve Error]
        /// <summary>
        /// Resolve Error
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static Assembly ResolveError(object sender, ResolveEventArgs args)
        {
            try
            {
                Assembly cMyAssembly = null;
                string strTempAssmbPath = string.Empty;
                Assembly objExecutingAssemblies = Assembly.GetExecutingAssembly();
                AssemblyName[] arrReferencedAssmbNames = objExecutingAssemblies.GetReferencedAssemblies();
                AssemblyName myAssemblyName = Array.Find<AssemblyName>(arrReferencedAssmbNames, a => a.Name == args.Name);
                if (myAssemblyName != null)
                {
                    cMyAssembly = Assembly.LoadFrom(myAssemblyName.CodeBase);
                }
                else
                {
                    string rootFolder = GetAssemblyPath(args, "");
                    if (!string.IsNullOrEmpty(rootFolder))
                    {
                        if (File.Exists(rootFolder))
                        {
                            // Loads the assembly from the specified path.                  
                            cMyAssembly = Assembly.LoadFrom(rootFolder);
                        }
                    }
                    string assemblyFolder = GetAssemblyPath(args, "Assemblies''");
                    if (!string.IsNullOrEmpty(assemblyFolder))
                    {
                        if (File.Exists(assemblyFolder))
                        {
                            // Loads the assembly from the specified path.                  
                            cMyAssembly = Assembly.LoadFrom(assemblyFolder);
                        }
                    }
                }
                // Returns the loaded assembly.
                return cMyAssembly;
            }
            catch (Exception exc)
            {
                FileLog.WriteLog("Fehler in Init.ResolveError:'r'n" + exc.ToString());
                return null;
            }
        }
        private static string GetAssemblyPath(ResolveEventArgs args, string AdditionalDirectory)
        {
            string returnValue = null;
            string cRMSAssemblyFolder = GlobalSettings.StudioPath + "''" + AdditionalDirectory;
            Assembly cMyAssembly = null;
            string strTempAssmbPath = string.Empty;
            Assembly objExecutingAssemblies = Assembly.GetExecutingAssembly();
            AssemblyName[] arrReferencedAssmbNames = objExecutingAssemblies.GetReferencedAssemblies();
            AssemblyName myAssemblyName = Array.Find<AssemblyName>(arrReferencedAssmbNames, a => a.Name == args.Name);
            if (myAssemblyName == null)
            {
                if (args.Name.Contains(","))
                {
                    strTempAssmbPath = Path.Combine(cRMSAssemblyFolder, args.Name.Substring(0, args.Name.IndexOf(",")) + ".dll");
                }
                else
                {
                    strTempAssmbPath = Path.Combine(cRMSAssemblyFolder, args.Name + ".dll");
                }
                returnValue = strTempAssmbPath;
            }
            return returnValue;
        }
        #endregion
    }
}

服务安装程序:

using System;
using System.Configuration.Install;
using System.ComponentModel;
using System.ServiceProcess;
using System.IO;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Configuration;
using System.Diagnostics;
/// <summary>
/// Installerklasse für den Service
/// </summary>
[RunInstaller(true)]
public class QServiceInstaller : Installer
{
    #region private Member
    private ServiceInstaller myThisService;
    private IContainer components;
    private ServiceProcessInstaller myThisServiceProcess;
    #endregion
    public QServiceInstaller()
    {
        myThisService = new ServiceInstaller();
        myThisServiceProcess = new ServiceProcessInstaller();
        string Path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
        myThisServiceProcess.Account = ServiceAccount.LocalSystem;
        myThisService.ServiceName = "Your application name";
        myThisService.StartType = ServiceStartMode.Automatic;
        Installers.Add(myThisService);
        Installers.Add(myThisServiceProcess);
    }
    private void InitializeComponent()
    {
    }
}

您的服务基础:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading;
namespace MyService.Service
{
    public class ASServiceBase : ServiceBase
    {
        #region Private Member
        private Thread myServiceThread;
        private bool myDoStop;
        #endregion
        #region Constructor
        /// <summary>
        /// Constructor
        /// </summary>
        public ASServiceBase()
        {
            myDoStop = false;
        }
        #endregion
        #region Public Methods
        #region OnStart
        protected override void OnStart(string[] args)
        {
            Start();
        }
        /// <summary>
        /// Start
        /// </summary>
        public void Start()
        {
            myServiceThread = new Thread(new ThreadStart(Do));
            myServiceThread.Start();
            MainThread = myServiceThread;
        }
        #endregion
        #region Do Anything
        /// <summary>
        /// Execute
        /// </summary>
        public void Do()
        {
            while (!myDoStop)
            {
                // Do some stuff
                Thread.Sleep(10);
            }
            LoggingManager.Singleton.Deactivate();
            // =====================================================================================
            // Stop anything
            // =====================================================================================
        }
        #endregion
        #region OnStop
        protected override void OnStop()
        {
            Stop();
        }
        /// <summary>
        /// Stop
        /// </summary>
        public void Stop()
        {
            myDoStop = true;
        }
        #endregion
        #endregion
        #region Private Methods
        #endregion
        #region Public Member
        /// <summary>
        /// Main Thread
        /// </summary>
        public static Thread MainThread
        {
            get;
            set;
        }
        #endregion
    }
}

希望我的代码有所帮助。询问您是否有任何问题

最好为这种程序提供服务。控制台应用程序输出使用大量资源,必须手动启动。而服务可以在每台计算机上执行,甚至无需用户登录即可启动。

为了部署它,最好的方法是创建一个安装过程,然后将其安装在服务器上。然后,您可以为服务器创建一个 uptade 进程,这样您就不需要为每次更新都安装它。