【问题标题】:Deploying a C# Server Application部署 C# 服务器应用程序
【发布时间】:2014-11-18 09:52:40
【问题描述】:

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

我必须怎么做才能将这样的 C# 控制台应用程序部署到服务器上?是否需要转换为服务?我可以得到一个 VPS 并在上面运行它吗?

非常感谢任何答案或建议,谢谢

【问题讨论】:

    标签: c# deployment server


    【解决方案1】:

    在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
        }
    }
    

    希望我的代码有所帮助。有什么问题可以问

    【讨论】:

    • 太好了,谢谢 - 这是我分析的一个很好的例子
    • 实际上它是一个完全的反模式。对于安装,制作一个 MSI - 这是标准的,任何管理员都会更喜欢那个命令行大杂烩。多年来,Wix 工具集一直是这方面的标准。
    • @TomTom 我支持你的说法。但我喜欢为管理员提供两种方式。 WiX 的 ServiceControl 非常适合:wixtoolset.org/documentation/manual/v3/xsd/wix/…
    【解决方案2】:

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

    为了部署它,最好的方法是创建一个设置过程,然后将它安装在服务器上。然后你可以为你的服务器创建一个升级过程,这样你就不需要为你所做的每个更新都安装它。

    【讨论】:

    • 太好了,感谢您的快速回复。我将看看转换它并创建一个设置过程。
    猜你喜欢
    • 2016-04-10
    • 1970-01-01
    • 2018-12-02
    • 1970-01-01
    • 2016-08-17
    • 2021-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多