[英]Deploying a C# Server Application
我最近完成了在C#中将多线程服务器创建为控制台应用程序的工作。 它最初在公司计算机上运行,该公司计算机通过端口转发暴露在Internet上。 但是,我认为随着客户端的增加,可能需要将其设置为真实的服务器设置。 我以前从来没有这样做,所以我想知道:
我该怎么做才能将这样的C#控制台应用程序部署到服务器上? 是否需要将其转换为服务? 我可以获取VPS并在其上运行它吗?
非常感谢您的任何回答或建议,谢谢
在C#中,编写Windows服务非常简单。 我喜欢结合控制台应用程序和服务。 我将其结合起来,因为出于调试的原因,控制台应用程序会更好,而在生产环境中服务会更好。 作为服务基础,我始终使用:
Program.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
}
}
希望我的代码有所帮助。 询问您是否有任何问题
最好为此类程序提供服务。 控制台应用程序输出使用大量资源,必须手动启动。 可以在每台计算机启动时执行服务,而无需用户登录。
为了部署它,最好的方法是创建一个安装过程,然后将其安装在服务器上。 然后,您可以为服务器创建升级过程,这样就不必为每次更新都安装它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.