mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-25 14:06:41 +01:00
Split the service and server functions
This commit is contained in:
@@ -32,7 +32,7 @@ The [WiX Toolset](http://wixtoolset.org/) is used for creating the installer .ms
|
||||
|
||||
#### Debugging
|
||||
|
||||
So you've built the project and everything's good, right? Now you have to debug it. Debugging the command line and control panel are easy enough, just launch them like any other process. Debugging the TGS.Server.Service itself though requires a bit of finagling due to how Windows services work.
|
||||
So you've built the project and everything's good, right? Now you have to debug it. Debugging the command line and control panel are easy enough, just launch them like any other process. Debugging the TGS.Server itself though requires a bit of finagling due to how Windows services work.
|
||||
|
||||
1. Uninstall any release versions of TG Station Server 3 you may have on your machine
|
||||
1. Open an administrative Windows cmd prompt
|
||||
|
||||
@@ -191,7 +191,7 @@ You can clear all active test merges using `Reset to Origin Branch` in the `Repo
|
||||
|
||||
### Viewing Server Logs
|
||||
* Logs are stored in the Windows event viewer under `Windows Logs` -> `Application`. You'll need to filter this list for `TG Station Server`
|
||||
* Every event type is keyed with an ID. A complete listing of these IDs and their purpose can be found [here](https://github.com/tgstation/tgstation-server/blob/master/TGS.Server.Service/EventID.cs).
|
||||
* Every event type is keyed with an ID. A complete listing of these IDs and their purpose can be found [here](https://github.com/tgstation/tgstation-server/blob/master/TGS.Server/EventID.cs).
|
||||
* You can also import the custom view `View TGS3 Logs.xml` in this folder to have them automatically filtered
|
||||
|
||||
### Enabling upstream changelog generation
|
||||
|
||||
+17
-14
@@ -84,37 +84,40 @@
|
||||
<File Source="$(var.TGS.CommandLine.TargetPath)" />
|
||||
<Environment Id="PATH" Name="PATH" Value="[INSTALLFOLDER]" Permanent="no" Part="last" Action="set" System="yes" />
|
||||
</Component>
|
||||
<Component Id="TGS.Server" Guid="*">
|
||||
<File Source="$(var.TGS.Server.TargetPath)" />
|
||||
</Component>
|
||||
<Component Id="TGS.Server.Service" Guid="*">
|
||||
<File Source="$(var.TGS.Server.Service.TargetPath)" Id="ServiceExecutable" />
|
||||
<ServiceInstall Id="ServiceInstaller" Name="TG Station Server" Type="ownProcess" EraseDescription="no" ErrorControl="normal" Start="auto" Vital="yes" />
|
||||
<ServiceControl Id="StartService" Start="install" Stop="both" Remove="uninstall" Name="TG Station Server" Wait="yes" />
|
||||
</Component>
|
||||
<Component Id="DiscordNetCore" Guid="*">
|
||||
<File Source="$(var.TGS.Server.Service.TargetDir)/Discord.Net.Core.dll" />
|
||||
<File Source="$(var.TGS.Server.TargetDir)/Discord.Net.Core.dll" />
|
||||
</Component>
|
||||
<Component Id="DiscordNetRest" Guid="*">
|
||||
<File Source="$(var.TGS.Server.Service.TargetDir)/Discord.Net.Rest.dll" />
|
||||
<File Source="$(var.TGS.Server.TargetDir)/Discord.Net.Rest.dll" />
|
||||
</Component>
|
||||
<Component Id="DiscordNetWebSocket" Guid="*">
|
||||
<File Source="$(var.TGS.Server.Service.TargetDir)/Discord.Net.WebSocket.dll" />
|
||||
<File Source="$(var.TGS.Server.TargetDir)/Discord.Net.WebSocket.dll" />
|
||||
</Component>
|
||||
<Component Id="LibGit2Sharp" Guid="*">
|
||||
<File Source="$(var.TGS.Server.Service.TargetDir)/LibGit2Sharp.dll" />
|
||||
<File Source="$(var.TGS.Server.TargetDir)/LibGit2Sharp.dll" />
|
||||
</Component>
|
||||
<Component Id="Octokit" Guid="*">
|
||||
<File Source="$(var.TGS.ControlPanel.TargetDir)/Octokit.dll" />
|
||||
</Component>
|
||||
<Component Id="MeebeySmartIrc4net" Guid="*">
|
||||
<File Source="$(var.TGS.Server.Service.TargetDir)/Meebey.SmartIrc4net.dll" />
|
||||
<File Source="$(var.TGS.Server.TargetDir)/Meebey.SmartIrc4net.dll" />
|
||||
</Component>
|
||||
<Component Id="NewtonsoftJson" Guid="*">
|
||||
<File Source="$(var.TGS.Server.Service.TargetDir)/Newtonsoft.Json.dll" />
|
||||
<File Source="$(var.TGS.Server.TargetDir)/Newtonsoft.Json.dll" />
|
||||
</Component>
|
||||
<Component Id="SystemCollectionsImmutable" Guid="*">
|
||||
<File Source="$(var.TGS.Server.Service.TargetDir)/System.Collections.Immutable.dll" />
|
||||
<File Source="$(var.TGS.Server.TargetDir)/System.Collections.Immutable.dll" />
|
||||
</Component>
|
||||
<Component Id="SystemInteractiveAsync" Guid="*">
|
||||
<File Source="$(var.TGS.Server.Service.TargetDir)/System.Interactive.Async.dll" />
|
||||
<File Source="$(var.TGS.Server.TargetDir)/System.Interactive.Async.dll" />
|
||||
</Component>
|
||||
<Component Id="TGS.ControlPanel" Guid="*">
|
||||
<File Source="$(var.TGS.ControlPanel.TargetPath)" KeyPath="yes" />
|
||||
@@ -128,24 +131,24 @@
|
||||
</ComponentGroup>
|
||||
<ComponentGroup Id="Gitx86Components" Directory="x86Folder">
|
||||
<Component Id="LibGit2Sharpx86" Guid="*">
|
||||
<File Source="$(var.TGS.Server.Service.TargetDir)lib\win32\x86\git2-ssh-baa87df.dll" Id="LibGit2Sharpx86dll"/>
|
||||
<File Source="$(var.TGS.Server.TargetDir)lib\win32\x86\git2-ssh-baa87df.dll" Id="LibGit2Sharpx86dll"/>
|
||||
</Component>
|
||||
<Component Id="LibGit2Sharpx86SSH" Guid="*">
|
||||
<File Source="$(var.TGS.Server.Service.TargetDir)lib\win32\x86\libssh2.dll" Id="LibGit2Sharpx86SSHdll"/>
|
||||
<File Source="$(var.TGS.Server.TargetDir)lib\win32\x86\libssh2.dll" Id="LibGit2Sharpx86SSHdll"/>
|
||||
</Component>
|
||||
<Component Id="LibGit2Sharpx86Z" Guid="*">
|
||||
<File Source="$(var.TGS.Server.Service.TargetDir)lib\win32\x86\zlib.dll" Id="LibGit2Sharpx86Zdll"/>
|
||||
<File Source="$(var.TGS.Server.TargetDir)lib\win32\x86\zlib.dll" Id="LibGit2Sharpx86Zdll"/>
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
<ComponentGroup Id="Gitx64Components" Directory="x64Folder">
|
||||
<Component Id="LibGit2Sharpx64" Guid="*">
|
||||
<File Source="$(var.TGS.Server.Service.TargetDir)lib\win32\x64\git2-ssh-baa87df.dll" Id="LibGit2Sharpx64dll" />
|
||||
<File Source="$(var.TGS.Server.TargetDir)lib\win32\x64\git2-ssh-baa87df.dll" Id="LibGit2Sharpx64dll" />
|
||||
</Component>
|
||||
<Component Id="LibGit2Sharpx64SSH" Guid="*">
|
||||
<File Source="$(var.TGS.Server.Service.TargetDir)lib\win32\x64\libssh2.dll" Id="LibGit2Sharpx64SSHdll"/>
|
||||
<File Source="$(var.TGS.Server.TargetDir)lib\win32\x64\libssh2.dll" Id="LibGit2Sharpx64SSHdll"/>
|
||||
</Component>
|
||||
<Component Id="LibGit2Sharpx64Z" Guid="*">
|
||||
<File Source="$(var.TGS.Server.Service.TargetDir)lib\win32\x64\zlib.dll" Id="LibGit2Sharpx64Zdll"/>
|
||||
<File Source="$(var.TGS.Server.TargetDir)lib\win32\x64\zlib.dll" Id="LibGit2Sharpx64Zdll"/>
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
|
||||
@@ -50,6 +50,14 @@
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\TGS.Server.Service\TGS.Server.Service.csproj">
|
||||
<Name>TGS.Server.Service</Name>
|
||||
<Project>{3f81e398-b223-4006-b40c-c2800714ce29}</Project>
|
||||
<Private>True</Private>
|
||||
<DoNotHarvest>True</DoNotHarvest>
|
||||
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
|
||||
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\TGS.Server\TGS.Server.csproj">
|
||||
<Name>TGS.Server</Name>
|
||||
<Project>{f32eda25-0855-411c-af5e-f0d042917e2d}</Project>
|
||||
<Private>True</Private>
|
||||
<DoNotHarvest>True</DoNotHarvest>
|
||||
|
||||
@@ -1,28 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<section name="TGS.Server.Service.Properties.Instance" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
|
||||
<section name="TGS.Server.Service.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/>
|
||||
</startup>
|
||||
<userSettings>
|
||||
<TGS.Server.Service.Properties.Settings>
|
||||
<setting name="PythonPath" serializeAs="String">
|
||||
<value>C:\Python27</value>
|
||||
</setting>
|
||||
<setting name="UpgradeRequired" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="SettingsVersion" serializeAs="String">
|
||||
<value>7</value>
|
||||
</setting>
|
||||
<setting name="RemoteAccessPort" serializeAs="String">
|
||||
<value>38607</value>
|
||||
</setting>
|
||||
</TGS.Server.Service.Properties.Settings>
|
||||
</userSettings>
|
||||
</configuration>
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.Runtime.InteropServices;
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("TGStation Server Service")]
|
||||
[assembly: AssemblyDescription("Server Service for running BYOND games")]
|
||||
[assembly: AssemblyDescription("Windows service adapter for TGStation Server")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
@@ -13,4 +13,4 @@ using System.Runtime.InteropServices;
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("f32eda25-0855-411c-af5e-f0d042917e2d")]
|
||||
[assembly: Guid("3f81e398-b223-4006-b40c-c2800714ce29")]
|
||||
|
||||
+32
-662
@@ -1,693 +1,63 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Security.Principal;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceProcess;
|
||||
using TGS.Interface;
|
||||
using TGS.Interface.Components;
|
||||
|
||||
namespace TGS.Server.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// The windows service the application runs as
|
||||
/// Windows <see cref="ServiceBase"/> adapter for <see cref="Server"/>
|
||||
/// </summary>
|
||||
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
|
||||
class Service : ServiceBase, ITGSService, ITGConnectivity, ITGLanding, ITGInstanceManager
|
||||
public sealed class Service : ServiceBase, ILogger
|
||||
{
|
||||
/// <summary>
|
||||
/// The logging ID used for <see cref="Service"/> events
|
||||
/// The entry point for the program. Calls <see cref="ServiceBase.Run(ServiceBase)"/> with a new <see cref="Service"/> as a parameter
|
||||
/// </summary>
|
||||
public const byte LoggingID = 0;
|
||||
public static void Main() => Run(new Service());
|
||||
|
||||
/// <summary>
|
||||
/// The service version <see cref="string"/> based on the <see cref="FileVersionInfo"/>
|
||||
/// The <see cref="Server"/> the <see cref="Service"/> manages
|
||||
/// </summary>
|
||||
public static readonly string VersionString = "/tg/station 13 Server Service v" + FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileVersion;
|
||||
Server activeServer;
|
||||
|
||||
/// <summary>
|
||||
/// Singleton instance
|
||||
/// </summary>
|
||||
static Service ActiveService;
|
||||
|
||||
/// <summary>
|
||||
/// Cancels WCF's user impersonation to allow clean access to writing log files
|
||||
/// </summary>
|
||||
public static void CancelImpersonation()
|
||||
/// <inheritdoc />
|
||||
public void WriteAccess(string username, bool authSuccess, byte loggingID)
|
||||
{
|
||||
WindowsIdentity.Impersonate(IntPtr.Zero);
|
||||
EventLog.WriteEntry(String.Format("Access from: {0}", username), authSuccess ? EventLogEntryType.SuccessAudit : EventLogEntryType.FailureAudit , (int)EventID.Authentication + loggingID);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void WriteError(string message, EventID id, byte loggingID)
|
||||
{
|
||||
EventLog.WriteEntry(message, EventLogEntryType.Error, (int)id + loggingID);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void WriteInfo(string message, EventID id, byte loggingID)
|
||||
{
|
||||
EventLog.WriteEntry(message, EventLogEntryType.Information, (int)id + loggingID);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void WriteWarning(string message, EventID id, byte loggingID)
|
||||
{
|
||||
EventLog.WriteEntry(message, EventLogEntryType.Warning, (int)id + loggingID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an event to Windows the event log
|
||||
/// Called when the <see cref="Service"/> is started. Creates a new <see cref="activeServer"/>
|
||||
/// </summary>
|
||||
/// <param name="message">The log message</param>
|
||||
/// <param name="id">The <see cref="EventID"/> of the message</param>
|
||||
/// <param name="eventType">The <see cref="EventLogEntryType"/> of the event</param>
|
||||
/// <param name="loggingID">The logging source ID for the event</param>
|
||||
public static void WriteEntry(string message, EventID id, EventLogEntryType eventType, byte loggingID)
|
||||
{
|
||||
ActiveService.EventLog.WriteEntry(message, eventType, (int)id + loggingID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks an <paramref name="instanceName"/> for illegal characters
|
||||
/// </summary>
|
||||
/// <param name="instanceName">The <see cref="ServerInstance"/> name to check</param>
|
||||
/// <returns><see langword="null"/> if <paramref name="instanceName"/> contains no illegal characters, error message otherwise</returns>
|
||||
static string CheckInstanceName(string instanceName)
|
||||
{
|
||||
char[] bannedCharacters = { ';', '&', '=', '%' };
|
||||
foreach (var I in bannedCharacters)
|
||||
if (instanceName.Contains(I.ToString()))
|
||||
return "Instance names may not contain the following characters: ';', '&', '=', or '%'";
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets up ServiceName and <see cref="ActiveService"/>
|
||||
/// </summary>
|
||||
public Service()
|
||||
{
|
||||
ServiceName = "TG Station Server";
|
||||
if (ActiveService != null)
|
||||
throw new Exception("There is already a Service instance running!");
|
||||
ActiveService = this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears <see cref="ActiveService"/>
|
||||
/// </summary>
|
||||
/// <param name="disposing"><see langword="true"/> if this method was invoked from <see cref="IDisposable.Dispose"/>, otherwise it was invoked by the finalizer</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
ActiveService = null;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The WCF host that contains <see cref="ITGSService"/> connects to
|
||||
/// </summary>
|
||||
ServiceHost serviceHost;
|
||||
/// <summary>
|
||||
/// Map of <see cref="InstanceConfig.Name"/> to the respective <see cref="ServiceHost"/> hosting the <see cref="ServerInstance"/>
|
||||
/// </summary>
|
||||
IDictionary<string, ServiceHost> hosts;
|
||||
/// <summary>
|
||||
/// List of <see cref="ServerInstance.LoggingID"/>s in use
|
||||
/// </summary>
|
||||
IList<int> UsedLoggingIDs = new List<int>();
|
||||
|
||||
/// <summary>
|
||||
/// Migrates the .NET config from <paramref name="oldVersion"/> to <paramref name="oldVersion"/> + 1
|
||||
/// </summary>
|
||||
/// <param name="oldVersion">The version to migrate from</param>
|
||||
void MigrateSettings(int oldVersion)
|
||||
{
|
||||
var Config = Properties.Settings.Default;
|
||||
switch (oldVersion)
|
||||
{
|
||||
case 6: //switch to per-instance configs
|
||||
var IC = DeprecatedInstanceConfig.CreateFromNETSettings();
|
||||
IC.Save();
|
||||
Config.InstancePaths.Add(IC.Directory);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enumerates configured <see cref="IInstanceConfig"/>s. Detaches those that fail to load
|
||||
/// </summary>
|
||||
/// <returns>Each configured <see cref="IInstanceConfig"/></returns>
|
||||
IEnumerable<IInstanceConfig> GetInstanceConfigs()
|
||||
{
|
||||
var pathsToRemove = new List<string>();
|
||||
lock (this)
|
||||
{
|
||||
var IPS = Properties.Settings.Default.InstancePaths;
|
||||
foreach (var I in IPS)
|
||||
{
|
||||
IInstanceConfig ic;
|
||||
try
|
||||
{
|
||||
ic = InstanceConfig.Load(I);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
WriteEntry(String.Format("Unable load instance config at path {0}. Error: {1} Detaching...", I, e.ToString()), EventID.InstanceInitializationFailure, EventLogEntryType.Error, LoggingID);
|
||||
pathsToRemove.Add(I);
|
||||
continue;
|
||||
}
|
||||
yield return ic;
|
||||
}
|
||||
foreach (var I in pathsToRemove)
|
||||
IPS.Remove(I);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides and saves the configured <see cref="Properties.Settings.RemoteAccessPort"/> if requested by command line parameters
|
||||
/// </summary>
|
||||
/// <param name="args">The command line parameters for the <see cref="Service"/></param>
|
||||
void ChangePortFromCommandLine(string[] args)
|
||||
{
|
||||
var Config = Properties.Settings.Default;
|
||||
|
||||
for (var I = 0; I < args.Length - 1; ++I)
|
||||
if (args[I].ToLower() == "-port")
|
||||
{
|
||||
try
|
||||
{
|
||||
var res = Convert.ToUInt16(args[I + 1]);
|
||||
if (res == 0)
|
||||
throw new Exception("Cannot bind to port 0");
|
||||
Config.RemoteAccessPort = res;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception("Invalid argument for \"-port\"", e);
|
||||
}
|
||||
Config.Save();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the Windows service manager. Initializes and starts configured <see cref="ServerInstance"/>s
|
||||
/// </summary>
|
||||
/// <param name="args">Command line arguments for the <see cref="Service"/></param>
|
||||
/// <param name="args">The service start arguments</param>
|
||||
protected override void OnStart(string[] args)
|
||||
{
|
||||
Environment.CurrentDirectory = Directory.CreateDirectory(Path.GetTempPath() + "/TGStationServerService").FullName; //MOVE THIS POINTER BECAUSE ONE TIME I ALMOST ACCIDENTALLY NUKED MYSELF BY REFACTORING! http://imgur.com/zvGEpJD.png
|
||||
|
||||
SetupConfig();
|
||||
|
||||
ChangePortFromCommandLine(args);
|
||||
|
||||
SetupService();
|
||||
|
||||
SetupInstances();
|
||||
|
||||
OnlineAllHosts();
|
||||
activeServer = new Server(args, this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes some changes to the <see cref="Properties.Settings"/> that always need to be done.
|
||||
/// </summary>
|
||||
void PrePrepConfig()
|
||||
{
|
||||
var Config = Properties.Settings.Default;
|
||||
|
||||
if (Config.InstancePaths == null)
|
||||
Config.InstancePaths = new StringCollection();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Upgrades up the service configuration
|
||||
/// </summary>
|
||||
void SetupConfig()
|
||||
{
|
||||
var Config = Properties.Settings.Default;
|
||||
if (Config.UpgradeRequired)
|
||||
{
|
||||
var newVersion = Config.SettingsVersion;
|
||||
Config.Upgrade();
|
||||
|
||||
PrePrepConfig();
|
||||
|
||||
for (var oldVersion = Config.SettingsVersion; oldVersion < newVersion; ++oldVersion)
|
||||
MigrateSettings(oldVersion);
|
||||
|
||||
Config.SettingsVersion = newVersion;
|
||||
|
||||
Config.UpgradeRequired = false;
|
||||
Config.Save();
|
||||
}
|
||||
else
|
||||
PrePrepConfig();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the <see cref="ServiceHost"/> for <see cref="ITGSService"/>
|
||||
/// </summary>
|
||||
void SetupService()
|
||||
{
|
||||
serviceHost = CreateHost(this, ServerInterface.MasterInterfaceName);
|
||||
foreach (var I in ServerInterface.ValidServiceInterfaces)
|
||||
AddEndpoint(serviceHost, I);
|
||||
serviceHost.Authorization.ServiceAuthorizationManager = new RootAuthorizationManager(); //only admins can diddle us
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens all created <see cref="ServiceHost"/>s
|
||||
/// </summary>
|
||||
void OnlineAllHosts()
|
||||
{
|
||||
serviceHost.Open();
|
||||
foreach (var I in hosts)
|
||||
I.Value.Open();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ServiceHost"/> for <paramref name="singleton"/> using the default pipe, CloseTimeout for the <see cref="ServiceHost"/>, and the configured <see cref="Properties.Settings.RemoteAccessPort"/>
|
||||
/// </summary>
|
||||
/// <param name="singleton">The <see cref="ServiceHost.SingletonInstance"/></param>
|
||||
/// <param name="endpointPostfix">The URL to access components on the <see cref="ServiceHost"/></param>
|
||||
/// <returns>The created <see cref="ServiceHost"/></returns>
|
||||
static ServiceHost CreateHost(object singleton, string endpointPostfix)
|
||||
{
|
||||
return new ServiceHost(singleton, new Uri[] { new Uri(String.Format("net.pipe://localhost/{0}", endpointPostfix)), new Uri(String.Format("https://localhost:{0}/{1}", Properties.Settings.Default.RemoteAccessPort, endpointPostfix)) })
|
||||
{
|
||||
CloseTimeout = new TimeSpan(0, 0, 5)
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates <see cref="ServiceHost"/>s for all <see cref="ServerInstance"/>s as listed in <see cref="Properties.Settings.InstancePaths"/>, detaches bad ones
|
||||
/// </summary>
|
||||
void SetupInstances()
|
||||
{
|
||||
hosts = new Dictionary<string, ServiceHost>();
|
||||
var pathsToRemove = new List<string>();
|
||||
var seenNames = new List<string>();
|
||||
foreach (var I in GetInstanceConfigs())
|
||||
{
|
||||
if (seenNames.Contains(I.Name))
|
||||
{
|
||||
WriteEntry(String.Format("Instance at {0} has a duplicate name! Detaching...", I.Directory), EventID.InstanceInitializationFailure, EventLogEntryType.Error, LoggingID);
|
||||
pathsToRemove.Add(I.Directory);
|
||||
}
|
||||
if (I.Enabled && SetupInstance(I) == null)
|
||||
pathsToRemove.Add(I.Directory);
|
||||
else
|
||||
seenNames.Add(I.Name);
|
||||
}
|
||||
foreach (var I in pathsToRemove)
|
||||
Properties.Settings.Default.InstancePaths.Remove(I);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unlocks a <see cref="ServerInstance.LoggingID"/> acquired with <see cref="LockLoggingID"/>
|
||||
/// </summary>
|
||||
/// <param name="ID">The <see cref="ServerInstance.LoggingID"/> to unlock</param>
|
||||
void UnlockLoggingID(byte ID)
|
||||
{
|
||||
lock (UsedLoggingIDs)
|
||||
{
|
||||
UsedLoggingIDs.Remove(ID);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and locks a <see cref="ServerInstance.LoggingID"/>
|
||||
/// </summary>
|
||||
/// <returns>A logging ID for the <see cref="ServerInstance"/> must be released using <see cref="UnlockLoggingID(byte)"/></returns>
|
||||
byte LockLoggingID()
|
||||
{
|
||||
lock (UsedLoggingIDs)
|
||||
{
|
||||
for (byte I = 1; I < 100; ++I)
|
||||
if (!UsedLoggingIDs.Contains(I))
|
||||
{
|
||||
UsedLoggingIDs.Add(I);
|
||||
return I;
|
||||
}
|
||||
}
|
||||
throw new Exception("All logging IDs in use!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and starts a <see cref="ServiceHost"/> for a <see cref="ServerInstance"/> at <paramref name="config"/>
|
||||
/// </summary>
|
||||
/// <param name="config">The <see cref="IInstanceConfig"/> for the <see cref="ServerInstance"/></param>
|
||||
/// <returns>The inactive <see cref="ServiceHost"/> on success, <see langword="null"/> on failure</returns>
|
||||
ServiceHost SetupInstance(IInstanceConfig config)
|
||||
{
|
||||
ServerInstance instance;
|
||||
string instanceName;
|
||||
try
|
||||
{
|
||||
if (hosts.ContainsKey(config.Directory))
|
||||
{
|
||||
var datInstance = ((ServerInstance)hosts[config.Directory].SingletonInstance);
|
||||
WriteEntry(String.Format("Unable to start instance at path {0}. Has the same name as instance at path {1}. Detaching...", config.Directory, datInstance.ServerDirectory()), EventID.InstanceInitializationFailure, EventLogEntryType.Error, LoggingID);
|
||||
return null;
|
||||
}
|
||||
if (!config.Enabled)
|
||||
return null;
|
||||
var ID = LockLoggingID();
|
||||
WriteEntry(String.Format("Instance {0} ({1}) assigned logging ID {2}", config.Name, config.Directory, ID), EventID.InstanceIDAssigned, EventLogEntryType.Information, ID);
|
||||
instanceName = config.Name;
|
||||
instance = new ServerInstance(config, ID);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
WriteEntry(String.Format("Unable to start instance at path {0}. Detaching... Error: {1}", config.Directory, e.ToString()), EventID.InstanceInitializationFailure, EventLogEntryType.Error, LoggingID);
|
||||
return null;
|
||||
}
|
||||
|
||||
var host = CreateHost(instance, String.Format("{0}/{1}", ServerInterface.InstanceInterfaceName, instanceName));
|
||||
hosts.Add(instanceName, host);
|
||||
|
||||
foreach (var J in ServerInterface.ValidInstanceInterfaces)
|
||||
AddEndpoint(host, J);
|
||||
|
||||
host.Authorization.ServiceAuthorizationManager = instance;
|
||||
return host;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a WCF endpoint for a component <paramref name="typetype"/>
|
||||
/// </summary>
|
||||
/// <param name="host">The service host to add the component to</param>
|
||||
/// <param name="typetype">The type of the component</param>
|
||||
void AddEndpoint(ServiceHost host, Type typetype)
|
||||
{
|
||||
var bindingName = typetype.Name;
|
||||
host.AddServiceEndpoint(typetype, new NetNamedPipeBinding() { SendTimeout = new TimeSpan(0, 0, 30), MaxReceivedMessageSize = ServerInterface.TransferLimitLocal }, bindingName);
|
||||
var httpsBinding = new WSHttpBinding()
|
||||
{
|
||||
SendTimeout = new TimeSpan(0, 0, 40),
|
||||
MaxReceivedMessageSize = ServerInterface.TransferLimitRemote
|
||||
};
|
||||
var requireAuth = typetype.Name != typeof(ITGConnectivity).Name;
|
||||
httpsBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
|
||||
httpsBinding.Security.Mode = requireAuth ? SecurityMode.TransportWithMessageCredential : SecurityMode.Transport; //do not require auth for a connectivity check
|
||||
httpsBinding.Security.Message.ClientCredentialType = requireAuth ? MessageCredentialType.UserName : MessageCredentialType.None;
|
||||
host.AddServiceEndpoint(typetype, httpsBinding, bindingName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shuts down all active <see cref="ServiceHost"/>s and calls <see cref="IDisposable.Dispose"/> on it's <see cref="ServerInstance"/>
|
||||
/// Called when the <see cref="Service"/> is stopped. Calls <see cref="IDisposable.Dispose"/> on <see cref="activeServer"/>
|
||||
/// </summary>
|
||||
protected override void OnStop()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var I in hosts)
|
||||
{
|
||||
var host = I.Value;
|
||||
var instance = (ServerInstance)host.SingletonInstance;
|
||||
host.Close();
|
||||
instance.Dispose();
|
||||
UnlockLoggingID(instance.LoggingID);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
WriteEntry(e.ToString(), EventID.ServiceShutdownFail, EventLogEntryType.Error, LoggingID);
|
||||
}
|
||||
serviceHost.Close();
|
||||
}
|
||||
Properties.Settings.Default.Save();
|
||||
ActiveService = null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void VerifyConnection() { }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void PrepareForUpdate()
|
||||
{
|
||||
foreach (var I in hosts)
|
||||
((ServerInstance)I.Value.SingletonInstance).Reattach(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ushort RemoteAccessPort()
|
||||
{
|
||||
return Properties.Settings.Default.RemoteAccessPort;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string SetRemoteAccessPort(ushort port)
|
||||
{
|
||||
if (port == 0)
|
||||
return "Cannot bind to port 0";
|
||||
Properties.Settings.Default.RemoteAccessPort = port;
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Version()
|
||||
{
|
||||
return VersionString;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool SetPythonPath(string path)
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
return false;
|
||||
Properties.Settings.Default.PythonPath = Path.GetFullPath(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string PythonPath()
|
||||
{
|
||||
return Properties.Settings.Default.PythonPath;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IList<InstanceMetadata> ListInstances()
|
||||
{
|
||||
var result = new List<InstanceMetadata>();
|
||||
lock (this)
|
||||
foreach (var ic in GetInstanceConfigs())
|
||||
result.Add(new InstanceMetadata
|
||||
{
|
||||
Name = ic.Name,
|
||||
Path = ic.Directory,
|
||||
Enabled = ic.Enabled,
|
||||
LoggingID = (byte)(ic.Enabled ? ((ServerInstance)hosts[ic.Name].SingletonInstance).LoggingID : 0)
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string CreateInstance(string Name, string path)
|
||||
{
|
||||
path = Program.NormalizePath(path);
|
||||
var res = CheckInstanceName(Name);
|
||||
if (res != null)
|
||||
return res;
|
||||
if (File.Exists(path) || Directory.Exists(path))
|
||||
return "Cannot create instance at pre-existing path!";
|
||||
var Config = Properties.Settings.Default;
|
||||
lock (this)
|
||||
{
|
||||
if (Config.InstancePaths.Contains(path))
|
||||
return String.Format("Instance at {0} already exists!", path);
|
||||
foreach (var oic in GetInstanceConfigs())
|
||||
if (Name == oic.Name)
|
||||
return String.Format("Instance named {0} already exists!", oic.Name);
|
||||
IInstanceConfig ic;
|
||||
try
|
||||
{
|
||||
ic = new InstanceConfig(path)
|
||||
{
|
||||
Name = Name
|
||||
};
|
||||
Directory.CreateDirectory(path);
|
||||
ic.Save();
|
||||
Properties.Settings.Default.InstancePaths.Add(path);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return e.ToString();
|
||||
}
|
||||
return SetupOneInstance(ic);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts and onlines an instance located at <paramref name="config"/>
|
||||
/// </summary>
|
||||
/// <param name="config">The <see cref="IInstanceConfig"/> for the <see cref="ServerInstance"/></param>
|
||||
/// <returns><see langword="null"/> on success, error message on failure</returns>
|
||||
string SetupOneInstance(IInstanceConfig config)
|
||||
{
|
||||
if (!config.Enabled)
|
||||
return null;
|
||||
try
|
||||
{
|
||||
var host = SetupInstance(config);
|
||||
if (host != null)
|
||||
host.Open();
|
||||
else
|
||||
lock (this)
|
||||
Properties.Settings.Default.InstancePaths.Remove(config.Directory);
|
||||
return null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return "Instance set up but an error occurred while starting it: " + e.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string ImportInstance(string path)
|
||||
{
|
||||
path = Program.NormalizePath(path);
|
||||
var Config = Properties.Settings.Default;
|
||||
lock (this)
|
||||
{
|
||||
if (Config.InstancePaths.Contains(path))
|
||||
return String.Format("Instance at {0} already exists!", path);
|
||||
if(!Directory.Exists(path))
|
||||
return String.Format("There is no instance located at {0}!", path);
|
||||
IInstanceConfig ic;
|
||||
try
|
||||
{
|
||||
ic = InstanceConfig.Load(path);
|
||||
foreach(var oic in GetInstanceConfigs())
|
||||
if(ic.Name == oic.Name)
|
||||
return String.Format("Instance named {0} already exists!", oic.Name);
|
||||
ic.Save();
|
||||
Properties.Settings.Default.InstancePaths.Add(path);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return e.ToString();
|
||||
}
|
||||
return SetupOneInstance(ic);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool InstanceEnabled(string Name)
|
||||
{
|
||||
lock(this)
|
||||
{
|
||||
return hosts.ContainsKey(Name);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string SetInstanceEnabled(string Name, bool enabled)
|
||||
{
|
||||
return SetInstanceEnabledImpl(Name, enabled, out string path);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sets a <see cref="ServerInstance"/>'s enabled status
|
||||
/// </summary>
|
||||
/// <param name="Name">The <see cref="ServerInstance"/> whom's status should be changed</param>
|
||||
/// <param name="enabled"><see langword="true"/> to enable the <see cref="ServerInstance"/>, <see langword="false"/> to disable it</param>
|
||||
/// <param name="path">The path to the modified <see cref="ServerInstance"/></param>
|
||||
/// <returns><see langword="null"/> on success, error message on failure</returns>
|
||||
string SetInstanceEnabledImpl(string Name, bool enabled, out string path)
|
||||
{
|
||||
path = null;
|
||||
lock (this)
|
||||
{
|
||||
var hostIsOnline = hosts.ContainsKey(Name);
|
||||
if (enabled)
|
||||
{
|
||||
if (hostIsOnline)
|
||||
return null;
|
||||
foreach (var ic in GetInstanceConfigs())
|
||||
if (ic.Name == Name)
|
||||
{
|
||||
path = ic.Directory;
|
||||
ic.Enabled = true;
|
||||
ic.Save();
|
||||
return SetupOneInstance(ic);
|
||||
}
|
||||
return String.Format("Instance {0} does not exist!", Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!hostIsOnline)
|
||||
return null;
|
||||
var host = hosts[Name];
|
||||
hosts.Remove(Name);
|
||||
var inst = (ServerInstance)host.SingletonInstance;
|
||||
host.Close();
|
||||
path = inst.ServerDirectory();
|
||||
inst.Offline();
|
||||
inst.Dispose();
|
||||
UnlockLoggingID(inst.LoggingID);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string RenameInstance(string name, string new_name)
|
||||
{
|
||||
if (name == new_name)
|
||||
return null;
|
||||
var res = CheckInstanceName(new_name);
|
||||
if (res != null)
|
||||
return res;
|
||||
lock (this)
|
||||
{
|
||||
//we have to check em all anyway
|
||||
IInstanceConfig the_droid_were_looking_for = null;
|
||||
foreach (var ic in GetInstanceConfigs())
|
||||
if (ic.Name == name)
|
||||
{
|
||||
the_droid_were_looking_for = ic;
|
||||
break;
|
||||
}
|
||||
else if (ic.Name == new_name)
|
||||
return String.Format("There is already another instance named {0}!", new_name);
|
||||
if (the_droid_were_looking_for == null)
|
||||
return String.Format("There is no instance named {0}!", name);
|
||||
var ie = InstanceEnabled(name);
|
||||
if(ie)
|
||||
SetInstanceEnabled(name, false);
|
||||
the_droid_were_looking_for.Name = new_name;
|
||||
string result = "";
|
||||
try
|
||||
{
|
||||
the_droid_were_looking_for.Save();
|
||||
result = null;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
result = "Could not save instance config! Error: " + e.ToString();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (ie)
|
||||
{
|
||||
var resRestore = SetInstanceEnabled(new_name, true);
|
||||
if (resRestore != null)
|
||||
result = (result + " " + resRestore).Trim();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string DetachInstance(string name)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
var res = SetInstanceEnabledImpl(name, false, out string path);
|
||||
if (res != null)
|
||||
return res;
|
||||
if (path == null) //gotta find it ourselves
|
||||
foreach (var ic in GetInstanceConfigs())
|
||||
if (ic.Name == name)
|
||||
{
|
||||
path = ic.Directory;
|
||||
break;
|
||||
}
|
||||
if (path == null)
|
||||
return String.Format("No instance named {0} exists!", name);
|
||||
Properties.Settings.Default.InstancePaths.Remove(path);
|
||||
return null;
|
||||
}
|
||||
activeServer.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,162 +1,63 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\packages\LibGit2Sharp-SSH.NativeBinaries.1.0.14\build\LibGit2Sharp-SSH.NativeBinaries.props" Condition="Exists('..\packages\LibGit2Sharp-SSH.NativeBinaries.1.0.14\build\LibGit2Sharp-SSH.NativeBinaries.props')" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{F32EDA25-0855-411C-AF5E-F0D042917E2D}</ProjectGuid>
|
||||
<ProjectGuid>{3F81E398-B223-4006-B40C-C2800714CE29}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>TGS.Server.Service</RootNamespace>
|
||||
<AssemblyName>TGServerService</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>tgs.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<DocumentationFile>bin\x86\Release\TGS.Server.Service.xml</DocumentationFile>
|
||||
<Optimize>true</Optimize>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SignAssembly>false</SignAssembly>
|
||||
<StartupObject>TGS.Server.Service.Service</StartupObject>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Discord.Net.Core, Version=1.0.2.0, Culture=neutral, PublicKeyToken=null, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Discord.Net.Core.1.0.2\lib\net45\Discord.Net.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Discord.Net.Rest, Version=1.0.2.0, Culture=neutral, PublicKeyToken=null, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Discord.Net.Rest.1.0.2\lib\net45\Discord.Net.Rest.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Discord.Net.WebSocket, Version=1.0.2.0, Culture=neutral, PublicKeyToken=null, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Discord.Net.WebSocket.1.0.2\lib\net45\Discord.Net.WebSocket.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="LibGit2Sharp, Version=1.0.22.0, Culture=neutral, PublicKeyToken=7cbde695407f0333, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\LibGit2Sharp-SSH.1.0.22\lib\net40\LibGit2Sharp.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Meebey.SmartIrc4net, Version=0.4.5.0, Culture=neutral, PublicKeyToken=7868485fbf407e0f, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SmartIrc4net.1.1\lib\Meebey.SmartIrc4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Collections.Immutable.1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.configuration" />
|
||||
<Reference Include="System.Configuration.Install" />
|
||||
<Reference Include="System.DirectoryServices.AccountManagement" />
|
||||
<Reference Include="System.Interactive.Async, Version=3.0.1000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.IO.Compression" />
|
||||
<Reference Include="System.IO.Compression.FileSystem" />
|
||||
<Reference Include="System.Numerics" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Web.Extensions" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.ServiceProcess" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ChatCommands\ByondCommand.cs" />
|
||||
<Compile Include="ChatCommands\CommandInfo.cs" />
|
||||
<Compile Include="ChatCommands\ChatCommand.cs" />
|
||||
<Compile Include="ChatCommands\KekCommand.cs" />
|
||||
<Compile Include="ChatCommands\PullRequestsCommand.cs" />
|
||||
<Compile Include="ChatCommands\RevisionCommand.cs" />
|
||||
<Compile Include="ChatCommands\RootChatCommand.cs" />
|
||||
<Compile Include="ChatCommands\ServerChatCommand.cs" />
|
||||
<Compile Include="ChatCommands\VersionCommand.cs" />
|
||||
<Compile Include="RootAuthorizationManager.cs" />
|
||||
<Compile Include="DeprecatedInstanceConfig.cs" />
|
||||
<Compile Include="InstanceConfig.cs" />
|
||||
<Compile Include="MessageType.cs" />
|
||||
<Compile Include="RepoConfig.cs" />
|
||||
<Compile Include="ServerInstance\Administration.cs" />
|
||||
<Compile Include="ServerInstance\Byond.cs" />
|
||||
<Compile Include="ServerInstance\Chat.cs" />
|
||||
<Compile Include="ChatProviders\ChatProvider.cs" />
|
||||
<Compile Include="ServerInstance\Compiler.cs" />
|
||||
<Compile Include="ServerInstance\Config.cs" />
|
||||
<Compile Include="ChatProviders\DiscordChatProvider.cs" />
|
||||
<Compile Include="ServerInstance\DreamDaemon.cs" />
|
||||
<Compile Include="EventID.cs" />
|
||||
<Compile Include="ServerInstance\ServerInstance.cs" />
|
||||
<Compile Include="ChatProviders\IRCChatProvider.cs" />
|
||||
<Compile Include="ServerInstance\Interop.cs" />
|
||||
<Compile Include="ServerInstance\PreactionHandler.cs" />
|
||||
<Compile Include="ProcessExtension.cs" />
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ServerInstance\Repository.cs" />
|
||||
<Compile Include="ProjectInstaller.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Service.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="..\AssemblyInfo.global.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<None Include="packages.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\TGS.Interface\TGS.Interface.csproj">
|
||||
<Project>{ac4e7e8b-f83a-481c-a8b0-8fa4e8ae59ab}</Project>
|
||||
<Name>TGS.Interface</Name>
|
||||
<ProjectReference Include="..\TGS.Server\TGS.Server.csproj">
|
||||
<Project>{f32eda25-0855-411c-af5e-f0d042917e2d}</Project>
|
||||
<Name>TGS.Server</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="tgs.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\LibGit2Sharp-SSH.NativeBinaries.1.0.14\build\LibGit2Sharp-SSH.NativeBinaries.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\LibGit2Sharp-SSH.NativeBinaries.1.0.14\build\LibGit2Sharp-SSH.NativeBinaries.props'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<section name="TGServerService.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
|
||||
</startup>
|
||||
<userSettings>
|
||||
<TGServerService.Properties.Settings>
|
||||
<setting name="PythonPath" serializeAs="String">
|
||||
<value>C:\Python27</value>
|
||||
</setting>
|
||||
<setting name="UpgradeRequired" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="SettingsVersion" serializeAs="String">
|
||||
<value>7</value>
|
||||
</setting>
|
||||
<setting name="RemoteAccessPort" serializeAs="String">
|
||||
<value>38607</value>
|
||||
</setting>
|
||||
</TGServerService.Properties.Settings>
|
||||
</userSettings>
|
||||
</configuration>
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using TGS.Interface;
|
||||
|
||||
namespace TGS.Server.Service.ChatCommands
|
||||
namespace TGS.Server.ChatCommands
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieve the installed, staged, or latest availab
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
using System.Threading;
|
||||
using TGS.Interface;
|
||||
|
||||
namespace TGS.Server.Service.ChatCommands
|
||||
namespace TGS.Server.ChatCommands
|
||||
{
|
||||
/// <summary>
|
||||
/// A command heard by a <see cref="ChatProviders.IChatProvider"/>
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
namespace TGS.Server.Service.ChatCommands
|
||||
namespace TGS.Server.ChatCommands
|
||||
{
|
||||
/// <summary>
|
||||
/// Metadata about the currently running <see cref="ChatCommand"/>
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TGS.Server.Service.ChatCommands
|
||||
namespace TGS.Server.ChatCommands
|
||||
{
|
||||
/// <summary>
|
||||
/// kek
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TGS.Server.Service.ChatCommands
|
||||
namespace TGS.Server.ChatCommands
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieve the list of test-merged github pull requests
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TGS.Server.Service.ChatCommands
|
||||
namespace TGS.Server.ChatCommands
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves the git SHA of the live DreamDaemon code
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using TGS.Interface;
|
||||
|
||||
namespace TGS.Server.Service.ChatCommands
|
||||
namespace TGS.Server.ChatCommands
|
||||
{
|
||||
/// <summary>
|
||||
/// The main root chat command
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TGS.Server.Service.ChatCommands
|
||||
namespace TGS.Server.ChatCommands
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="ChatCommand"/>s generated by DreamDaemon via the API
|
||||
@@ -37,7 +37,7 @@ namespace TGS.Server.Service.ChatCommands
|
||||
/// <inheritdoc />
|
||||
protected override ExitCode Run(IList<string> parameters)
|
||||
{
|
||||
var res = Instance.SendCommand(String.Format("{0};sender={1};custom={2}", Keyword, CommandInfo.Value.Speaker, Program.SanitizeTopicString(String.Join(" ", parameters))));
|
||||
var res = Instance.SendCommand(String.Format("{0};sender={1};custom={2}", Keyword, CommandInfo.Value.Speaker, Helpers.SanitizeTopicString(String.Join(" ", parameters))));
|
||||
if (res != "SUCCESS" && !String.IsNullOrWhiteSpace(res))
|
||||
OutputProc(res);
|
||||
return ExitCode.Normal;
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TGS.Server.Service.ChatCommands
|
||||
namespace TGS.Server.ChatCommands
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieve the current service version
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using TGS.Interface;
|
||||
|
||||
namespace TGS.Server.Service.ChatProviders
|
||||
namespace TGS.Server.ChatProviders
|
||||
{
|
||||
/// <summary>
|
||||
/// Callback for the chat provider recieving a <paramref name="message"/>
|
||||
+1
-3
@@ -6,7 +6,7 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using TGS.Interface;
|
||||
|
||||
namespace TGS.Server.Service.ChatProviders
|
||||
namespace TGS.Server.ChatProviders
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="IChatProvider"/> for Discord: https://discordapp.com/
|
||||
@@ -179,7 +179,6 @@ namespace TGS.Server.Service.ChatProviders
|
||||
lock (DiscordLock)
|
||||
{
|
||||
var tasks = new List<Task>();
|
||||
var Config = Properties.Settings.Default;
|
||||
foreach (var I in client.Guilds)
|
||||
foreach (var J in I.TextChannels)
|
||||
{
|
||||
@@ -208,7 +207,6 @@ namespace TGS.Server.Service.ChatProviders
|
||||
lock (DiscordLock)
|
||||
{
|
||||
var tasks = new List<Task>();
|
||||
var Config = Properties.Settings.Default;
|
||||
var channel = Convert.ToUInt64(channelname);
|
||||
if (SeenPrivateChannels.ContainsKey(channel))
|
||||
SeenPrivateChannels[channel].SendMessageAsync(message).Wait();
|
||||
+2
-2
@@ -4,7 +4,7 @@ using System.Threading;
|
||||
using TGS.Interface;
|
||||
using Meebey.SmartIrc4net;
|
||||
|
||||
namespace TGS.Server.Service.ChatProviders
|
||||
namespace TGS.Server.ChatProviders
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="IChatProvider"/> for internet relay chat
|
||||
@@ -48,7 +48,7 @@ namespace TGS.Server.Service.ChatProviders
|
||||
irc = new IrcFeatures()
|
||||
{
|
||||
SupportNonRfc = true,
|
||||
CtcpUserInfo = Service.VersionString,
|
||||
CtcpUserInfo = Server.VersionString,
|
||||
AutoRejoin = true,
|
||||
AutoRejoinOnKick = true,
|
||||
AutoRelogin = true,
|
||||
+5
-5
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
|
||||
namespace TGS.Server.Service
|
||||
namespace TGS.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to migrate old config settings
|
||||
@@ -19,8 +19,8 @@ namespace TGS.Server.Service
|
||||
/// <returns>An <see cref="IInstanceConfig"/> based off the old .NET setting file</returns>
|
||||
public static IInstanceConfig CreateFromNETSettings()
|
||||
{
|
||||
var Config = Properties.Settings.Default;
|
||||
var result = new DeprecatedInstanceConfig(Program.NormalizePath(LoadPreviousNetPropertyOrDefault("ServerDirectory", "C:\\tgstation-server-3")));
|
||||
var Config = TGServerService.Properties.Settings.Default;
|
||||
var result = new DeprecatedInstanceConfig(Helpers.NormalizePath(LoadPreviousNetPropertyOrDefault("ServerDirectory", "C:\\tgstation-server-3")));
|
||||
// using nameof for sanity where possible
|
||||
result.ProjectName = LoadPreviousNetPropertyOrDefault(nameof(ProjectName), result.ProjectName);
|
||||
result.Port = LoadPreviousNetPropertyOrDefault("ServerPort", result.Port);
|
||||
@@ -53,7 +53,7 @@ namespace TGS.Server.Service
|
||||
//try it the simple way first
|
||||
try
|
||||
{
|
||||
var result = (T)Properties.Settings.Default.GetPreviousVersion(property);
|
||||
var result = (T)TGServerService.Properties.Settings.Default.GetPreviousVersion(property);
|
||||
return result == null ? defaultValue : result;
|
||||
}
|
||||
catch
|
||||
@@ -65,7 +65,7 @@ namespace TGS.Server.Service
|
||||
//Which means we can never fucking delete config settings
|
||||
//Which is fucking retarded
|
||||
//This hooks into the settings provider and forces it to load it anyway
|
||||
var Config = Properties.Settings.Default;
|
||||
var Config = TGServerService.Properties.Settings.Default;
|
||||
var Provider = Config.Properties[nameof(Config.SettingsVersion)].Provider; //nameof for sanity
|
||||
|
||||
var sp = new SettingsProperty(property)
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
|
||||
namespace TGS.Server.Service
|
||||
namespace TGS.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// Various events and their IDs in no particular order. Found in the Windows event log. These key incremented by 100 and are guaranteed to never be reused in the future. In the windows event viewer, these IDs will be offset by the <see cref="ServerInstance.LoggingID"/> to distinguish events between instances. Each event ID may be information, a warning, or error and will be documented accordingly. Warnings will occur due to user, data, or network errors. Errors will occur due to filesystem errors or hard faults
|
||||
@@ -76,11 +76,11 @@ namespace TGS.Server.Service
|
||||
/// </summary>
|
||||
DMCompileCancel = 1600,
|
||||
/// <summary>
|
||||
/// Error: Failed to reattach the watchdog to a running DreamDaemon instance after a <see cref="Service"/> update
|
||||
/// Error: Failed to reattach the watchdog to a running DreamDaemon instance after a <see cref="Server"/> update
|
||||
/// </summary>
|
||||
DDReattachFail = 1700,
|
||||
/// <summary>
|
||||
/// Info: Successfully reattached the watchdog to a running DreamDaemon instance after a <see cref="Service"/> update
|
||||
/// Info: Successfully reattached the watchdog to a running DreamDaemon instance after a <see cref="Server"/> update
|
||||
/// </summary>
|
||||
DDReattachSuccess = 1800,
|
||||
/// <summary>
|
||||
@@ -261,7 +261,7 @@ namespace TGS.Server.Service
|
||||
/// </summary>
|
||||
InstanceInitializationFailure = 6000,
|
||||
/// <summary>
|
||||
/// Error: When an exception occurs while the <see cref="Service"/> is stopping
|
||||
/// Error: When an exception occurs while the <see cref="Server"/> is stopping
|
||||
/// </summary>
|
||||
ServiceShutdownFail = 6100,
|
||||
/// <summary>
|
||||
@@ -1,21 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.ServiceProcess;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TGS.Server.Service
|
||||
namespace TGS.Server
|
||||
{
|
||||
static class Program
|
||||
/// <summary>
|
||||
/// Generic helpers for the <see cref="Server"/>
|
||||
/// </summary>
|
||||
static class Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Entry point to the program
|
||||
/// </summary>
|
||||
static void Main() {
|
||||
using (var S = new Service())
|
||||
ServiceBase.Run(S);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy a file from <paramref name="source"/> to <paramref name="dest"/>, but first ensure the destination directory exists
|
||||
/// </summary>
|
||||
@@ -0,0 +1,39 @@
|
||||
namespace TGS.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// Used for writing logs to a provider
|
||||
/// </summary>
|
||||
public interface ILogger
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes information to the log
|
||||
/// </summary>
|
||||
/// <param name="message">The log message</param>
|
||||
/// <param name="id">The <see cref="EventID"/> of the message</param>
|
||||
/// <param name="loggingID">The 0-99 ID of the log source</param>
|
||||
void WriteInfo(string message, EventID id, byte loggingID);
|
||||
|
||||
/// <summary>
|
||||
/// Writes an error to the log
|
||||
/// </summary>
|
||||
/// <param name="message">The log message</param>
|
||||
/// <param name="id">The <see cref="EventID"/> of the message</param>
|
||||
/// <param name="loggingID">The 0-99 ID of the log source</param>
|
||||
void WriteError(string message, EventID id, byte loggingID);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a warning to the log
|
||||
/// </summary>
|
||||
/// <param name="message">The log message</param>
|
||||
/// <param name="id">The <see cref="EventID"/> of the message</param>
|
||||
/// <param name="loggingID">The 0-99 ID of the log source</param>
|
||||
void WriteWarning(string message, EventID id, byte loggingID);
|
||||
/// <summary>
|
||||
/// Writes an access event to the log
|
||||
/// </summary>
|
||||
/// <param name="username">The (un)authenticated Windows user's name</param>
|
||||
/// <param name="authSuccess"><see langword="true"/> if <paramref name="username"/> authenticated sucessfully, <see langword="false"/> otherwise</param>
|
||||
/// <param name="loggingID">The 0-99 ID of the log source</param>
|
||||
void WriteAccess(string username, bool authSuccess, byte loggingID);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Web.Script.Serialization;
|
||||
using TGS.Interface;
|
||||
|
||||
namespace TGS.Server.Service
|
||||
namespace TGS.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// Configuration settings for a <see cref="ServerInstance"/>
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
|
||||
namespace TGS.Server.Service
|
||||
namespace TGS.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// Type of chat message, these may be OR'd together
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace TGS.Server.Service
|
||||
namespace TGS.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers to <see cref="Suspend(Process)"/>ing and <see cref="Resume(Process)"/> a <see cref="Process"/>. Lightly massaged code from https://stackoverflow.com/a/13109774. Documentation linked from MSDN on 20/10/2017
|
||||
@@ -0,0 +1,16 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("TGStation Server")]
|
||||
[assembly: AssemblyDescription("Server management suite for running BYOND games")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("f32eda25-0855-411c-af5e-f0d042917e2d")]
|
||||
Generated
+1
-1
@@ -8,7 +8,7 @@
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace TGS.Server.Service.Properties {
|
||||
namespace TGServerService.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="TGS.Server.Service.Properties" GeneratedClassName="Settings">
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="TGS.Server.Properties" GeneratedClassName="Settings">
|
||||
<Profiles />
|
||||
<Settings>
|
||||
<Setting Name="PythonPath" Type="System.String" Scope="User">
|
||||
@@ -4,7 +4,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Web.Script.Serialization;
|
||||
|
||||
namespace TGS.Server.Service
|
||||
namespace TGS.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// Repository specific information for a <see cref="ServerInstance"/>
|
||||
+2
-3
@@ -1,12 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Security.Principal;
|
||||
using System.ServiceModel;
|
||||
using TGS.Interface.Components;
|
||||
|
||||
namespace TGS.Server.Service
|
||||
namespace TGS.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="ServiceAuthorizationManager"/> used to determine only if the caller is an admin
|
||||
@@ -33,7 +32,7 @@ namespace TGS.Server.Service
|
||||
if (LastSeenUser != user)
|
||||
{
|
||||
LastSeenUser = user;
|
||||
Service.WriteEntry(String.Format("Root access from: {0}", user), EventID.Authentication, authSuccess ? EventLogEntryType.SuccessAudit : EventLogEntryType.FailureAudit, Service.LoggingID);
|
||||
Server.Logger.WriteAccess(String.Format("Root access from: {0}", user), authSuccess, Server.LoggingID);
|
||||
}
|
||||
return authSuccess;
|
||||
}
|
||||
@@ -0,0 +1,704 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Security.Principal;
|
||||
using System.ServiceModel;
|
||||
using TGS.Interface;
|
||||
using TGS.Interface.Components;
|
||||
|
||||
namespace TGS.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// The windows service the application runs as
|
||||
/// </summary>
|
||||
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
|
||||
public sealed class Server : ITGSService, ITGConnectivity, ITGLanding, ITGInstanceManager, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// The logging ID used for <see cref="Server"/> events
|
||||
/// </summary>
|
||||
public const byte LoggingID = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The service version <see cref="string"/> based on the <see cref="FileVersionInfo"/>
|
||||
/// </summary>
|
||||
public static readonly string VersionString = "/tg/station 13 Server Service v" + FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion;
|
||||
|
||||
/// <summary>
|
||||
/// Singleton <see cref="ILogger"/>
|
||||
/// </summary>
|
||||
public static ILogger Logger { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Cancels WCF's user impersonation to allow clean access to writing log files
|
||||
/// </summary>
|
||||
public static void CancelImpersonation()
|
||||
{
|
||||
WindowsIdentity.Impersonate(IntPtr.Zero);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks an <paramref name="instanceName"/> for illegal characters
|
||||
/// </summary>
|
||||
/// <param name="instanceName">The <see cref="ServerInstance"/> name to check</param>
|
||||
/// <returns><see langword="null"/> if <paramref name="instanceName"/> contains no illegal characters, error message otherwise</returns>
|
||||
static string CheckInstanceName(string instanceName)
|
||||
{
|
||||
char[] bannedCharacters = { ';', '&', '=', '%' };
|
||||
foreach (var I in bannedCharacters)
|
||||
if (instanceName.Contains(I.ToString()))
|
||||
return "Instance names may not contain the following characters: ';', '&', '=', or '%'";
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The WCF host that contains <see cref="ITGSService"/> connects to
|
||||
/// </summary>
|
||||
ServiceHost serviceHost;
|
||||
/// <summary>
|
||||
/// Map of <see cref="InstanceConfig.Name"/> to the respective <see cref="ServiceHost"/> hosting the <see cref="ServerInstance"/>
|
||||
/// </summary>
|
||||
IDictionary<string, ServiceHost> hosts;
|
||||
/// <summary>
|
||||
/// List of <see cref="ServerInstance.LoggingID"/>s in use
|
||||
/// </summary>
|
||||
IList<int> UsedLoggingIDs = new List<int>();
|
||||
|
||||
/// <summary>
|
||||
/// Construct a <see cref="Server"/>
|
||||
/// </summary>
|
||||
/// <param name="args">Command line arguments for the <see cref="Server"/></param>
|
||||
/// <param name="logger">The <see cref="ILogger"/> to use</param>
|
||||
public Server(string[] args, ILogger logger)
|
||||
{
|
||||
Environment.CurrentDirectory = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Assembly.GetExecutingAssembly().GetName().Name)).FullName; //MOVE THIS POINTER BECAUSE ONE TIME I ALMOST ACCIDENTALLY NUKED MYSELF BY REFACTORING! http://imgur.com/zvGEpJD.png
|
||||
|
||||
SetupConfig();
|
||||
|
||||
ChangePortFromCommandLine(args);
|
||||
|
||||
SetupService();
|
||||
|
||||
SetupInstances();
|
||||
|
||||
OnlineAllHosts();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Migrates the .NET config from <paramref name="oldVersion"/> to <paramref name="oldVersion"/> + 1
|
||||
/// </summary>
|
||||
/// <param name="oldVersion">The version to migrate from</param>
|
||||
void MigrateSettings(int oldVersion)
|
||||
{
|
||||
var Config = TGServerService.Properties.Settings.Default;
|
||||
switch (oldVersion)
|
||||
{
|
||||
case 6: //switch to per-instance configs
|
||||
var IC = DeprecatedInstanceConfig.CreateFromNETSettings();
|
||||
IC.Save();
|
||||
Config.InstancePaths.Add(IC.Directory);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enumerates configured <see cref="IInstanceConfig"/>s. Detaches those that fail to load
|
||||
/// </summary>
|
||||
/// <returns>Each configured <see cref="IInstanceConfig"/></returns>
|
||||
IEnumerable<IInstanceConfig> GetInstanceConfigs()
|
||||
{
|
||||
var pathsToRemove = new List<string>();
|
||||
lock (this)
|
||||
{
|
||||
var IPS = TGServerService.Properties.Settings.Default.InstancePaths;
|
||||
foreach (var I in IPS)
|
||||
{
|
||||
IInstanceConfig ic;
|
||||
try
|
||||
{
|
||||
ic = InstanceConfig.Load(I);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.WriteError(String.Format("Unable load instance config at path {0}. Error: {1} Detaching...", I, e.ToString()), EventID.InstanceInitializationFailure, LoggingID);
|
||||
pathsToRemove.Add(I);
|
||||
continue;
|
||||
}
|
||||
yield return ic;
|
||||
}
|
||||
foreach (var I in pathsToRemove)
|
||||
IPS.Remove(I);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides and saves the configured <see cref="TGServerService.Properties.Settings.RemoteAccessPort"/> if requested by command line parameters
|
||||
/// </summary>
|
||||
/// <param name="args">The command line parameters for the <see cref="Server"/></param>
|
||||
void ChangePortFromCommandLine(string[] args)
|
||||
{
|
||||
var Config = TGServerService.Properties.Settings.Default;
|
||||
|
||||
for (var I = 0; I < args.Length - 1; ++I)
|
||||
if (args[I].ToLower() == "-port")
|
||||
{
|
||||
try
|
||||
{
|
||||
var res = Convert.ToUInt16(args[I + 1]);
|
||||
if (res == 0)
|
||||
throw new Exception("Cannot bind to port 0");
|
||||
Config.RemoteAccessPort = res;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception("Invalid argument for \"-port\"", e);
|
||||
}
|
||||
Config.Save();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes some changes to the <see cref="TGServerService.Properties.Settings"/> that always need to be done.
|
||||
/// </summary>
|
||||
void PrePrepConfig()
|
||||
{
|
||||
var Config = TGServerService.Properties.Settings.Default;
|
||||
|
||||
if (Config.InstancePaths == null)
|
||||
Config.InstancePaths = new StringCollection();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Upgrades up the service configuration
|
||||
/// </summary>
|
||||
void SetupConfig()
|
||||
{
|
||||
var Config = TGServerService.Properties.Settings.Default;
|
||||
if (Config.UpgradeRequired)
|
||||
{
|
||||
var newVersion = Config.SettingsVersion;
|
||||
Config.Upgrade();
|
||||
|
||||
PrePrepConfig();
|
||||
|
||||
for (var oldVersion = Config.SettingsVersion; oldVersion < newVersion; ++oldVersion)
|
||||
MigrateSettings(oldVersion);
|
||||
|
||||
Config.SettingsVersion = newVersion;
|
||||
|
||||
Config.UpgradeRequired = false;
|
||||
Config.Save();
|
||||
}
|
||||
else
|
||||
PrePrepConfig();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the <see cref="ServiceHost"/> for <see cref="ITGSService"/>
|
||||
/// </summary>
|
||||
void SetupService()
|
||||
{
|
||||
serviceHost = CreateHost(this, ServerInterface.MasterInterfaceName);
|
||||
foreach (var I in ServerInterface.ValidServiceInterfaces)
|
||||
AddEndpoint(serviceHost, I);
|
||||
serviceHost.Authorization.ServiceAuthorizationManager = new RootAuthorizationManager(); //only admins can diddle us
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens all created <see cref="ServiceHost"/>s
|
||||
/// </summary>
|
||||
void OnlineAllHosts()
|
||||
{
|
||||
serviceHost.Open();
|
||||
foreach (var I in hosts)
|
||||
I.Value.Open();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ServiceHost"/> for <paramref name="singleton"/> using the default pipe, CloseTimeout for the <see cref="ServiceHost"/>, and the configured <see cref="TGServerService.Properties.Settings.RemoteAccessPort"/>
|
||||
/// </summary>
|
||||
/// <param name="singleton">The <see cref="ServiceHost.SingletonInstance"/></param>
|
||||
/// <param name="endpointPostfix">The URL to access components on the <see cref="ServiceHost"/></param>
|
||||
/// <returns>The created <see cref="ServiceHost"/></returns>
|
||||
static ServiceHost CreateHost(object singleton, string endpointPostfix)
|
||||
{
|
||||
return new ServiceHost(singleton, new Uri[] { new Uri(String.Format("net.pipe://localhost/{0}", endpointPostfix)), new Uri(String.Format("https://localhost:{0}/{1}", TGServerService.Properties.Settings.Default.RemoteAccessPort, endpointPostfix)) })
|
||||
{
|
||||
CloseTimeout = new TimeSpan(0, 0, 5)
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates <see cref="ServiceHost"/>s for all <see cref="ServerInstance"/>s as listed in <see cref="TGServerService.Properties.Settings.InstancePaths"/>, detaches bad ones
|
||||
/// </summary>
|
||||
void SetupInstances()
|
||||
{
|
||||
hosts = new Dictionary<string, ServiceHost>();
|
||||
var pathsToRemove = new List<string>();
|
||||
var seenNames = new List<string>();
|
||||
foreach (var I in GetInstanceConfigs())
|
||||
{
|
||||
if (seenNames.Contains(I.Name))
|
||||
{
|
||||
Logger.WriteError(String.Format("Instance at {0} has a duplicate name! Detaching...", I.Directory), EventID.InstanceInitializationFailure, LoggingID);
|
||||
pathsToRemove.Add(I.Directory);
|
||||
}
|
||||
if (I.Enabled && SetupInstance(I) == null)
|
||||
pathsToRemove.Add(I.Directory);
|
||||
else
|
||||
seenNames.Add(I.Name);
|
||||
}
|
||||
foreach (var I in pathsToRemove)
|
||||
TGServerService.Properties.Settings.Default.InstancePaths.Remove(I);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unlocks a <see cref="ServerInstance.LoggingID"/> acquired with <see cref="LockLoggingID"/>
|
||||
/// </summary>
|
||||
/// <param name="ID">The <see cref="ServerInstance.LoggingID"/> to unlock</param>
|
||||
void UnlockLoggingID(byte ID)
|
||||
{
|
||||
lock (UsedLoggingIDs)
|
||||
{
|
||||
UsedLoggingIDs.Remove(ID);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and locks a <see cref="ServerInstance.LoggingID"/>
|
||||
/// </summary>
|
||||
/// <returns>A logging ID for the <see cref="ServerInstance"/> must be released using <see cref="UnlockLoggingID(byte)"/></returns>
|
||||
byte LockLoggingID()
|
||||
{
|
||||
lock (UsedLoggingIDs)
|
||||
{
|
||||
for (byte I = 1; I < 100; ++I)
|
||||
if (!UsedLoggingIDs.Contains(I))
|
||||
{
|
||||
UsedLoggingIDs.Add(I);
|
||||
return I;
|
||||
}
|
||||
}
|
||||
throw new Exception("All logging IDs in use!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and starts a <see cref="ServiceHost"/> for a <see cref="ServerInstance"/> at <paramref name="config"/>
|
||||
/// </summary>
|
||||
/// <param name="config">The <see cref="IInstanceConfig"/> for the <see cref="ServerInstance"/></param>
|
||||
/// <returns>The inactive <see cref="ServiceHost"/> on success, <see langword="null"/> on failure</returns>
|
||||
ServiceHost SetupInstance(IInstanceConfig config)
|
||||
{
|
||||
ServerInstance instance;
|
||||
string instanceName;
|
||||
try
|
||||
{
|
||||
if (hosts.ContainsKey(config.Directory))
|
||||
{
|
||||
var datInstance = ((ServerInstance)hosts[config.Directory].SingletonInstance);
|
||||
Logger.WriteError(String.Format("Unable to start instance at path {0}. Has the same name as instance at path {1}. Detaching...", config.Directory, datInstance.ServerDirectory()), EventID.InstanceInitializationFailure, LoggingID);
|
||||
return null;
|
||||
}
|
||||
if (!config.Enabled)
|
||||
return null;
|
||||
var ID = LockLoggingID();
|
||||
Logger.WriteInfo(String.Format("Instance {0} ({1}) assigned logging ID {2}", config.Name, config.Directory, ID), EventID.InstanceIDAssigned, ID);
|
||||
instanceName = config.Name;
|
||||
instance = new ServerInstance(config, ID);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.WriteError(String.Format("Unable to start instance at path {0}. Detaching... Error: {1}", config.Directory, e.ToString()), EventID.InstanceInitializationFailure, LoggingID);
|
||||
return null;
|
||||
}
|
||||
|
||||
var host = CreateHost(instance, String.Format("{0}/{1}", ServerInterface.InstanceInterfaceName, instanceName));
|
||||
hosts.Add(instanceName, host);
|
||||
|
||||
foreach (var J in ServerInterface.ValidInstanceInterfaces)
|
||||
AddEndpoint(host, J);
|
||||
|
||||
host.Authorization.ServiceAuthorizationManager = instance;
|
||||
return host;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a WCF endpoint for a component <paramref name="typetype"/>
|
||||
/// </summary>
|
||||
/// <param name="host">The service host to add the component to</param>
|
||||
/// <param name="typetype">The type of the component</param>
|
||||
void AddEndpoint(ServiceHost host, Type typetype)
|
||||
{
|
||||
var bindingName = typetype.Name;
|
||||
host.AddServiceEndpoint(typetype, new NetNamedPipeBinding() { SendTimeout = new TimeSpan(0, 0, 30), MaxReceivedMessageSize = ServerInterface.TransferLimitLocal }, bindingName);
|
||||
var httpsBinding = new WSHttpBinding()
|
||||
{
|
||||
SendTimeout = new TimeSpan(0, 0, 40),
|
||||
MaxReceivedMessageSize = ServerInterface.TransferLimitRemote
|
||||
};
|
||||
var requireAuth = typetype.Name != typeof(ITGConnectivity).Name;
|
||||
httpsBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
|
||||
httpsBinding.Security.Mode = requireAuth ? SecurityMode.TransportWithMessageCredential : SecurityMode.Transport; //do not require auth for a connectivity check
|
||||
httpsBinding.Security.Message.ClientCredentialType = requireAuth ? MessageCredentialType.UserName : MessageCredentialType.None;
|
||||
host.AddServiceEndpoint(typetype, httpsBinding, bindingName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shuts down all active <see cref="ServiceHost"/>s and calls <see cref="IDisposable.Dispose"/> on it's <see cref="ServerInstance"/>
|
||||
/// </summary>
|
||||
void OnStop()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var I in hosts)
|
||||
{
|
||||
var host = I.Value;
|
||||
var instance = (ServerInstance)host.SingletonInstance;
|
||||
host.Close();
|
||||
instance.Dispose();
|
||||
UnlockLoggingID(instance.LoggingID);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.WriteError(e.ToString(), EventID.ServiceShutdownFail, LoggingID);
|
||||
}
|
||||
serviceHost.Close();
|
||||
}
|
||||
TGServerService.Properties.Settings.Default.Save();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void VerifyConnection() { }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void PrepareForUpdate()
|
||||
{
|
||||
foreach (var I in hosts)
|
||||
((ServerInstance)I.Value.SingletonInstance).Reattach(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ushort RemoteAccessPort()
|
||||
{
|
||||
return TGServerService.Properties.Settings.Default.RemoteAccessPort;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string SetRemoteAccessPort(ushort port)
|
||||
{
|
||||
if (port == 0)
|
||||
return "Cannot bind to port 0";
|
||||
TGServerService.Properties.Settings.Default.RemoteAccessPort = port;
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Version()
|
||||
{
|
||||
return VersionString;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool SetPythonPath(string path)
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
return false;
|
||||
TGServerService.Properties.Settings.Default.PythonPath = Path.GetFullPath(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string PythonPath()
|
||||
{
|
||||
return TGServerService.Properties.Settings.Default.PythonPath;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IList<InstanceMetadata> ListInstances()
|
||||
{
|
||||
var result = new List<InstanceMetadata>();
|
||||
lock (this)
|
||||
foreach (var ic in GetInstanceConfigs())
|
||||
result.Add(new InstanceMetadata
|
||||
{
|
||||
Name = ic.Name,
|
||||
Path = ic.Directory,
|
||||
Enabled = ic.Enabled,
|
||||
LoggingID = (byte)(ic.Enabled ? ((ServerInstance)hosts[ic.Name].SingletonInstance).LoggingID : 0)
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string CreateInstance(string Name, string path)
|
||||
{
|
||||
path = Helpers.NormalizePath(path);
|
||||
var res = CheckInstanceName(Name);
|
||||
if (res != null)
|
||||
return res;
|
||||
if (File.Exists(path) || Directory.Exists(path))
|
||||
return "Cannot create instance at pre-existing path!";
|
||||
var Config = TGServerService.Properties.Settings.Default;
|
||||
lock (this)
|
||||
{
|
||||
if (Config.InstancePaths.Contains(path))
|
||||
return String.Format("Instance at {0} already exists!", path);
|
||||
foreach (var oic in GetInstanceConfigs())
|
||||
if (Name == oic.Name)
|
||||
return String.Format("Instance named {0} already exists!", oic.Name);
|
||||
IInstanceConfig ic;
|
||||
try
|
||||
{
|
||||
ic = new InstanceConfig(path)
|
||||
{
|
||||
Name = Name
|
||||
};
|
||||
Directory.CreateDirectory(path);
|
||||
ic.Save();
|
||||
TGServerService.Properties.Settings.Default.InstancePaths.Add(path);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return e.ToString();
|
||||
}
|
||||
return SetupOneInstance(ic);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts and onlines an instance located at <paramref name="config"/>
|
||||
/// </summary>
|
||||
/// <param name="config">The <see cref="IInstanceConfig"/> for the <see cref="ServerInstance"/></param>
|
||||
/// <returns><see langword="null"/> on success, error message on failure</returns>
|
||||
string SetupOneInstance(IInstanceConfig config)
|
||||
{
|
||||
if (!config.Enabled)
|
||||
return null;
|
||||
try
|
||||
{
|
||||
var host = SetupInstance(config);
|
||||
if (host != null)
|
||||
host.Open();
|
||||
else
|
||||
lock (this)
|
||||
TGServerService.Properties.Settings.Default.InstancePaths.Remove(config.Directory);
|
||||
return null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return "Instance set up but an error occurred while starting it: " + e.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string ImportInstance(string path)
|
||||
{
|
||||
path = Helpers.NormalizePath(path);
|
||||
var Config = TGServerService.Properties.Settings.Default;
|
||||
lock (this)
|
||||
{
|
||||
if (Config.InstancePaths.Contains(path))
|
||||
return String.Format("Instance at {0} already exists!", path);
|
||||
if(!Directory.Exists(path))
|
||||
return String.Format("There is no instance located at {0}!", path);
|
||||
IInstanceConfig ic;
|
||||
try
|
||||
{
|
||||
ic = InstanceConfig.Load(path);
|
||||
foreach(var oic in GetInstanceConfigs())
|
||||
if(ic.Name == oic.Name)
|
||||
return String.Format("Instance named {0} already exists!", oic.Name);
|
||||
ic.Save();
|
||||
TGServerService.Properties.Settings.Default.InstancePaths.Add(path);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return e.ToString();
|
||||
}
|
||||
return SetupOneInstance(ic);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool InstanceEnabled(string Name)
|
||||
{
|
||||
lock(this)
|
||||
{
|
||||
return hosts.ContainsKey(Name);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string SetInstanceEnabled(string Name, bool enabled)
|
||||
{
|
||||
return SetInstanceEnabledImpl(Name, enabled, out string path);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sets a <see cref="ServerInstance"/>'s enabled status
|
||||
/// </summary>
|
||||
/// <param name="Name">The <see cref="ServerInstance"/> whom's status should be changed</param>
|
||||
/// <param name="enabled"><see langword="true"/> to enable the <see cref="ServerInstance"/>, <see langword="false"/> to disable it</param>
|
||||
/// <param name="path">The path to the modified <see cref="ServerInstance"/></param>
|
||||
/// <returns><see langword="null"/> on success, error message on failure</returns>
|
||||
string SetInstanceEnabledImpl(string Name, bool enabled, out string path)
|
||||
{
|
||||
path = null;
|
||||
lock (this)
|
||||
{
|
||||
var hostIsOnline = hosts.ContainsKey(Name);
|
||||
if (enabled)
|
||||
{
|
||||
if (hostIsOnline)
|
||||
return null;
|
||||
foreach (var ic in GetInstanceConfigs())
|
||||
if (ic.Name == Name)
|
||||
{
|
||||
path = ic.Directory;
|
||||
ic.Enabled = true;
|
||||
ic.Save();
|
||||
return SetupOneInstance(ic);
|
||||
}
|
||||
return String.Format("Instance {0} does not exist!", Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!hostIsOnline)
|
||||
return null;
|
||||
var host = hosts[Name];
|
||||
hosts.Remove(Name);
|
||||
var inst = (ServerInstance)host.SingletonInstance;
|
||||
host.Close();
|
||||
path = inst.ServerDirectory();
|
||||
inst.Offline();
|
||||
inst.Dispose();
|
||||
UnlockLoggingID(inst.LoggingID);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string RenameInstance(string name, string new_name)
|
||||
{
|
||||
if (name == new_name)
|
||||
return null;
|
||||
var res = CheckInstanceName(new_name);
|
||||
if (res != null)
|
||||
return res;
|
||||
lock (this)
|
||||
{
|
||||
//we have to check em all anyway
|
||||
IInstanceConfig the_droid_were_looking_for = null;
|
||||
foreach (var ic in GetInstanceConfigs())
|
||||
if (ic.Name == name)
|
||||
{
|
||||
the_droid_were_looking_for = ic;
|
||||
break;
|
||||
}
|
||||
else if (ic.Name == new_name)
|
||||
return String.Format("There is already another instance named {0}!", new_name);
|
||||
if (the_droid_were_looking_for == null)
|
||||
return String.Format("There is no instance named {0}!", name);
|
||||
var ie = InstanceEnabled(name);
|
||||
if(ie)
|
||||
SetInstanceEnabled(name, false);
|
||||
the_droid_were_looking_for.Name = new_name;
|
||||
string result = "";
|
||||
try
|
||||
{
|
||||
the_droid_were_looking_for.Save();
|
||||
result = null;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
result = "Could not save instance config! Error: " + e.ToString();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (ie)
|
||||
{
|
||||
var resRestore = SetInstanceEnabled(new_name, true);
|
||||
if (resRestore != null)
|
||||
result = (result + " " + resRestore).Trim();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string DetachInstance(string name)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
var res = SetInstanceEnabledImpl(name, false, out string path);
|
||||
if (res != null)
|
||||
return res;
|
||||
if (path == null) //gotta find it ourselves
|
||||
foreach (var ic in GetInstanceConfigs())
|
||||
if (ic.Name == name)
|
||||
{
|
||||
path = ic.Directory;
|
||||
break;
|
||||
}
|
||||
if (path == null)
|
||||
return String.Format("No instance named {0} exists!", name);
|
||||
TGServerService.Properties.Settings.Default.InstancePaths.Remove(path);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#region IDisposable Support
|
||||
/// <summary>
|
||||
/// To detect redundant <see cref="Dispose()"/> calls
|
||||
/// </summary>
|
||||
private bool disposedValue = false;
|
||||
|
||||
/// <summary>
|
||||
/// Implements the <see cref="IDisposable"/> pattern. Calls <see cref="OnStop"/>
|
||||
/// </summary>
|
||||
/// <param name="disposing"><see langword="true"/> if <see cref="Dispose()"/> was called manually, <see langword="false"/> if it was from the finalizer</param>
|
||||
void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
OnStop();
|
||||
}
|
||||
|
||||
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
|
||||
// TODO: set large fields to null.
|
||||
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
|
||||
// ~Server() {
|
||||
// // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
|
||||
// Dispose(false);
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Implements the <see cref="IDisposable"/> pattern
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
|
||||
Dispose(true);
|
||||
// TODO: uncomment the following line if the finalizer is overridden above.
|
||||
// GC.SuppressFinalize(this);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -6,7 +6,7 @@ using System.Threading;
|
||||
using TGS.Interface;
|
||||
using TGS.Interface.Components;
|
||||
|
||||
namespace TGS.Server.Service
|
||||
namespace TGS.Server
|
||||
{
|
||||
//note this only works with MACHINE LOCAL groups and admins for now
|
||||
//if someone wants AD shit, code it yourself
|
||||
@@ -26,7 +26,7 @@ namespace TGS.Server.Service
|
||||
string LastSeenUser;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="SecurityIdentifier"/> of the account the <see cref="Service"/> is running as
|
||||
/// The <see cref="SecurityIdentifier"/> of the account the <see cref="Server"/> is running as
|
||||
/// </summary>
|
||||
readonly SecurityIdentifier ServiceSID = WindowsIdentity.GetCurrent().User;
|
||||
|
||||
@@ -8,7 +8,7 @@ using System.Threading;
|
||||
using TGS.Interface;
|
||||
using TGS.Interface.Components;
|
||||
|
||||
namespace TGS.Server.Service
|
||||
namespace TGS.Server
|
||||
{
|
||||
sealed partial class ServerInstance : ITGByond
|
||||
{
|
||||
@@ -88,7 +88,7 @@ namespace TGS.Server.Service
|
||||
//linger not
|
||||
if (File.Exists(rrdp))
|
||||
File.Delete(rrdp);
|
||||
Program.DeleteDirectory(RelativePath(StagingDirectory));
|
||||
Helpers.DeleteDirectory(RelativePath(StagingDirectory));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -326,9 +326,9 @@ namespace TGS.Server.Service
|
||||
try
|
||||
{
|
||||
var rbd = RelativePath(ByondDirectory);
|
||||
Program.DeleteDirectory(rbd);
|
||||
Helpers.DeleteDirectory(rbd);
|
||||
Directory.Move(RelativePath(StagingDirectoryInner), rbd);
|
||||
Program.DeleteDirectory(RelativePath(StagingDirectory));
|
||||
Helpers.DeleteDirectory(RelativePath(StagingDirectory));
|
||||
lastError = null;
|
||||
SendMessage("BYOND: Update completed!", MessageType.DeveloperInfo);
|
||||
WriteInfo(String.Format("BYOND update {0} completed!", GetVersion(ByondVersion.Installed)), EventID.BYONDUpdateComplete);
|
||||
@@ -2,12 +2,12 @@
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Script.Serialization;
|
||||
using TGS.Server.Service.ChatCommands;
|
||||
using TGS.Server.Service.ChatProviders;
|
||||
using TGS.Server.ChatCommands;
|
||||
using TGS.Server.ChatProviders;
|
||||
using TGS.Interface;
|
||||
using TGS.Interface.Components;
|
||||
|
||||
namespace TGS.Server.Service
|
||||
namespace TGS.Server
|
||||
{
|
||||
sealed partial class ServerInstance : ITGChat
|
||||
{
|
||||
@@ -114,7 +114,7 @@ namespace TGS.Server.Service
|
||||
|
||||
var rawdata = new JavaScriptSerializer().Serialize(infosList);
|
||||
|
||||
Config.ChatProviderData = Helpers.EncryptData(rawdata, out string entrp);
|
||||
Config.ChatProviderData = Interface.Helpers.EncryptData(rawdata, out string entrp);
|
||||
Config.ChatProviderEntropy = entrp;
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ namespace TGS.Server.Service
|
||||
string plaintext;
|
||||
try
|
||||
{
|
||||
plaintext = Helpers.DecryptData(rawdata, Config.ChatProviderEntropy);
|
||||
plaintext = Interface.Helpers.DecryptData(rawdata, Config.ChatProviderEntropy);
|
||||
|
||||
var lists = new JavaScriptSerializer().Deserialize<List<List<string>>>(plaintext);
|
||||
var output = new List<ChatSetupInfo>(lists.Count);
|
||||
+5
-5
@@ -9,7 +9,7 @@ using System.Threading;
|
||||
using TGS.Interface;
|
||||
using TGS.Interface.Components;
|
||||
|
||||
namespace TGS.Server.Service
|
||||
namespace TGS.Server
|
||||
{
|
||||
sealed partial class ServerInstance : ITGCompiler
|
||||
{
|
||||
@@ -178,7 +178,7 @@ namespace TGS.Server.Service
|
||||
{
|
||||
SendMessage("DM: Setting up symlinks...", MessageType.DeveloperInfo);
|
||||
CleanGameFolder();
|
||||
Program.DeleteDirectory(RelativePath(GameDir));
|
||||
Helpers.DeleteDirectory(RelativePath(GameDir));
|
||||
|
||||
Directory.CreateDirectory(RelativePath(GameDirA));
|
||||
Directory.CreateDirectory(RelativePath(GameDirB));
|
||||
@@ -350,7 +350,7 @@ namespace TGS.Server.Service
|
||||
var deleteExcludeList = new List<string> { BridgeDLLName };
|
||||
deleteExcludeList.AddRange(Config.StaticDirectoryPaths);
|
||||
deleteExcludeList.AddRange(Config.DLLPaths);
|
||||
Program.DeleteDirectory(resurrectee, true, deleteExcludeList);
|
||||
Helpers.DeleteDirectory(resurrectee, true, deleteExcludeList);
|
||||
|
||||
|
||||
Directory.CreateDirectory(resurrectee + "/.git/logs");
|
||||
@@ -372,11 +372,11 @@ namespace TGS.Server.Service
|
||||
CreateSymlink(Path.Combine(resurrectee, BridgeDLLName), RelativePath(BridgeDLLName));
|
||||
|
||||
deleteExcludeList.Add(".git");
|
||||
Program.CopyDirectory(RelativePath(RepoPath), resurrectee, deleteExcludeList);
|
||||
Helpers.CopyDirectory(RelativePath(RepoPath), resurrectee, deleteExcludeList);
|
||||
CurrentSha = GetHead(false, out string error);
|
||||
//just the tip
|
||||
const string GitLogsDir = "/.git/logs";
|
||||
Program.CopyDirectory(RelativePath(RepoPath + GitLogsDir), resurrectee + GitLogsDir);
|
||||
Helpers.CopyDirectory(RelativePath(RepoPath + GitLogsDir), resurrectee + GitLogsDir);
|
||||
try
|
||||
{
|
||||
File.Copy(RelativePath(PRJobFile), Path.Combine(resurrectee, PRJobFile));
|
||||
@@ -4,7 +4,7 @@ using System.IO;
|
||||
using System.ServiceModel;
|
||||
using TGS.Interface.Components;
|
||||
|
||||
namespace TGS.Server.Service
|
||||
namespace TGS.Server
|
||||
{
|
||||
//knobs and such
|
||||
sealed partial class ServerInstance : ITGConfig
|
||||
@@ -75,7 +75,7 @@ namespace TGS.Server.Service
|
||||
}
|
||||
|
||||
var output = File.ReadAllText(path);
|
||||
Service.CancelImpersonation();
|
||||
Server.CancelImpersonation();
|
||||
WriteInfo("Read of " + path, EventID.StaticRead);
|
||||
error = null;
|
||||
unauthorized = false;
|
||||
@@ -92,7 +92,7 @@ namespace TGS.Server.Service
|
||||
catch (Exception e)
|
||||
{
|
||||
error = e.ToString();
|
||||
Service.CancelImpersonation();
|
||||
Server.CancelImpersonation();
|
||||
WriteWarning(String.Format("Read of {0} failed! Error: {1}", path, e.ToString()), EventID.StaticRead);
|
||||
unauthorized = false;
|
||||
return null;
|
||||
@@ -131,7 +131,7 @@ namespace TGS.Server.Service
|
||||
|
||||
Directory.CreateDirectory(destdir);
|
||||
File.WriteAllText(path, data);
|
||||
Service.CancelImpersonation();
|
||||
Server.CancelImpersonation();
|
||||
WriteInfo("Write to " + path, EventID.StaticWrite);
|
||||
unauthorized = false;
|
||||
return null;
|
||||
@@ -146,7 +146,7 @@ namespace TGS.Server.Service
|
||||
catch (Exception e)
|
||||
{
|
||||
unauthorized = false;
|
||||
Service.CancelImpersonation();
|
||||
Server.CancelImpersonation();
|
||||
WriteWarning(String.Format("Write of {0} failed! Error: {1}", path, e.ToString()), EventID.StaticRead);
|
||||
return e.ToString();
|
||||
}
|
||||
@@ -184,8 +184,8 @@ namespace TGS.Server.Service
|
||||
if (fi.Exists)
|
||||
File.Delete(path);
|
||||
else if (Directory.Exists(path))
|
||||
Program.DeleteDirectory(path);
|
||||
Service.CancelImpersonation();
|
||||
Helpers.DeleteDirectory(path);
|
||||
Server.CancelImpersonation();
|
||||
WriteInfo("Delete of " + path, EventID.StaticDelete);
|
||||
unauthorized = false;
|
||||
return null;
|
||||
@@ -200,7 +200,7 @@ namespace TGS.Server.Service
|
||||
catch (Exception e)
|
||||
{
|
||||
unauthorized = false;
|
||||
Service.CancelImpersonation();
|
||||
Server.CancelImpersonation();
|
||||
WriteWarning(String.Format("Delete of {0} failed! Error: {1}", path, e.ToString()), EventID.StaticRead);
|
||||
return e.ToString();
|
||||
}
|
||||
+2
-2
@@ -8,7 +8,7 @@ using System.Timers;
|
||||
using TGS.Interface;
|
||||
using TGS.Interface.Components;
|
||||
|
||||
namespace TGS.Server.Service
|
||||
namespace TGS.Server
|
||||
{
|
||||
//manages the dd window.
|
||||
//It's not possible to actually click it while starting it in CL mode, so in order to change visibility, security, etc. It restarts the process when the world reboots
|
||||
@@ -721,7 +721,7 @@ namespace TGS.Server.Service
|
||||
/// <inheritdoc />
|
||||
public string WorldAnnounce(string message)
|
||||
{
|
||||
var res = SendCommand(SCWorldAnnounce + ";message=" + Program.SanitizeTopicString(message));
|
||||
var res = SendCommand(SCWorldAnnounce + ";message=" + Helpers.SanitizeTopicString(message));
|
||||
if (res == "SUCCESS")
|
||||
return null;
|
||||
return res;
|
||||
@@ -6,11 +6,11 @@ using System.Text;
|
||||
using System.Threading;
|
||||
using System.Web.Script.Serialization;
|
||||
using System.Web.Security;
|
||||
using TGS.Server.Service.ChatCommands;
|
||||
using TGS.Server.ChatCommands;
|
||||
using TGS.Interface;
|
||||
using TGS.Interface.Components;
|
||||
|
||||
namespace TGS.Server.Service
|
||||
namespace TGS.Server
|
||||
{
|
||||
//handles talking between the world and us
|
||||
sealed partial class ServerInstance : ITGInterop
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace TGS.Server.Service
|
||||
namespace TGS.Server
|
||||
{
|
||||
// Some useful functions for triggering pre action events
|
||||
sealed partial class ServerInstance
|
||||
+8
-8
@@ -10,7 +10,7 @@ using System.Web.Script.Serialization;
|
||||
using TGS.Interface;
|
||||
using TGS.Interface.Components;
|
||||
|
||||
namespace TGS.Server.Service
|
||||
namespace TGS.Server
|
||||
{
|
||||
sealed partial class ServerInstance : ITGRepository, IDisposable
|
||||
{
|
||||
@@ -231,7 +231,7 @@ namespace TGS.Server.Service
|
||||
try
|
||||
{
|
||||
DisposeRepo();
|
||||
Program.DeleteDirectory(RelativePath(RepoPath));
|
||||
Helpers.DeleteDirectory(RelativePath(RepoPath));
|
||||
DeletePRList();
|
||||
lock (configLock)
|
||||
{
|
||||
@@ -311,9 +311,9 @@ namespace TGS.Server.Service
|
||||
newFullPath = Path.Combine(path, tempDirName);
|
||||
}
|
||||
|
||||
Program.CopyDirectory(rsd, newFullPath);
|
||||
Helpers.CopyDirectory(rsd, newFullPath);
|
||||
}
|
||||
Program.DeleteDirectory(rsd);
|
||||
Helpers.DeleteDirectory(rsd);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -352,7 +352,7 @@ namespace TGS.Server.Service
|
||||
var source = Path.Combine(RelativePath(RepoPath), I);
|
||||
var dest = Path.Combine(RelativePath(StaticDirs), I);
|
||||
if (Directory.Exists(source))
|
||||
Program.CopyDirectory(source, dest);
|
||||
Helpers.CopyDirectory(source, dest);
|
||||
else
|
||||
Directory.CreateDirectory(dest);
|
||||
}
|
||||
@@ -372,7 +372,7 @@ namespace TGS.Server.Service
|
||||
continue;
|
||||
}
|
||||
var dest = Path.Combine(RelativePath(StaticDirs), I);
|
||||
Program.CopyFileForceDirectories(source, dest, false);
|
||||
Helpers.CopyFileForceDirectories(source, dest, false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -712,7 +712,7 @@ namespace TGS.Server.Service
|
||||
//kill off the modules/ folder in .git and try again
|
||||
try
|
||||
{
|
||||
Program.DeleteDirectory(String.Format("{0}/.git/modules/{1}", RepoPath, I.Path));
|
||||
Helpers.DeleteDirectory(String.Format("{0}/.git/modules/{1}", RepoPath, I.Path));
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -1271,7 +1271,7 @@ namespace TGS.Server.Service
|
||||
return null;
|
||||
}
|
||||
|
||||
var Config = Properties.Settings.Default;
|
||||
var Config = TGServerService.Properties.Settings.Default;
|
||||
|
||||
var PythonFile = Path.Combine(Config.PythonPath, "python.exe");
|
||||
if (!File.Exists(PythonFile))
|
||||
+6
-6
@@ -4,7 +4,7 @@ using System.IO;
|
||||
using System.ServiceModel;
|
||||
using TGS.Interface.Components;
|
||||
|
||||
namespace TGS.Server.Service
|
||||
namespace TGS.Server
|
||||
{
|
||||
//I know the fact that this is one massive partial class is gonna trigger everyone
|
||||
//There really was no other succinct way to do it (<= He's lying through his teeth, don't listen to him)
|
||||
@@ -62,7 +62,7 @@ namespace TGS.Server.Service
|
||||
/// <param name="id">The <see cref="EventID"/> of the message</param>
|
||||
void WriteInfo(string message, EventID id)
|
||||
{
|
||||
Service.WriteEntry(message, id, EventLogEntryType.Information, LoggingID);
|
||||
Server.Logger.WriteInfo(message, id, LoggingID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -72,7 +72,7 @@ namespace TGS.Server.Service
|
||||
/// <param name="id">The <see cref="EventID"/> of the message</param>
|
||||
void WriteError(string message, EventID id)
|
||||
{
|
||||
Service.WriteEntry(message, id, EventLogEntryType.Error, LoggingID);
|
||||
Server.Logger.WriteError(message, id, LoggingID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -82,7 +82,7 @@ namespace TGS.Server.Service
|
||||
/// <param name="id">The <see cref="EventID"/> of the message</param>
|
||||
void WriteWarning(string message, EventID id)
|
||||
{
|
||||
Service.WriteEntry(message, id, EventLogEntryType.Warning, LoggingID);
|
||||
Server.Logger.WriteWarning(message, id, LoggingID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -92,7 +92,7 @@ namespace TGS.Server.Service
|
||||
/// <param name="authSuccess"><see langword="true"/> if <paramref name="username"/> authenticated sucessfully, <see langword="false"/> otherwise</param>
|
||||
void WriteAccess(string username, bool authSuccess)
|
||||
{
|
||||
Service.WriteEntry(String.Format("Access from: {0}", username), EventID.Authentication, authSuccess ? EventLogEntryType.SuccessAudit : EventLogEntryType.FailureAudit, LoggingID);
|
||||
Server.Logger.WriteAccess(String.Format("Access from: {0}", username), authSuccess, LoggingID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -107,7 +107,7 @@ namespace TGS.Server.Service
|
||||
/// <inheritdoc />
|
||||
public string Version()
|
||||
{
|
||||
return Service.VersionString;
|
||||
return Server.VersionString;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -0,0 +1,153 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\packages\LibGit2Sharp-SSH.NativeBinaries.1.0.14\build\LibGit2Sharp-SSH.NativeBinaries.props" Condition="Exists('..\packages\LibGit2Sharp-SSH.NativeBinaries.1.0.14\build\LibGit2Sharp-SSH.NativeBinaries.props')" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{F32EDA25-0855-411C-AF5E-F0D042917E2D}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>TGS.Server</RootNamespace>
|
||||
<AssemblyName>TGS.Server</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>tgs.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<DocumentationFile>bin\x86\Release\TGS.Server.xml</DocumentationFile>
|
||||
<Optimize>true</Optimize>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SignAssembly>false</SignAssembly>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<StartupObject />
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Discord.Net.Core, Version=1.0.2.0, Culture=neutral, PublicKeyToken=null, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Discord.Net.Core.1.0.2\lib\net45\Discord.Net.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Discord.Net.Rest, Version=1.0.2.0, Culture=neutral, PublicKeyToken=null, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Discord.Net.Rest.1.0.2\lib\net45\Discord.Net.Rest.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Discord.Net.WebSocket, Version=1.0.2.0, Culture=neutral, PublicKeyToken=null, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Discord.Net.WebSocket.1.0.2\lib\net45\Discord.Net.WebSocket.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="LibGit2Sharp, Version=1.0.22.0, Culture=neutral, PublicKeyToken=7cbde695407f0333, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\LibGit2Sharp-SSH.1.0.22\lib\net40\LibGit2Sharp.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Meebey.SmartIrc4net, Version=0.4.5.0, Culture=neutral, PublicKeyToken=7868485fbf407e0f, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SmartIrc4net.1.1\lib\Meebey.SmartIrc4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Collections.Immutable.1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.configuration" />
|
||||
<Reference Include="System.Configuration.Install" />
|
||||
<Reference Include="System.DirectoryServices.AccountManagement" />
|
||||
<Reference Include="System.Interactive.Async, Version=3.0.1000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.IO.Compression" />
|
||||
<Reference Include="System.IO.Compression.FileSystem" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Web.Extensions" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ChatCommands\ByondCommand.cs" />
|
||||
<Compile Include="ChatCommands\CommandInfo.cs" />
|
||||
<Compile Include="ChatCommands\ChatCommand.cs" />
|
||||
<Compile Include="ChatCommands\KekCommand.cs" />
|
||||
<Compile Include="ChatCommands\PullRequestsCommand.cs" />
|
||||
<Compile Include="ChatCommands\RevisionCommand.cs" />
|
||||
<Compile Include="ChatCommands\RootChatCommand.cs" />
|
||||
<Compile Include="ChatCommands\ServerChatCommand.cs" />
|
||||
<Compile Include="ChatCommands\VersionCommand.cs" />
|
||||
<Compile Include="Helpers.cs" />
|
||||
<Compile Include="ILogger.cs" />
|
||||
<Compile Include="RootAuthorizationManager.cs" />
|
||||
<Compile Include="DeprecatedInstanceConfig.cs" />
|
||||
<Compile Include="InstanceConfig.cs" />
|
||||
<Compile Include="MessageType.cs" />
|
||||
<Compile Include="RepoConfig.cs" />
|
||||
<Compile Include="ServerInstance\Administration.cs" />
|
||||
<Compile Include="ServerInstance\Byond.cs" />
|
||||
<Compile Include="ServerInstance\Chat.cs" />
|
||||
<Compile Include="ChatProviders\ChatProvider.cs" />
|
||||
<Compile Include="ServerInstance\Compiler.cs" />
|
||||
<Compile Include="ServerInstance\Config.cs" />
|
||||
<Compile Include="ChatProviders\DiscordChatProvider.cs" />
|
||||
<Compile Include="ServerInstance\DreamDaemon.cs" />
|
||||
<Compile Include="EventID.cs" />
|
||||
<Compile Include="ServerInstance\ServerInstance.cs" />
|
||||
<Compile Include="ChatProviders\IRCChatProvider.cs" />
|
||||
<Compile Include="ServerInstance\Interop.cs" />
|
||||
<Compile Include="ServerInstance\PreactionHandler.cs" />
|
||||
<Compile Include="ProcessExtension.cs" />
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ServerInstance\Repository.cs" />
|
||||
<Compile Include="Server.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="..\AssemblyInfo.global.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<None Include="packages.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\TGS.Interface\TGS.Interface.csproj">
|
||||
<Project>{ac4e7e8b-f83a-481c-a8b0-8fa4e8ae59ab}</Project>
|
||||
<Name>TGS.Interface</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="tgs.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\LibGit2Sharp-SSH.NativeBinaries.1.0.14\build\LibGit2Sharp-SSH.NativeBinaries.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\LibGit2Sharp-SSH.NativeBinaries.1.0.14\build\LibGit2Sharp-SSH.NativeBinaries.props'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 120 KiB |
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
namespace TGS.Server.Service.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// For accessing service control methods of <see cref="Service"/>
|
||||
/// </summary>
|
||||
class ServiceAccessor : Service
|
||||
{
|
||||
/// <summary>
|
||||
/// Fake a <see cref="Service"/> start up
|
||||
/// </summary>
|
||||
/// <param name="args">Fake commandline parameters passed to <see cref="OnStart"/></param>
|
||||
public void FakeStart(string[] args)
|
||||
{
|
||||
OnStart(args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fake a <see cref="Service"/> shutdown
|
||||
/// </summary>
|
||||
public void FakeStop()
|
||||
{
|
||||
OnStop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.IO;
|
||||
using TGServiceTests;
|
||||
|
||||
namespace TGS.Server.Service.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests for <see cref="InstanceConfig"/>
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class TestInstanceConfig : TempDirectoryRequiredTest
|
||||
{
|
||||
/// <summary>
|
||||
/// The path to the <see cref="InstanceConfig"/> JSON at <see cref="TempPath"/>
|
||||
/// </summary>
|
||||
string InstanceJSONPath { get { return Path.Combine(TempPath, InstanceConfig.JSONFilename); } }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a default <see cref="InstanceConfig"/> at <see cref="TempPath"/>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IInstanceConfig CreateTempConfig()
|
||||
{
|
||||
return new InstanceConfig(TempPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test that <see cref="InstanceConfig(string)"/> can execute successfully and doesn't automatically save
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestCreate()
|
||||
{
|
||||
var IC = CreateTempConfig();
|
||||
Assert.IsFalse(File.Exists(InstanceJSONPath));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test that <see cref="InstanceConfig.Save"/> works correctly
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestSave()
|
||||
{
|
||||
var IC = CreateTempConfig();
|
||||
IC.Save();
|
||||
Assert.IsTrue(File.Exists(InstanceJSONPath));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test that <see cref="InstanceConfig.Load(string)"/> works correctly
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestLoad()
|
||||
{
|
||||
var IC = CreateTempConfig();
|
||||
var name = "asdf";
|
||||
IC.Name = name;
|
||||
IC.Save();
|
||||
var IC2 = InstanceConfig.Load(TempPath);
|
||||
Assert.AreEqual(name, IC2.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using TGServiceTests;
|
||||
|
||||
namespace TGS.Server.Service.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests for <see cref="ServerInstance"/>
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class TestServerInstance : TempDirectoryRequiredTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Test a <see cref="ServerInstance"/> can be created and destroyed successfully with a basic <see cref="InstanceConfig"/>
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestBasicInstantiation()
|
||||
{
|
||||
new ServerInstance(new InstanceConfig(TempPath), 1).Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the return value of <see cref="ServerInstance.PushTestmergeCommits"/>
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestPushTestMergeCommits()
|
||||
{
|
||||
var ic = new InstanceConfig(TempPath) { PushTestmergeCommits = false };
|
||||
using (var si = new ServerInstance(ic, 1))
|
||||
{
|
||||
Assert.IsFalse(si.PushTestmergeCommits());
|
||||
ic.PushTestmergeCommits = true;
|
||||
Assert.IsTrue(si.PushTestmergeCommits());
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestSetPushTestMergeCommits()
|
||||
{
|
||||
var ic = new InstanceConfig(TempPath) { PushTestmergeCommits = false };
|
||||
using (var si = new ServerInstance(ic, 1))
|
||||
{
|
||||
si.SetPushTestmergeCommits(true);
|
||||
Assert.IsTrue(ic.PushTestmergeCommits);
|
||||
si.SetPushTestmergeCommits(false);
|
||||
Assert.IsFalse(ic.PushTestmergeCommits);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using TGServiceTests;
|
||||
|
||||
namespace TGS.Server.Service.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests for <see cref="Service"/>
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class TestService : TempDirectoryRequiredTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Test <see cref="Service.Service"/> can execute successfully
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestInstantiation()
|
||||
{
|
||||
new Service().Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts and stops a <see cref="Service"/>
|
||||
/// </summary>
|
||||
void StartStopServiceBasic()
|
||||
{
|
||||
using (var S = new ServiceAccessor())
|
||||
{
|
||||
S.FakeStart(new string[] { });
|
||||
S.FakeStop();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test <see cref="Service.OnStart(string[])"/> and <see cref="Service.OnStop"/> can execute successfully
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestStartupAndShutdown()
|
||||
{
|
||||
StartStopServiceBasic();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test <see cref="Service.OnStart(string[])"/> and <see cref="Service.OnStop"/> can execute successfully with a commandline port override
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestCommandLinePortSet()
|
||||
{
|
||||
Properties.Settings.Default.RemoteAccessPort = 11111;
|
||||
using (var S = new ServiceAccessor())
|
||||
{
|
||||
S.FakeStart(new string[] { "-port", "36785" });
|
||||
S.FakeStop();
|
||||
}
|
||||
Assert.AreEqual(Properties.Settings.Default.RemoteAccessPort, 36785);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test that the .NET config is always initialized regardless of <see cref="Properties.Settings.UpgradeRequired"/>
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestNETConfigIsAlwaysPrepped()
|
||||
{
|
||||
Properties.Settings.Default.UpgradeRequired = true;
|
||||
Properties.Settings.Default.InstancePaths = null;
|
||||
StartStopServiceBasic();
|
||||
Assert.IsNotNull(Properties.Settings.Default.InstancePaths);
|
||||
Properties.Settings.Default.UpgradeRequired = false;
|
||||
Properties.Settings.Default.InstancePaths = null;
|
||||
StartStopServiceBasic();
|
||||
Assert.IsNotNull(Properties.Settings.Default.InstancePaths);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,12 +68,6 @@
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ServiceInterface\TestHelpers.cs" />
|
||||
<Compile Include="ServiceInterface\TestInterface.cs" />
|
||||
<Compile Include="Service\ServiceAccessor.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Service\TestInstanceConfig.cs" />
|
||||
<Compile Include="Service\TestServerInstance.cs" />
|
||||
<Compile Include="Service\TestService.cs" />
|
||||
<Compile Include="TempDirectoryRequiredTest.cs" />
|
||||
<Compile Include="..\AssemblyInfo.global.cs" />
|
||||
</ItemGroup>
|
||||
@@ -94,7 +88,7 @@
|
||||
<Project>{8956d4c3-bfb9-448e-bf5f-ee7e6f9996f9}</Project>
|
||||
<Name>TGInstallerWrapper</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\TGS.Server.Service\TGS.Server.Service.csproj">
|
||||
<ProjectReference Include="..\TGS.Server\TGS.Server.csproj">
|
||||
<Project>{f32eda25-0855-411c-af5e-f0d042917e2d}</Project>
|
||||
<Name>TGServerService</Name>
|
||||
</ProjectReference>
|
||||
|
||||
+11
-1
@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27004.2006
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TGS.Server.Service", "TGS.Server.Service\TGS.Server.Service.csproj", "{F32EDA25-0855-411C-AF5E-F0D042917E2D}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TGS.Server", "TGS.Server\TGS.Server.csproj", "{F32EDA25-0855-411C-AF5E-F0D042917E2D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TGS.ControlPanel", "TGS.ControlPanel\TGS.ControlPanel.csproj", "{394E7643-6B8C-416F-AB18-95AC12648CDC}"
|
||||
EndProject
|
||||
@@ -97,6 +97,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TGS.Interface.Bridge", "TGS
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TGS.Tests", "TGS.Tests\TGS.Tests.csproj", "{FB693FFB-17E3-4E84-8CBF-6FFA9C8FD971}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TGS.Server.Service", "TGS.Server.Service\TGS.Server.Service.csproj", "{3F81E398-B223-4006-B40C-C2800714CE29}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -159,6 +161,14 @@ Global
|
||||
{FB693FFB-17E3-4E84-8CBF-6FFA9C8FD971}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FB693FFB-17E3-4E84-8CBF-6FFA9C8FD971}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FB693FFB-17E3-4E84-8CBF-6FFA9C8FD971}.Release-Client|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3F81E398-B223-4006-B40C-C2800714CE29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3F81E398-B223-4006-B40C-C2800714CE29}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3F81E398-B223-4006-B40C-C2800714CE29}.Debug-Client|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3F81E398-B223-4006-B40C-C2800714CE29}.Debug-Client|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3F81E398-B223-4006-B40C-C2800714CE29}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3F81E398-B223-4006-B40C-C2800714CE29}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3F81E398-B223-4006-B40C-C2800714CE29}.Release-Client|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3F81E398-B223-4006-B40C-C2800714CE29}.Release-Client|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -11,6 +11,7 @@ if (Test-Path env:snk_passphrase)
|
||||
{
|
||||
CodeSign "$bf/TGS.CommandLine/bin/Release/TGCommandLine.exe"
|
||||
CodeSign "$bf/TGS.ControlPanel/bin/Release/TGControlPanel.exe"
|
||||
CodeSign "$bf/TGS.Server/bin/Release/TGS.Server.dll"
|
||||
CodeSign "$bf/TGS.Server.Service/bin/Release/TGServerService.exe"
|
||||
CodeSign "$bf/TGS.Interface.Bridge/bin/x86/Release/TGDreamDaemonBridge.dll"
|
||||
CodeSign "$bf/TGS.Interface/bin/Release/TGServiceInterface.dll"
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ build:
|
||||
after_build:
|
||||
- ps: Tools/PostCIBuild.ps1
|
||||
- ps: if($env:APPVEYOR_REPO_COMMIT_MESSAGE -match "\[TGSDeploy\]"){$env:TGSDeploy = "Do it."}
|
||||
- ps: $env:TGSVersion = [System.Diagnostics.FileVersionInfo]::GetVersionInfo("$env:APPVEYOR_BUILD_FOLDER/TGS.Server.Service/bin/Release/TGS.Server.Service.exe").FileVersion
|
||||
- ps: $env:TGSVersion = [System.Diagnostics.FileVersionInfo]::GetVersionInfo("$env:APPVEYOR_BUILD_FOLDER/TGS.Server/bin/Release/TGS.Server.dll").FileVersion
|
||||
test_script:
|
||||
- set path=%ProgramFiles(x86)%\Microsoft Visual Studio\2017\TestAgent\Common7\IDE\CommonExtensions\Microsoft\TestWindow;%path%
|
||||
- copy "%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Community\Common7\IDE\CommonExtensions\Microsoft\TestWindow\Extensions\appveyor.*" "%ProgramFiles(x86)%\Microsoft Visual Studio\2017\TestAgent\Common7\IDE\CommonExtensions\Microsoft\TestWindow\Extensions" /y
|
||||
|
||||
Reference in New Issue
Block a user