Files
watrbx-game-engine/Client.LegacyAssemblies/Roblox.Common/Roblox.ServiceProcess/ServiceHostApp.cs
T
2025-09-18 17:55:52 -04:00

250 lines
5.7 KiB
C#

using System;
using System.Collections;
using System.Configuration.Install;
using System.Reflection;
using System.ServiceModel;
using System.ServiceProcess;
namespace Roblox.ServiceProcess;
public class ServiceHostApp<TServiceClass> : ServiceBasePublic where TServiceClass : class
{
private ServiceHost serviceHost;
private TServiceClass singleton;
private ServiceBasePublic[] otherSingletons;
public event EventHandler HostClosed;
public event EventHandler HostClosing;
public event EventHandler HostFaulted;
public event EventHandler HostOpened;
public event EventHandler HostOpening;
public ServiceHostApp(TServiceClass singleton)
{
this.singleton = singleton;
}
public ServiceHostApp(TServiceClass singleton, ServiceBasePublic[] others)
: this(singleton)
{
otherSingletons = others;
}
public ServiceHostApp()
{
}
protected override void OnStart(string[] args)
{
CloseServiceHost();
if (singleton != null)
{
serviceHost = new ServiceHost(singleton);
}
else
{
serviceHost = new ServiceHost(typeof(TServiceClass));
}
if (serviceHost.SingletonInstance is IArgumentService)
{
(serviceHost.SingletonInstance as IArgumentService).ProcessArgs(args);
}
serviceHost.Closed += serviceHost_Closed;
serviceHost.Closing += serviceHost_Closing;
serviceHost.Faulted += serviceHost_Faulted;
serviceHost.Opened += serviceHost_Opened;
serviceHost.Opening += serviceHost_Opening;
serviceHost.Open();
if (otherSingletons != null)
{
ServiceBasePublic[] array = otherSingletons;
foreach (ServiceBasePublic sbp in array)
{
sbp.OnStartPublic(args);
}
}
}
private void CloseServiceHost()
{
if (serviceHost != null)
{
if (serviceHost.State != CommunicationState.Closed)
{
serviceHost.Close();
}
serviceHost.Closed -= serviceHost_Closed;
serviceHost.Closing -= serviceHost_Closing;
serviceHost.Faulted -= serviceHost_Faulted;
serviceHost.Opened -= serviceHost_Opened;
serviceHost.Opening -= serviceHost_Opening;
serviceHost = null;
}
}
private void serviceHost_Closed(object sender, EventArgs e)
{
if (this.HostClosed != null)
{
this.HostClosed(sender, e);
}
}
private void serviceHost_Closing(object sender, EventArgs e)
{
if (this.HostClosing != null)
{
this.HostClosing(sender, e);
}
}
private void serviceHost_Faulted(object sender, EventArgs e)
{
if (this.HostFaulted != null)
{
this.HostFaulted(sender, e);
}
}
private void serviceHost_Opened(object sender, EventArgs e)
{
if (this.HostOpened != null)
{
this.HostOpened(sender, e);
}
}
private void serviceHost_Opening(object sender, EventArgs e)
{
if (this.HostOpening != null)
{
this.HostOpening(sender, e);
}
}
protected override void OnStop()
{
CloseServiceHost();
if (otherSingletons != null)
{
ServiceBasePublic[] array = otherSingletons;
foreach (ServiceBasePublic sbp in array)
{
sbp.OnStopPublic();
}
}
}
public void Process(string[] args)
{
Process(args, null);
}
public void Process(string[] args, Action statsTask)
{
if (args.Length != 0)
{
try
{
switch (args[0].Substring(1).ToLower())
{
case "console":
{
ConsoleKey closeSocketsKey = ConsoleKey.Q;
ConsoleKey exitKey = ConsoleKey.Escape;
ConsoleKey garbageCollectionKey = ConsoleKey.G;
Console.WriteLine("Starting {0}...", typeof(TServiceClass));
OnStart(args);
Console.WriteLine("Service started. Press any key to {0}.", (statsTask == null) ? "exit" : "get stats");
Console.WriteLine("Press {0} to force a full Garbage Collection cycle", garbageCollectionKey);
Console.WriteLine("Press {0} to close sockets or {1} to exit process", closeSocketsKey, exitKey);
while (true)
{
ConsoleKey key = Console.ReadKey(intercept: true).Key;
if (key == exitKey)
{
break;
}
if (key == garbageCollectionKey)
{
Console.Write("Initiating GC cycle ....");
GC.Collect(3, GCCollectionMode.Forced);
Console.WriteLine("done");
}
else if (key == closeSocketsKey)
{
Console.Write("Closing sockets....");
CloseServiceHost();
Console.WriteLine(" done");
Console.WriteLine("Press {0} to exit process", exitKey);
}
else
{
if (statsTask == null)
{
break;
}
statsTask();
}
}
Console.WriteLine("Stopping Service.");
OnStop();
break;
}
case "install":
{
Console.WriteLine("Installing...");
AssemblyInstaller installer2 = new AssemblyInstaller(Assembly.GetEntryAssembly(), new string[0]);
installer2.UseNewContext = true;
IDictionary savedState2 = new Hashtable();
installer2.Install(savedState2);
installer2.Commit(savedState2);
Console.WriteLine("Service Installed");
break;
}
case "uninstall":
{
Console.WriteLine("Uninstalling...");
AssemblyInstaller installer = new AssemblyInstaller(Assembly.GetEntryAssembly(), new string[0]);
installer.UseNewContext = true;
IDictionary savedState = new Hashtable();
installer.Uninstall(savedState);
Console.WriteLine("Service Uninstalled");
break;
}
default:
throw new ApplicationException("Bad argument " + args[0]);
}
return;
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
return;
}
}
if (otherSingletons != null)
{
ServiceBase[] hosts = new ServiceBase[otherSingletons.Length + 1];
int pos = 0;
hosts[pos++] = this;
ServiceBasePublic[] array = otherSingletons;
foreach (ServiceBase sb in array)
{
hosts[pos++] = sb;
}
ServiceBase.Run(hosts);
}
else
{
ServiceBase.Run(this);
}
}
}