Switch from .vdproj to .wixprojs

Wix is just better, it drives the fucking Visual Studio installer for gods' sakes. Thankfully, v4 is a whole lot better than v3 in that it's native dotnet tooling.

- Added ability to set base path for loading configuration files.
- Added Service command descriptions for help text.
- New `.exe` installer also installs dotnet dependencies.
- New `.msi` properly invokes configure, sets up and controls service, sends detach stop signal on upgrades, and uses ProgramData for configs with appropriate permissions.
- Remove .deb symlinks in favor of explicitly setting config directory.
- Adjust CI pipeline with new installer changes.
- Appropriately bump TGS migrator version.
This commit is contained in:
Jordan Dominion
2023-07-02 04:08:14 -04:00
parent e13aa79efe
commit d0d9e7b2ba
55 changed files with 781 additions and 1509 deletions
+62 -41
View File
@@ -240,10 +240,10 @@ jobs:
ref: "refs/pull/${{ github.event.number }}/merge"
- name: Build
run: dotnet build -c ${{ matrix.configuration }}NoFramework
run: dotnet build -c ${{ matrix.configuration }}NoWindows
- name: Run Unit Tests
run: sudo dotnet test --no-build --logger GitHubActions --filter FullyQualifiedName!~TestLiveServer -c ${{ matrix.configuration }}NoFramework --collect:"XPlat Code Coverage" --settings build/coverlet.runsettings --results-directory ./TestResults tgstation-server.sln
run: sudo dotnet test --no-build --logger GitHubActions --filter FullyQualifiedName!~TestLiveServer -c ${{ matrix.configuration }}NoWindows --collect:"XPlat Code Coverage" --settings build/coverlet.runsettings --results-directory ./TestResults tgstation-server.sln
- name: Store Code Coverage
uses: actions/upload-artifact@v3
@@ -562,13 +562,13 @@ jobs:
ref: "refs/pull/${{ github.event.number }}/merge"
- name: Build
run: dotnet build -c ${{ matrix.configuration }}NoFramework tests/Tgstation.Server.Tests/Tgstation.Server.Tests.csproj
run: dotnet build -c ${{ matrix.configuration }}NoWindows tests/Tgstation.Server.Tests/Tgstation.Server.Tests.csproj
- name: Run Live Tests
run: |
cd tests/Tgstation.Server.Tests
sleep 10
dotnet test -c ${{ matrix.configuration }}NoFramework --filter FullyQualifiedName~TestLiveServer --logger GitHubActions --no-build --collect:"XPlat Code Coverage" --settings ../../build/coverlet.runsettings --results-directory ../../TestResults
dotnet test -c ${{ matrix.configuration }}NoWindows --filter FullyQualifiedName~TestLiveServer --logger GitHubActions --no-build --collect:"XPlat Code Coverage" --settings ../../build/coverlet.runsettings --results-directory ../../TestResults
- name: Store Code Coverage
uses: actions/upload-artifact@v3
@@ -582,14 +582,14 @@ jobs:
cd src/Tgstation.Server.Host.Console
dotnet publish -c ${{ matrix.configuration }} -o ../../Artifacts/Console
cd ../Tgstation.Server.Host
dotnet publish -c ${{ matrix.configuration }}NoFramework --no-build -o ../../Artifacts/Console/lib/Default
dotnet publish -c ${{ matrix.configuration }}NoWindows --no-build -o ../../Artifacts/Console/lib/Default
mv ../../Artifacts/Console/lib/Default/appsettings.yml ../../Artifacts/Console/appsettings.yml
- name: Package Server Update Package
if: ${{ matrix.configuration == 'Release' && matrix.watchdog-type == 'System' && matrix.database-type == 'PostgresSql' }}
run: |
cd src/Tgstation.Server.Host
dotnet publish -c ${{ matrix.configuration }}NoFramework --no-build -o ../../Artifacts/ServerUpdate
dotnet publish -c ${{ matrix.configuration }}NoWindows --no-build -o ../../Artifacts/ServerUpdate
rm ../../Artifacts/ServerUpdate/appsettings.yml
- name: Store Server Console
@@ -930,27 +930,24 @@ jobs:
- name: Test Install
run: |
sudo mkdir /etc/tgstation-server
sudo cp build/package/appsettings.GitHub.yml /etc/tgstation-server/appsettings.Production.yml
sudo apt-get install -y ./tgstation-server_${{ env.TGS_VERSION }}-1_amd64.deb
sudo ls -al /etc/tgstation-server
sudo cat /etc/tgstation-server/appsettings.Production.yml
ls -al /opt/tgstation-server
sudo cat /opt/tgstation-server/appsettings.Production.yml
cat /opt/tgstation-server/appsettings.yml
cat /opt/tgstation-server/lib/Default/Tgstation.Server.Host.deps.json
cat /usr/bin/tgs-configure
- name: Test Service
run: |
set +e
systemctl status tgstation-server
$EXIT_CODE=$?
set -e
if [ $EXIT_CODE != 0 ] && [ $EXIT_CODE != '3' ]; then
exit $EXIT_CODE
fi
- name: Test Uninstall
- name: Test Uninstall # Wait 10s for service to initialize
shell: bash
run: |
sleep 10
sudo apt-get remove -y tgstation-server
if [[ -d "/opt/tgstation-server" ]]; then
ls -al /opt/tgstation-server
@@ -967,21 +964,19 @@ jobs:
path: tgstation-server-v${{ env.TGS_VERSION }}.debian.packaging.tar.xz
build-msi:
name: Build .msi Package
name: Build Windows Installer .exe
needs: start-ci-run-gate
runs-on: windows-latest
if: "!(cancelled() || failure()) && needs.start-ci-run-gate.result == 'success'"
steps:
- name: Setup VS Dev Environment
uses: seanmiddleditch/gha-setup-vsdevenv@v4
- name: Disable Out of Process Building
working-directory: C:/Program Files/Microsoft Visual Studio/2022/Enterprise/Common7/IDE/CommonExtensions/Microsoft/VSI/DisableOutOfProcBuild
run: ./DisableOutOfProcBuild.exe
- name: Install winget
uses: Cyberboss/install-winget@v1
- name: Setup dotnet
uses: actions/setup-dotnet@v2
with:
dotnet-version: ${{ env.TGS_DOTNET_VERSION }}
- name: Checkout (Branch)
uses: actions/checkout@v3
if: github.event_name == 'push' || github.event_name == 'schedule'
@@ -995,16 +990,27 @@ jobs:
- name: Validate winget Manifest
run: winget validate --manifest build/package/winget/manifest
- name: Execute Build Script
- name: Build Service
run: dotnet build -c Release src/Tgstation.Server.Host.Service/Tgstation.Server.Host.Service.csproj
- name: Prepare Artifacts
shell: powershell
run: build/package/winget/build_msi.ps1
run: build/package/winget/prepare_installer_input_artifacts.ps1
- name: Build Installer
run: |
cd build/package/winget
dotnet tool restore
dotnet build -c Release Tgstation.Server.Service.Wix.Bundle
- name: Test Install # Sanity checks the .deps.json exists, which the installation is broken without
shell: powershell # If it's missing, I found that <PrivateAssets> in <PackageReference> elements were the problem
run: |
$file = [System.IO.Path]::GetFullPath("packaging/build/package/winget/Tgstation.Server.Host.Service.Msi/Release/tgstation-server.msi")
mkdir C:/ProgramData/tgstation-server
cp build/package/appsettings.GitHub.yml C:/ProgramData/tgstation-server/appsettings.Production.yml
$file = [System.IO.Path]::GetFullPath("build/package/winget/Tgstation.Server.Host.Service.Wix.Bundle/bin/x86/Release/tgstation-server-installer.exe")
$log = [System.IO.Path]::GetFullPath("install.log")
$procMain = Start-Process "msiexec" "/i `"$file`" /qn /l*! `"$log`"" -NoNewWindow -PassThru -Wait
$procMain = Start-Process "$file" "/install /silent /log `"$log`"" -NoNewWindow -PassThru -Wait
if (Test-Path -Path $log -PathType Leaf) {
Get-Content $log
}
@@ -1016,6 +1022,9 @@ jobs:
if (-Not (Test-Path -Path "C:/Program Files (x86)/tgstation-server/lib/Default/Tgstation.Server.Host.deps.json" -PathType Leaf)) {
exit 2
}
if (-Not (Test-Path -Path "C:/ProgramData/tgstation-server/appsettings.Production.json" -PathType Leaf)) {
exit 4
}
- name: Test Service
shell: powershell
@@ -1024,13 +1033,16 @@ jobs:
if ($service.Length -eq 0) {
exit 3
}
if ($service[0].Status -ne "Running") {
exit 4
}
- name: Test Uninstall # Sanity checks the .deps.json exists, which the installation is broken without
shell: powershell # If it's missing, I found that <PrivateAssets> in <PackageReference> elements were the problem
shell: powershell
run: |
$file = [System.IO.Path]::GetFullPath("packaging/build/package/winget/Tgstation.Server.Host.Service.Msi/Release/tgstation-server.msi")
$file = [System.IO.Path]::GetFullPath("build/package/winget/Tgstation.Server.Host.Service.Wix.Bundle/bin/x86/Release/tgstation-server-installer.exe")
$log = [System.IO.Path]::GetFullPath("uninstall.log")
$procMain = Start-Process "msiexec" "/x `"$file`" /qn /l*! `"$log`"" -NoNewWindow -PassThru -Wait
$procMain = Start-Process "$file" "/install /silent /log `"$log`"" -NoNewWindow -PassThru -Wait
if (Test-Path -Path $log -PathType Leaf) {
Get-Content $log
}
@@ -1045,11 +1057,11 @@ jobs:
exit 2
}
- name: Upload .msi
- name: Upload Installer .exe
uses: actions/upload-artifact@v3
with:
name: packaging-windows
path: packaging/build/package/winget/Tgstation.Server.Host.Service.Msi/Release/tgstation-server.msi
path: build/package/winget/Tgstation.Server.Host.Service.Wix.Bundle/bin/x86/Release/tgstation-server-installer.exe
check-winget-pr-template:
name: Check winget-pkgs Pull Request Template is up to date
@@ -1078,8 +1090,11 @@ jobs:
with:
ref: "refs/pull/${{ github.event.number }}/merge"
- name: Build ReleaseNotes
run: dotnet build -c Release tools/ReleaseNotes/ReleaseNotes.csproj
- name: Run ReleaseNotes Check
run: dotnet run -c Release --project tools/ReleaseNotes --winget-template-check ${{ steps.get-sha.outputs.pr_template_sha }}
run: dotnet run -c Release --no-build --project tools/ReleaseNotes --winget-template-check ${{ steps.get-sha.outputs.pr_template_sha }}
ci-completion-gate: # This job exists so there isn't a moving target for branch protections
name: CI Completion Gate
@@ -1236,8 +1251,11 @@ jobs:
- name: Checkout
uses: actions/checkout@v3
- name: Build ReleaseNotes
run: dotnet build -c Release tools/ReleaseNotes/ReleaseNotes.csproj
- name: Run ReleaseNotes with --ensure-release
run: dotnet run -c Release --project tools/ReleaseNotes --ensure-release
run: dotnet run -c Release --no-build --project tools/ReleaseNotes --ensure-release
deploy-tgs:
name: Deploy TGS
@@ -1253,6 +1271,9 @@ jobs:
- name: Checkout
uses: actions/checkout@v3
- name: Build ReleaseNotes
run: dotnet build -c Release tools/ReleaseNotes/ReleaseNotes.csproj
- name: Parse TGS version
shell: powershell
run: |
@@ -1290,7 +1311,7 @@ jobs:
name: packaging-debian
path: packaging-debian
- name: Retrieve .msi
- name: Retrieve Installer .exe
uses: actions/download-artifact@v3
with:
name: packaging-windows
@@ -1306,7 +1327,7 @@ jobs:
&"C:/Program Files/7-Zip/7z.exe" a ServerUpdatePackage.zip ./ServerUpdatePackage/* -tzip
- name: Generate Release Notes
run: dotnet run -c Release --project tools/ReleaseNotes ${{ env.TGS_VERSION }}
run: dotnet run -c Release --no-build --project tools/ReleaseNotes ${{ env.TGS_VERSION }}
- name: Create GitHub Release
uses: actions/create-release@v1
@@ -1379,14 +1400,14 @@ jobs:
asset_name: tgstation-server-v${{ env.TGS_VERSION }}.debian.packaging.tar.xz
asset_content_type: application/x-tar
- name: Upload .msi
- name: Upload Installer .exe
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.DEV_PUSH_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./packaging-windows/tgstation-server.msi
asset_name: tgstation-server.msi
asset_path: ./packaging-windows/tgstation-server-installer.exe
asset_name: tgstation-server-installer.exe
asset_content_type: application/octet-stream
deploy-docker:
@@ -1458,7 +1479,7 @@ jobs:
- name: Build ReleaseNotes
run: dotnet build -c Release tools/ReleaseNotes
- name: Retrieve .msi
- name: Retrieve Installer .exe
uses: actions/download-artifact@v3
with:
name: packaging-windows
@@ -1466,7 +1487,7 @@ jobs:
- name: Execute Push Script
shell: powershell
run: build/package/winget/push_manifest.ps1 -MsiPath packaging-windows/tgstation-server.msi
run: build/package/winget/push_manifest.ps1 -InstallerPath packaging-windows/tgstation-server-installer.exe
- name: Run ReleaseNotes with --link-winget
run: dotnet run -c Release --project tools/ReleaseNotes --link-winget ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: dotnet run -c Release --no-build --project tools/ReleaseNotes --link-winget ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
+1 -1
View File
@@ -35,7 +35,7 @@ jobs:
languages: csharp
- name: Build
run: dotnet build -c ReleaseNoFramework
run: dotnet build -c ReleaseNoWindows
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
-1
View File
@@ -25,4 +25,3 @@ release_notes.md
*nupkg
*.sqlite3
packaging/
build/package/winget/Tgstation.Server.Host.Service.Msi/Release/
+1 -1
View File
@@ -2,7 +2,7 @@
<Import Project="Version.props" />
<PropertyGroup>
<TgsNetVersion>net6.0</TgsNetVersion>
<TgsFrameworkVersion>net$(TgsNetMajorVersion).0</TgsFrameworkVersion>
<TgsNugetNetVersion>netstandard2.0</TgsNugetNetVersion>
<LangVersion>latest</LangVersion>
<DebugType>Full</DebugType>
+5 -1
View File
@@ -13,6 +13,10 @@
<TgsInteropVersion>5.6.1</TgsInteropVersion>
<TgsHostWatchdogVersion>1.3.0</TgsHostWatchdogVersion>
<TgsContainerScriptVersion>1.2.1</TgsContainerScriptVersion>
<TgsMigratorVersion>1.0.1</TgsMigratorVersion>
<TgsMigratorVersion>1.0.2</TgsMigratorVersion>
<TgsNetMajorVersion>6</TgsNetMajorVersion>
<!-- Update this frequently with dotnet runtime patches. MAJOR MUST MATCH ABOVE! -->
<!-- You also need to update the .Bundle project's ExePackagePayload hash and file size after changing it -->
<TgsRedistUrl>https://dotnetcli.azureedge.net/dotnet/aspnetcore/Runtime/6.0.19/dotnet-hosting-6.0.19-win.exe</TgsRedistUrl>
</PropertyGroup>
</Project>
+23
View File
@@ -1,3 +1,26 @@
# Barebones config file used for testing service installs in GitHub actions
Database:
DatabaseType: Sqlite
ConnectionString: Data Source=/tgs.sqlite3;Mode=ReadWriteCreate
General:
ConfigVersion: 4.6.0
ApiPort: 5000
GitHubAccessToken:
SetupWizardMode: Never
ByondTopicTimeout: 5000
RestartTimeoutMinutes: 1
ShutdownTimeoutMinutes: 300
UseBasicWatchdog: false
HostApiDocumentation: true
SkipAddingByondFirewallException: false
DeploymentDirectoryCopyTasksPerCore:
MinimumPasswordLength: 15
InstanceLimit: 10
UserLimit: 100
UserGroupLimit: 25
ValidInstancePaths:
FileLogging:
Directory:
Disable: false
LogLevel: Trace
MicrosoftLogLevel: Warning
+1 -1
View File
@@ -1,2 +1,2 @@
# tgstation-server configuration file
# See /opt/tgstation-server/appsettings.yml for details on individual configuration options
# See appsettings.yml or README.md for details on individual configuration options
+1 -1
View File
@@ -3,5 +3,5 @@
install:
build/package/deb/install_artifacts.sh "$(DESTDIR)"
install -D build/package/appsettings.Initial.yml "$(DESTDIR)/etc/tgstation-server/appsettings.Production.yml"
install src/Tgstation.Server.Host/appsettings.yml "$(DESTDIR)/etc/tgstation-server/appsettings.ex.yml"
install src/Tgstation.Server.Host/appsettings.yml "$(DESTDIR)/etc/tgstation-server/appsettings.yml"
install -D build/package/deb/tgs-configure "$(DESTDIR)/usr/bin/tgs-configure"
-1
View File
@@ -1 +0,0 @@
/etc/tgstation-server/appsettings.Production.yml /opt/tgstation-server/appsettings.Production.yml
+2 -2
View File
@@ -7,13 +7,13 @@ export DH_VERBOSE = 1
override_dh_auto_clean:
rm -rf artifacts
dotnet clean -c ReleaseNoFramework
dotnet clean -c ReleaseNoWindows
override_dh_auto_build:
dotnet restore
cd src/Tgstation.Server.Host.Console && dotnet publish -c Release -o ../../artifacts
cd src/Tgstation.Server.Host && dotnet publish -c Release -o ../../artifacts/lib/Default
mv artifacts/lib/Default/appsettings.yml artifacts/appsettings.yml
rm artifacts/lib/Default/appsettings.yml
override_dh_auto_install:
cp build/package/deb/MakeInstall ./Makefile
@@ -1,94 +0,0 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.AccessControl;
using System.Threading;
using System.Windows.Forms;
using var process = new Process();
var installDir = Path.GetDirectoryName(
Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location))!;
process.StartInfo.WorkingDirectory = installDir;
process.StartInfo.FileName = Path.Combine(
installDir,
"Tgstation.Server.Host.Service.exe");
/*
https://www.roelvanlisdonk.nl/2009/11/13/how-to-detect-unattended-installation-msiexec-quit-or-qn-in-youre-custom-action-with-c/
msiUILevelNoChange 0 Does not change UI level.
msiUILevelDefault 1 Uses default UI level.
msiUILevelNone 2 Silent installation.
msiUILevelBasic 3 Simple progress and error handling.
msiUILevelReduced 4 Authored UI and wizard dialog boxes suppressed.
msiUILevelFull 5 Authored UI with wizards, progress, and errors.
msiUILevelHideCancel 32 If combined with the msiUILevelBasic value, the installer shows progress dialog boxes but does not display a Cancel button on the dialog box to prevent users from canceling the installation.
msiUILevelProgressOnly 64 If combined with the msiUILevelBasic value, the installer displays progress dialog boxes but does not display any modal dialog boxes or error dialog boxes.
msiUILevelEndDialog 128 If combined with any above value, the installer displays a modal dialog box at the end of a successful installation or if there has been an error. No dialog box is displayed if the user cancels.
*/
var uiLevel = Int32.Parse(args[0]);
// leave it to MS to overcomplicate things
var interactive = uiLevel switch
{
0 or 1 or 4 or 5 => true,
_ => false,
};
var silent = uiLevel == 2;
var uninstall = args
.Any(arg => arg.Equals("--uninstall", StringComparison.OrdinalIgnoreCase));
var shortcut = uiLevel == 42069;
bool restartService;
if (shortcut)
{
var result = MessageBox.Show($"This program will configure tgstation-server. Would you like to restart the service after doing so?{Environment.NewLine}{Environment.NewLine}A restart is required to apply changes. It will not kill your DreamDaemon instances provided you are running a version >=5.13.0 (Always true if you've never downgraded)", "Restart TGS After Configuring?", MessageBoxButtons.YesNo);
restartService = result == DialogResult.Yes;
}
else
restartService = interactive;
process.StartInfo.Arguments = uninstall
? $"-u{(silent ? " -s" : String.Empty)}"
: $"-i -f -x{(restartService ? " -r" : String.Empty)}{((interactive || shortcut) ? " -c" : String.Empty)}{(silent ? " -s" : String.Empty)}";
process.Start();
await process.WaitForExitAsync(CancellationToken.None); // DCT: None available
foreach (var installLogFile in Directory.EnumerateFiles(installDir, "*.log"))
File.Delete(installLogFile);
if (uninstall)
{
Directory.Delete(
Path.Combine(installDir, "lib"),
true);
// returning non-zero can make the installation uninstallable, no thanks
return 0;
}
// try and lockdown the appsettings file
var fileInfo = new FileInfo(Path.Combine(installDir, "appsettings.Production.yml"));
//get security access
FileSecurity fs = fileInfo.GetAccessControl();
//remove inherited access
fs.SetAccessRuleProtection(true, false);
// Explicitly grant admins and SYSTEM
fs.AddAccessRule(new FileSystemAccessRule("Administrators", FileSystemRights.FullControl, AccessControlType.Allow));
fs.AddAccessRule(new FileSystemAccessRule("NT AUTHORITY\\SYSTEM", FileSystemRights.Read, AccessControlType.Allow));
fileInfo.SetAccessControl(fs);
return process.ExitCode;
@@ -1,17 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<RuntimeIdentifier>win-x86</RuntimeIdentifier>
<UseWindowsForms>true</UseWindowsForms>
<Nullable>enable</Nullable>
<ApplicationManifest>../../../uac_elevation_manifest.xml</ApplicationManifest>
<ApplicationIcon>../../../tgs.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<AdditionalFiles Include="../../../uac_elevation_manifest.xml" />
</ItemGroup>
</Project>
@@ -1,3 +0,0 @@
# .msi Installer Project
Useful reference for variables: https://learn.microsoft.com/en-us/windows/win32/msi/property-reference?redirectedfrom=MSDN
@@ -0,0 +1,22 @@
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal" xmlns:netfx="http://wixtoolset.org/schemas/v4/wxs/netfx">
<Bundle Name="tgstation-server" Manufacturer="/tg/station 13" Version="$(var.ProductVersion)" AboutUrl="https://github.com/tgstation/tgstation-server/blob/tgstation-server-v$(var.ProductVersion)/LICENSE" IconSourceFile="../../../tgs.ico" HelpUrl="https://github.com/tgstation/tgstation-server/discussions/categories/q-a" UpdateUrl="https://github.com/tgstation/tgstation-server/releases/latest" UpgradeCode="542535f4-49ad-45c4-9b96-6d8235ed8b87">
<BootstrapperApplication>
<bal:WixStandardBootstrapperApplication LicenseUrl="https://github.com/tgstation/tgstation/tree/tgstation-server-v$(var.ProductVersion)" Theme="hyperlinkLicense" LogoFile="../../../tgs.ico" ShowVersion="yes" SuppressOptionsUI="yes" />
</BootstrapperApplication>
<netfx:DotNetCoreSearch RuntimeType="aspnet" Platform="x64" MajorVersion="$(var.NetMajorVersion)" Variable="AspNetCorex64Status" />
<netfx:DotNetCoreSearch RuntimeType="aspnet" Platform="x86" MajorVersion="$(var.NetMajorVersion)" Variable="AspNetCorex86Status" />
<WixVariable Id="AspNetCoreDetectCondition" Value="AspNetCorex64Status OR AspNetCorex86Status" Overridable="yes" />
<Chain>
<ExePackage PerMachine="yes" DetectCondition="!(wix.AspNetCoreDetectCondition)" Vital="yes" Permanent="yes" Protocol="burn" InstallArguments="/install /quiet /norestart /log [HOSTING_BUNDLE_LOG_PATH]" RepairArguments="/repair /quiet /norestart /log [HOSTING_BUNDLE_LOG_PATH]" UninstallArguments="/uninstall /quiet /norestart /log [HOSTING_BUNDLE_LOG_PATH]" Cache="remove" LogPathVariable="HOSTING_BUNDLE_LOG_PATH" RepairCondition="FALSE">
<ExePackagePayload Name="Microsoft.DotNet.HostingBundle.$(var.NetMajorVersion)" DownloadUrl="$(var.AspNetRedistUrl)" Hash="FADC48A76561A7ABD5CC599DB737AFC2B1638013C95E29CFC8955CACA1D57004BD9078C6EF9696BECFD75BAA2983FDC2FF4382C9EBDF833A11316C2DEC218884" Size="71391856" Compressed="no" />
</ExePackage>
<MsiPackage SourceFile="$(var.Tgstation.Server.Host.Service.Wix.TargetPath)">
<MsiProperty Name="WIX_BOOTSTRAPPER_UILEVEL" Value="[WixBundleUILevel]" />
</MsiPackage>
</Chain>
</Bundle>
</Wix>
@@ -0,0 +1,16 @@
<Project Sdk="WixToolset.Sdk/4.0.1" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
<Import Project="../../../Common.props" />
<PropertyGroup>
<DefineConstants>ProductVersion=$(TgsCoreVersion);NetMajorVersion=$(TgsNetMajorVersion);AspNetRedistUrl=$(TgsRedistUrl)</DefineConstants>
<OutputType>Bundle</OutputType>
<Platforms>x86</Platforms>
<OutputName>tgstation-server-installer</OutputName>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="WixToolset.Bal.wixext" Version="4.0.1" />
<PackageReference Include="WixToolset.Netfx.wixext" Version="4.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Tgstation.Server.Host.Service.Wix\Tgstation.Server.Host.Service.Wix.wixproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" />
<supportedRuntime version="v2.0.50727" />
</startup>
</configuration>
@@ -0,0 +1,76 @@
namespace Tgstation.Server.Host.Service.Wix.SafeShutdown
{
using System;
using System.ServiceProcess;
using Tgstation.Server.Host.Common;
using WixToolset.Dtf.WindowsInstaller;
/// <summary>
/// Extension methods for the .msi installer.
/// </summary>
public static class InstallationExtensions
{
/// <summary>
/// Attempts to detach stop the existing tgstation-server service if it exists.
/// </summary>
/// <param name="session">The installer <see cref="Session"/>.</param>
/// <returns>The <see cref="ActionResult"/> of the custom action.</returns>
[CustomAction]
public static ActionResult DetachStopTgsServiceIfRunning(Session session)
{
if (session == null)
throw new ArgumentNullException(nameof(session));
try
{
session.Log("Begin DetachStopTgsServiceIfRunning");
ServiceController serviceController = null;
session.Log($"Searching for {Constants.CanonicalPackageName} service...");
foreach (var controller in ServiceController.GetServices())
if (controller.ServiceName == Constants.CanonicalPackageName)
{
serviceController = controller;
break;
}
else
controller.Dispose();
using (serviceController)
{
if (serviceController == null || serviceController.Status != ServiceControllerStatus.Running)
{
session.Log($"{Constants.CanonicalPackageName} service not found. Continuing.");
return ActionResult.Success;
}
var commandId = PipeCommands.GetCommandId(
PipeCommands.CommandDetachingShutdown)
.Value;
session.Log($"{Constants.CanonicalPackageName} service found. Sending command \"{PipeCommands.CommandDetachingShutdown}\" ({commandId})...");
serviceController.ExecuteCommand(commandId);
session.Log($"Command sent. Waiting for {Constants.CanonicalPackageName} service to stop...");
serviceController.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromMinutes(1));
var stopped = serviceController.Status == ServiceControllerStatus.Stopped;
session.Log($"{Constants.CanonicalPackageName} stopped {(stopped ? String.Empty : "un")}successfully.");
return stopped
? ActionResult.Success
: ActionResult.NotExecuted;
}
}
catch (Exception ex)
{
session.Log($"Exception in DetachStopTgsServiceIfRunning:{Environment.NewLine}{ex}");
return ActionResult.Failure;
}
}
}
}
@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../../../Common.props" />
<PropertyGroup>
<TargetFramework>net2.0</TargetFramework>
<Version>$(TgsCoreVersion)</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="WixToolset.Dtf.CustomAction" Version="4.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\src\Tgstation.Server.Host.Common\Tgstation.Server.Host.Common.csproj">
<Private>True</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="CustomAction.config" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup>
<Reference Include="System.ServiceProcess" />
</ItemGroup>
</Project>
@@ -0,0 +1,11 @@
<!--
This file contains the declaration of all the localizable strings.
-->
<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="en-US">
<String Id="DowngradeError" Value="A newer version of [ProductName] is already installed." />
<String Id="MainServerFeatureDescription" Value="The primary application for running [ProductName]." />
<String Id="ServerServiceDescription" Value="[ProductName] running as a Windows service." />
<String Id="ConfigureRestartDescription" Value="Runs the tgstation-server setup wizard and restarts the service (Does not stop DreamDaemon processes)." />
<String Id="ConfigureRestartName" Value="Configure &amp; Restart tgstation-server" />
</WixLocalization>
@@ -0,0 +1,86 @@
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
<Package Name="tgstation-server" Manufacturer="/tg/station 13" Version="$(var.ProductVersion)" UpgradeCode="36912c45-5953-4f16-ad7d-17a150ea3587" Scope="perMachine">
<MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)" />
<MediaTemplate EmbedCab="yes" />
<Binary Id="InstallerExtensionsBinary" SourceFile="$(var.Tgstation.Server.Host.Service.Wix.Extensions.TargetName).CA.dll" />
<CustomAction Id="DetachStopTgsServiceIfRunningAction" BinaryRef="InstallerExtensionsBinary" DllEntry="DetachStopTgsServiceIfRunning" Execute="deferred" />
<CustomAction Id="RunTgsConfigure" Execute="deferred" FileRef="ServiceExecutableFile" ExeCommand="-c -p=--appsettings-base-path=[APPLICATIONDATADIRECTORY]" />
<Icon Id="tgs.ico" SourceFile="../../../tgs.ico" />
<SetProperty Id="WIX_BOOTSTRAPPER_UILEVEL" Value="[UILevel]" After="CostFinalize" Condition="WIX_BOOTSTRAPPER_UILEVEL=&quot;&quot;" />
<InstallExecuteSequence>
<Custom Action="DetachStopTgsServiceIfRunningAction" Condition="UPGRADINGPRODUCTCODE OR REINSTALL" Before="StopServices" />
<Custom Action="RunTgsConfigure" Before="StartServices" Condition="(NOT REMOVE~=&quot;ALL&quot;) AND (NOT PRODUCTIONAPPSETTINGSPRESENT) AND ((WIX_BOOTSTRAPPER_UILEVEL >= 4) OR (UILevel >= 4))" />
</InstallExecuteSequence>
<Feature Id="MainServerFeature" AllowAbsent="no" Description="!(loc.MainServerFeatureDescription)">
<ComponentGroupRef Id="InitialHostComponentGroup"/>
<ComponentGroupRef Id="ServiceHostWatchdogComponentGroup"/>
<ComponentRef Id="StoreApplicationDataDirectoryPathComponent"/>
<ComponentRef Id="ServiceHostWatchdogExeComponent"/>
<ComponentRef Id="PurgeLibDirectoryComponent"/>
<ComponentRef Id="BaseAppSettingsComponent"/>
<ComponentRef Id="ProductionAppSettingsComponent"/>
</Feature>
<Property Id="LIBDIRECTORY">
<RegistrySearch Key="SOFTWARE\tgstation\tgstation-server" Root="HKLM" Type="raw" Id="StoredLibDirectory" Name="LibDirectory" />
</Property>
<Property Id="APPLICATIONDATADIRECTORY">
<RegistrySearch Key="SOFTWARE\tgstation\tgstation-server" Root="HKLM" Type="raw" Id="StoredProgramDataDirectory" Name="ProgramDataDirectory" />
</Property>
<Property Id="PRODUCTIONAPPSETTINGSPRESENT">
<DirectorySearch Path="[CommonAppDataFolder]" Depth="0" Id="ProgramDataDirectorySearcher">
<DirectorySearch Path="!(bind.Property.ProductName)" Depth="0" Id="ApplicationDataDirectorySearcher">
<FileSearch Name="appsettings.Production.yml" />
</DirectorySearch>
</DirectorySearch>
</Property>
<StandardDirectory Id="ProgramFiles6432Folder">
<Directory Id="ApplicationDirectory" Name="!(bind.Property.ProductName)">
<Directory Id="LIBDIRECTORY" Name="lib">
<Directory Id="DefaultLibDirectory" Name="Default" />
<Component Id="PurgeLibDirectoryComponent" Guid="38E323E2-0404-4ACB-ACDD-80F5525538FB">
<RegistryValue Root="HKLM" Key="SOFTWARE\tgstation\tgstation-server" Name="LibDirectory" Type="string" Value="[LIBDIRECTORY]" KeyPath="yes" />
<util:RemoveFolderEx Id="PurgeLibDirectory" On="both" Property="LIBDIRECTORY" />
</Component>
</Directory>
<Component Id="ServiceHostWatchdogExeComponent" Guid="9430D56D-EEBF-4026-9EC1-693668A6EC7C" >
<File Id="ServiceExecutableFile" Source="Tgstation.Server.Host.Service.exe" KeyPath="yes" />
<Shortcut Advertise="yes" Arguments="-c -x -r -p=--appsettings-base-path=[APPLICATIONDATADIRECTORY]" Description="!(loc.ConfigureRestartDescription)" Name="!(loc.ConfigureRestartName)" Directory="DesktopFolder" Icon="tgs.ico" />
<Shortcut Advertise="yes" Arguments="-c -x -r -p=--appsettings-base-path=[APPLICATIONDATADIRECTORY]" Description="!(loc.ConfigureRestartDescription)" Name="!(loc.ConfigureRestartName)" Directory="StartMenuFolder" Icon="tgs.ico" />
<ServiceInstall Name="!(bind.Property.ProductName)" DisplayName="!(bind.Property.ProductName)" Description="!(loc.ServerServiceDescription)" Start="auto" Type="ownProcess" ErrorControl="normal" Account="LocalSystem" Vital="yes" Interactive="no" Arguments="-p=--appsettings-base-path=[APPLICATIONDATADIRECTORY]">
<ServiceDependency Id="Tcpip" />
<ServiceDependency Id="Dhcp" />
<ServiceDependency Id="Dnscache" />
</ServiceInstall>
<ServiceControl Name="!(bind.Property.ProductName)" Remove="uninstall" Start="install" Stop="uninstall" Wait="yes" />
</Component>
</Directory>
</StandardDirectory>
<StandardDirectory Id="CommonAppDataFolder">
<Directory Id="APPLICATIONDATADIRECTORY" Name="!(bind.Property.ProductName)">
<Component Id="StoreApplicationDataDirectoryPathComponent" Guid="86B0EB79-DAC9-4325-8965-42089ABED375">
<RegistryValue Root="HKLM" Key="SOFTWARE\tgstation\tgstation-server" Name="ProgramDataDirectory" Type="string" Value="[APPLICATIONDATADIRECTORY]" KeyPath="yes" />
</Component>
<Component Id="BaseAppSettingsComponent" Guid="" NeverOverwrite="yes">
<File Source="../../../../src/Tgstation.Server.Host/appsettings.yml" />
</Component>
<Component Id="ProductionAppSettingsComponent" Guid="" NeverOverwrite="yes">
<File Source="../../appsettings.Initial.yml" Name="appsettings.Production.yml">
<PermissionEx Sddl="D:PAI(A;;FA;;;SY)(A;;FA;;;BA)" />
</File>
</Component>
</Directory>
</StandardDirectory>
</Package>
</Wix>
@@ -0,0 +1,34 @@
<Project Sdk="WixToolset.Sdk/4.0.1">
<Import Project="../../../Common.props" />
<PropertyGroup>
<DefineConstants>ProductVersion=$(TgsCoreVersion)</DefineConstants>
<HarvestDirectorySuppressSpecificWarnings>5150;5151</HarvestDirectorySuppressSpecificWarnings>
<Platforms>x86</Platforms>
<OutputName>tgstation-server</OutputName>
</PropertyGroup>
<ItemGroup>
<BindPath Include="../Tgstation.Server.Host.Service.Wix.Extensions/$(Configuration)/net472" />
<BindPath Include="../../../../artifacts" />
<BindPath Include="../../../../artifacts/Tgstation.Server.Host" />
<BindPath Include="../../../../artifacts/Tgstation.Server.Host.Service" />
<HarvestDirectory Include="../../../../artifacts/Tgstation.Server.Host">
<ComponentGroupName>InitialHostComponentGroup</ComponentGroupName>
<DirectoryRefId>DefaultLibDirectory</DirectoryRefId>
<SuppressCom>true</SuppressCom>
<SuppressRegistry>true</SuppressRegistry>
<SuppressRootDirectory>true</SuppressRootDirectory>
</HarvestDirectory>
<HarvestDirectory Include="../../../../artifacts/Tgstation.Server.Host.Service">
<ComponentGroupName>ServiceHostWatchdogComponentGroup</ComponentGroupName>
<DirectoryRefId>ApplicationDirectory</DirectoryRefId>
<SuppressRootDirectory>true</SuppressRootDirectory>
</HarvestDirectory>
</ItemGroup>
<ItemGroup>
<PackageReference Include="WixToolset.Heat" Version="4.0.1" />
<PackageReference Include="WixToolset.Util.wixext" Version="4.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Tgstation.Server.Host.Service.Wix.Extensions\Tgstation.Server.Host.Service.Wix.Extensions.csproj" />
</ItemGroup>
</Project>
-29
View File
@@ -1,29 +0,0 @@
$currentCommit=git rev-parse HEAD
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue packaging
git worktree remove -f packaging
git worktree add -f packaging $currentCommit
cd packaging
Remove-Item -Recurse -Force .git
dotnet restore
[XML]$versionXML = Get-Content build/Version.props -ErrorAction Stop
$tgsVersion = $versionXML.Project.PropertyGroup.TgsCoreVersion
cd build/package/winget
$devVersion = '0.22.475'
(Get-Content Tgstation.Server.Host.Service.Msi/Tgstation.Server.Host.Service.Msi.vdproj -ErrorAction Stop).Replace($devVersion, $tgsVersion) | Set-Content Tgstation.Server.Host.Service.Msi/Tgstation.Server.Host.Service.Msi.vdproj -ErrorAction Stop
# We make _some_ assumptions
DevEnv installer.sln /Project Tgstation.Server.Host.Service.Msi/Tgstation.Server.Host.Service.Msi.vdproj /build Release
if (-Not $?) {
exit $lastexitcode
}
cd ../../../..
-50
View File
@@ -1,50 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.6.33801.468
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tgstation.Server.Host.Service.Configure", "Tgstation.Server.Host.Service.Configure\Tgstation.Server.Host.Service.Configure.csproj", "{6CC73878-8C37-4ACC-ADAA-A60EBDBC2315}"
EndProject
Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "Tgstation.Server.Host.Service.Msi", "Tgstation.Server.Host.Service.Msi\Tgstation.Server.Host.Service.Msi.vdproj", "{C7BE7AC6-D020-4497-84DE-282C24BA575D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tgstation.Server.Api", "..\..\..\src\Tgstation.Server.Api\Tgstation.Server.Api.csproj", "{8B4A208D-A48A-4A5D-8B94-E2661138865D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tgstation.Server.Common", "..\..\..\src\Tgstation.Server.Common\Tgstation.Server.Common.csproj", "{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tgstation.Server.Host.Common", "..\..\..\src\Tgstation.Server.Host.Common\Tgstation.Server.Host.Common.csproj", "{CF3968A0-EA81-4464-B2D4-C7D40F6B5BCB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tgstation.Server.Host.Service", "..\..\..\src\Tgstation.Server.Host.Service\Tgstation.Server.Host.Service.csproj", "{29927416-3B78-49A7-A560-5CCAA638B6B4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tgstation.Server.Host.Watchdog", "..\..\..\src\Tgstation.Server.Host.Watchdog\Tgstation.Server.Host.Watchdog.csproj", "{5D2D682C-6BF0-439C-850B-6AB945BBEAEA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tgstation.Server.Host", "..\..\..\src\Tgstation.Server.Host\Tgstation.Server.Host.csproj", "{2B69AD6D-2B5A-4023-8EAD-0BD1B18E028A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6CC73878-8C37-4ACC-ADAA-A60EBDBC2315}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6CC73878-8C37-4ACC-ADAA-A60EBDBC2315}.Release|Any CPU.Build.0 = Release|Any CPU
{C7BE7AC6-D020-4497-84DE-282C24BA575D}.Release|Any CPU.ActiveCfg = Release
{C7BE7AC6-D020-4497-84DE-282C24BA575D}.Release|Any CPU.Build.0 = Release
{8B4A208D-A48A-4A5D-8B94-E2661138865D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8B4A208D-A48A-4A5D-8B94-E2661138865D}.Release|Any CPU.Build.0 = Release|Any CPU
{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.Release|Any CPU.Build.0 = Release|Any CPU
{CF3968A0-EA81-4464-B2D4-C7D40F6B5BCB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CF3968A0-EA81-4464-B2D4-C7D40F6B5BCB}.Release|Any CPU.Build.0 = Release|Any CPU
{29927416-3B78-49A7-A560-5CCAA638B6B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{29927416-3B78-49A7-A560-5CCAA638B6B4}.Release|Any CPU.Build.0 = Release|Any CPU
{5D2D682C-6BF0-439C-850B-6AB945BBEAEA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5D2D682C-6BF0-439C-850B-6AB945BBEAEA}.Release|Any CPU.Build.0 = Release|Any CPU
{2B69AD6D-2B5A-4023-8EAD-0BD1B18E028A}.Release|Any CPU.ActiveCfg = Installer|Any CPU
{2B69AD6D-2B5A-4023-8EAD-0BD1B18E028A}.Release|Any CPU.Build.0 = Installer|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {EBC981CA-0309-468F-984F-067BA2A6DF99}
EndGlobalSection
EndGlobal
@@ -4,18 +4,20 @@
PackageIdentifier: Tgstation.Server
PackageVersion: 0.22.475 # Set before publish by push_manifest.ps1
Installers:
- InstallerUrl: https://github.com/tgstation/tgstation-server/releases/download/tgstation-server-v0.22.475/tgstation-server.msi # Set before publish by push_manifest.ps1
- InstallerUrl: https://github.com/tgstation/tgstation-server/releases/download/tgstation-server-v0.22.475/tgstation-server-installer.exe # Set before publish by push_manifest.ps1
InstallerLocale: en-US
Architecture: x86
InstallerType: msi
InstallerType: exe
Scope: machine
InstallerSha256: F749672C1BDBAC8CD8AEF7352B97E54C21CF389D798D0ED245CA75EC72521460 # Set before publish by push_manifest.ps1
InstallerSha256: CF0D4D2FD042098D826A226A05A9DAA5C792318CF48FD334F7FC06AF6A8A23B1 # Set before publish by push_manifest.ps1
InstallModes:
- interactive
- silent
InstallerSwitches:
Silent: /silent
SilentWithProgress: /passive
Log: /log <LOGPATH>
ProductCode: '{D24887FA-3228-4509-B5F3-4E07E349F278}'
RequireExplicitUpgrade: true
UpgradeBehavior: uninstallPrevious
UnsupportedOSArchitectures:
- arm
- arm64
@@ -0,0 +1,43 @@
# Note: This script requires that Tgstation.Server.Host and Tgstation.Server.Host.Service be built in Release configuration beforehand
$ErrorActionPreference="stop"
$startDirectory=$pwd
try
{
Remove-Item -Recurse -Force artifacts -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force build/package/winget/Tgstation.Server.Host.Service.Wix/bin -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force build/package/winget/Tgstation.Server.Host.Service.Wix/obj -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force build/package/winget/Tgstation.Server.Host.Service.Wix.Bundle/bin -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force build/package/winget/Tgstation.Server.Host.Service.Wix.Bundle/obj -ErrorAction SilentlyContinue
[XML]$versionXML = Get-Content build/Version.props -ErrorAction Stop
$redistUrl = $versionXML.Project.PropertyGroup.TgsRedistUrl
mkdir artifacts
$previousProgressPreference = $ProgressPreference
$ProgressPreference = 'SilentlyContinue'
try
{
Invoke-WebRequest -Uri $redistUrl -OutFile artifacts/hosting-bundle.exe
} finally {
$ProgressPreference = $previousProgressPreference
}
cd src/Tgstation.Server.Host
dotnet publish -c Release --no-build -o ../../artifacts/Tgstation.Server.Host
if (-Not $?) {
exit $lastexitcode
}
cd ../Tgstation.Server.Host.Service
dotnet publish -c Release --no-build -o ../../artifacts/Tgstation.Server.Host.Service
if (-Not $?) {
exit $lastexitcode
}
mv ../../artifacts/Tgstation.Server.Host.Service/Tgstation.Server.Host.Service.exe ../../artifacts/
} finally {
cd $startDirectory
}
+1 -1
View File
@@ -1,5 +1,5 @@
param(
[string]$MsiPath = 'packaging/build/package/winget/Tgstation.Server.Host.Service.Msi/Release/tgstation-server.msi'
[string]$MsiPath = 'packaging/build/package/winget/Tgstation.Server.Host.Service.Wix/Release/tgstation-server.msi'
)
$ErrorActionPreference="Stop"
+1 -1
View File
@@ -10,7 +10,7 @@ After=mssql-server.service
Type=notify-reload
NotifyAccess=all
WorkingDirectory=/opt/tgstation-server
ExecStart=/usr/bin/dotnet Tgstation.Server.Host.Console.dll --General:SetupWizardMode=Never --Internal:UsingSystemD=true
ExecStart=/usr/bin/dotnet Tgstation.Server.Host.Console.dll --appsettings-base-path=/etc/tgstation-server --General:SetupWizardMode=Never --Internal:UsingSystemD=true
TimeoutStartSec=600
Restart=Always
KillMode=process
@@ -0,0 +1,13 @@
namespace Tgstation.Server.Host.Common
{
/// <summary>
/// Constant values.
/// </summary>
public static class Constants
{
/// <summary>
/// The name of the project.
/// </summary>
public const string CanonicalPackageName = "tgstation-server";
}
}
@@ -1,6 +1,4 @@
using System.Collections.Generic;
namespace Tgstation.Server.Host.Common
namespace Tgstation.Server.Host.Common
{
/// <summary>
/// Values able to be passed via the update file path.
@@ -22,14 +20,30 @@ namespace Tgstation.Server.Host.Common
/// </summary>
public const string CommandDetachingShutdown = "detach";
#if NET6_0_OR_GREATER
/// <summary>
/// All of the <see cref="PipeCommands"/> represented as a <see cref="IReadOnlyCollection{T}"/>.
/// All of the <see cref="PipeCommands"/> represented as a <see cref="System.Collections.Generic.IReadOnlyList{T}"/>.
/// </summary>
public static IReadOnlyList<string> AllCommands { get; } = new[]
public static System.Collections.Generic.IReadOnlyList<string> AllCommands { get; } = new[]
{
CommandStop,
CommandGracefulShutdown,
CommandDetachingShutdown,
};
#endif
/// <summary>
/// Gets the <see cref="int"/> value of a given <paramref name="command"/>.
/// </summary>
/// <param name="command">The <see cref="PipeCommands"/>.</param>
/// <returns>The <see cref="int"/> value of the command or <see langword="null"/> if it was unrecognized.</returns>
public static int? GetCommandId(string command)
=> command switch
{
CommandStop => 128, // Windows only allows commands 128-256: https://stackoverflow.com/a/62858106
CommandGracefulShutdown => 129,
CommandDetachingShutdown => 130,
_ => null,
};
}
}
@@ -2,7 +2,7 @@
<Import Project="../../build/Common.props" />
<PropertyGroup>
<TargetFramework>$(TgsNetVersion)</TargetFramework>
<TargetFrameworks>$(TgsFrameworkVersion);net2.0</TargetFrameworks>
<Version>$(TgsCoreVersion)</Version>
<IsPackable>false</IsPackable>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
@@ -3,7 +3,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>$(TgsNetVersion)</TargetFramework>
<TargetFramework>$(TgsFrameworkVersion)</TargetFramework>
<Version>$(TgsCoreVersion)</Version>
<UseAppHost>false</UseAppHost>
<IsPackable>false</IsPackable>
+81 -65
View File
@@ -8,6 +8,7 @@ using System.Threading.Tasks;
using McMaster.Extensions.CommandLineUtils;
using Microsoft.Extensions.Hosting.WindowsServices;
using Microsoft.Extensions.Logging;
using Tgstation.Server.Host.Common;
@@ -30,56 +31,50 @@ namespace Tgstation.Server.Host.Service
/// <summary>
/// The --uninstall or -u option.
/// </summary>
[Option(ShortName = "u")]
[Option(ShortName = "u", Description = "Uninstalls ANY installed tgstation-server service >=v4.0.0")]
public bool Uninstall { get; }
/// <summary>
/// The --detach or -x option. Valid only with <see cref="Install"/>.
/// </summary>
[Option(ShortName = "x")]
[Option(ShortName = "x", Description = "If the service has to stop, detach any running DreamDaemon processes beforehand. Only supported on versions >=5.13.0")]
public bool Detach { get; }
/// <summary>
/// The --restart or -r option.
/// </summary>
[Option(ShortName = "r")]
[Option(ShortName = "r", Description = "Stop and restart the tgstation-server service")]
public bool Restart { get; }
/// <summary>
/// The --install or -i option.
/// </summary>
[Option(ShortName = "i")]
[Option(ShortName = "i", Description = "Installs this executable as the tgstation-server Windows service")]
public bool Install { get; set; }
/// <summary>
/// The --force or -f option.
/// </summary>
[Option(ShortName = "f")]
[Option(ShortName = "f", Description = "Automatically agree to uninstall prompts")]
public bool Force { get; set; }
/// <summary>
/// The --silent or -s option.
/// </summary>
[Option(ShortName = "s")]
[Option(ShortName = "s", Description = "Suppresses console output from the host watchdog")]
public bool Silent { get; set; }
/// <summary>
/// The --configure or -c option.
/// </summary>
[Option(ShortName = "c")]
[Option(ShortName = "c", Description = "Runs the TGS setup wizard")]
public bool Configure { get; set; }
/// <summary>
/// The --trace or -t option. Enables trace logs.
/// The --passthroughargs or -p option.
/// </summary>
[Option(ShortName = "t")]
public bool Trace { get; set; }
/// <summary>
/// The --debug or -d option. Enables debug logs.
/// </summary>
[Option(ShortName = "d")]
public bool Debug { get; set; }
[Option(ShortName = "p", Description = "Arguments passed to main host process")]
public string PassthroughArgs { get; set; }
/// <summary>
/// Entrypoint for the application.
@@ -108,6 +103,7 @@ namespace Tgstation.Server.Host.Service
process.StartInfo.Arguments = serviceToUninstall == null
? $"create tgstation-server binPath=\"{exePath}\" start=auto depend=Tcpip/Dhcp/Dnscache"
: $"delete {serviceToUninstall}";
process.StartInfo.CreateNoWindow = false;
process.Start();
@@ -121,35 +117,53 @@ namespace Tgstation.Server.Host.Service
public async Task OnExecuteAsync()
{
var standardRun = !Install && !Uninstall && !Configure;
if (standardRun)
if (!Silent && !WindowsServiceHelpers.IsWindowsService())
{
#if NET7_0_OR_GREATER
#error Deprecated functionality, remove
#endif
var result = NativeMethods.MessageBox(
default,
"You are running the TGS windows service executable directly. It should only be run by the service control manager. Would you like to install and configure the service in this location? (Note: This functionality is deprecated and will be removed in a future version)",
"TGS Service",
NativeMethods.MessageBoxButtons.YesNo);
if (Environment.UserInteractive && standardRun)
{
var result = NativeMethods.MessageBox(
default,
"You are running the TGS windows service executable directly. It should only be run by the service control manager. Would you like to install and configure the service in this location?",
"TGS Service",
NativeMethods.MessageBoxButtons.YesNo);
if (result != NativeMethods.DialogResult.Yes)
return;
if (result != NativeMethods.DialogResult.Yes)
return;
Install = true;
Configure = true;
}
Install = true;
Configure = true;
}
else
using (var service = new ServerService(WatchdogFactory, GetPassthroughArgs(), LogLevel.Trace))
{
service.Run();
return;
}
if (Configure)
await RunConfigure(CancellationToken.None); // DCT: None available
await RunConfigure(CancellationToken.None); // DCT: None available
bool stopped = false;
if (Uninstall)
{
foreach (ServiceController sc in ServiceController.GetServices())
if (sc.ServiceName == ServerService.Name)
{
bool match;
using (sc)
{
match = sc.ServiceName == ServerService.Name;
if (match)
RestartService(sc);
}
if (match)
{
RestartService(sc);
await InvokeSC(ServerService.Name);
break;
}
}
stopped = true;
}
@@ -157,22 +171,17 @@ namespace Tgstation.Server.Host.Service
if (Install)
stopped |= await RunServiceInstall();
if (standardRun)
{
using var service = new ServerService(WatchdogFactory, Trace ? LogLevel.Trace : Debug ? LogLevel.Debug : LogLevel.Information);
ServiceBase.Run(service);
}
if (Restart)
foreach (ServiceController sc in ServiceController.GetServices())
if (sc.ServiceName == ServerService.Name)
{
if (!stopped)
RestartService(sc);
using (sc)
if (sc.ServiceName == ServerService.Name)
{
if (!stopped)
RestartService(sc);
sc.Start();
break;
}
sc.Start();
break;
}
}
/// <summary>
@@ -183,29 +192,30 @@ namespace Tgstation.Server.Host.Service
{
// First check if the service already exists
bool serviceStopped = false;
if (Force || Environment.UserInteractive)
if (Force || !WindowsServiceHelpers.IsWindowsService())
foreach (ServiceController sc in ServiceController.GetServices())
{
var serviceName = sc.ServiceName;
if (serviceName == ServerService.Name || serviceName == "tgstation-server-4")
using (sc)
{
NativeMethods.DialogResult result = !Force
? NativeMethods.MessageBox(
default,
$"You already have another TGS service installed ({sc.ServiceName}). Would you like to uninstall it now? Pressing \"No\" will cancel this install.",
"TGS Service",
NativeMethods.MessageBoxButtons.YesNo)
: NativeMethods.DialogResult.Yes;
if (result != NativeMethods.DialogResult.Yes)
return false; // is this needed after exit?
var serviceName = sc.ServiceName;
if (serviceName == ServerService.Name || serviceName == "tgstation-server-4")
{
NativeMethods.DialogResult result = !Force
? NativeMethods.MessageBox(
default,
$"You already have another TGS service installed ({sc.ServiceName}). Would you like to uninstall it now? Pressing \"No\" will cancel this install.",
"TGS Service",
NativeMethods.MessageBoxButtons.YesNo)
: NativeMethods.DialogResult.Yes;
if (result != NativeMethods.DialogResult.Yes)
return false; // is this needed after exit?
// Stop it first to give it some cleanup time
RestartService(sc);
// Stop it first to give it some cleanup time
RestartService(sc);
// And remove it
await InvokeSC(sc.ServiceName);
// And remove it
await InvokeSC(sc.ServiceName);
}
}
}
await InvokeSC(null);
@@ -225,7 +235,7 @@ namespace Tgstation.Server.Host.Service
if (!stop)
{
serviceController.ExecuteCommand(
ServerService.GetCommand(
PipeCommands.GetCommandId(
PipeCommands.CommandDetachingShutdown)
.Value);
serviceController.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(30));
@@ -254,7 +264,13 @@ namespace Tgstation.Server.Host.Service
});
var watchdog = WatchdogFactory.CreateWatchdog(new NoopSignalChecker(), loggerFactory);
await watchdog.RunAsync(true, Array.Empty<string>(), cancellationToken);
await watchdog.RunAsync(true, GetPassthroughArgs(), cancellationToken);
}
/// <summary>
/// Format <see cref="PassthroughArgs"/> into an <see cref="Array"/>.
/// </summary>
/// <returns><see cref="PassthroughArgs"/> formatted as a <see cref="string"/> <see cref="Array"/>.</returns>
string[] GetPassthroughArgs() => PassthroughArgs?.Split(' ', StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty<string>();
}
}
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
@@ -24,7 +25,7 @@ namespace Tgstation.Server.Host.Service
/// <summary>
/// The canonical windows service name.
/// </summary>
public const string Name = "tgstation-server";
public const string Name = Constants.CanonicalPackageName;
/// <summary>
/// The <see cref="IWatchdog"/> for the <see cref="ServerService"/>.
@@ -32,7 +33,12 @@ namespace Tgstation.Server.Host.Service
readonly IWatchdogFactory watchdogFactory;
/// <summary>
/// The minimum <see cref="Microsoft.Extensions.Logging.LogLevel"/> for the <see cref="EventLog"/>.
/// The <see cref="Array"/> of command line arguments the service was invoked with.
/// </summary>
readonly string[] commandLineArguments;
/// <summary>
/// The minimum <see cref="LogLevel"/> for the <see cref="EventLog"/>.
/// </summary>
readonly LogLevel minimumLogLevel;
@@ -61,28 +67,16 @@ namespace Tgstation.Server.Host.Service
/// </summary>
AnonymousPipeServerStream pipeServer;
/// <summary>
/// Gets the <see cref="int"/> value of a given <paramref name="command"/>.
/// </summary>
/// <param name="command">The <see cref="PipeCommands"/>.</param>
/// <returns>The <see cref="int"/> value of the command or <see langword="null"/> if it was unrecognized.</returns>
public static int? GetCommand(string command)
=> command switch
{
PipeCommands.CommandStop => 128, // Windows only allows commands 128-256: https://stackoverflow.com/a/62858106
PipeCommands.CommandGracefulShutdown => 129,
PipeCommands.CommandDetachingShutdown => 130,
_ => null,
};
/// <summary>
/// Initializes a new instance of the <see cref="ServerService"/> class.
/// </summary>
/// <param name="watchdogFactory">The value of <see cref="watchdogFactory"/>.</param>
/// <param name="minimumLogLevel">The minimum <see cref="Microsoft.Extensions.Logging.LogLevel"/> to record in the event log.</param>
public ServerService(IWatchdogFactory watchdogFactory, LogLevel minimumLogLevel)
/// <param name="commandLineArguments">The value of <see cref="commandLineArguments"/>.</param>
/// <param name="minimumLogLevel">The minimum <see cref="LogLevel"/> to record in the event log.</param>
public ServerService(IWatchdogFactory watchdogFactory, string[] commandLineArguments, LogLevel minimumLogLevel)
{
this.watchdogFactory = watchdogFactory ?? throw new ArgumentNullException(nameof(watchdogFactory));
this.commandLineArguments = commandLineArguments ?? throw new ArgumentNullException(nameof(commandLineArguments));
this.minimumLogLevel = minimumLogLevel;
ServiceName = Name;
}
@@ -98,6 +92,11 @@ namespace Tgstation.Server.Host.Service
}
}
/// <summary>
/// Executes the <see cref="ServerService"/>.
/// </summary>
public void Run() => Run(this);
/// <inheritdoc />
protected override void Dispose(bool disposing)
{
@@ -117,7 +116,7 @@ namespace Tgstation.Server.Host.Service
var commandsToCheck = PipeCommands.AllCommands;
foreach (var stringCommand in commandsToCheck)
{
var commandId = GetCommand(stringCommand);
var commandId = PipeCommands.GetCommandId(stringCommand);
if (command == commandId)
{
SendCommandToUpdatePath(stringCommand);
@@ -149,7 +148,15 @@ namespace Tgstation.Server.Host.Service
cancellationTokenSource?.Dispose();
cancellationTokenSource = new CancellationTokenSource();
watchdogTask = RunWatchdog(watchdog, args, cancellationTokenSource.Token);
var newArgs = new List<string>(commandLineArguments.Length + args.Length + 1)
{
"--General:SetupWizardMode=Never",
};
newArgs.AddRange(commandLineArguments);
newArgs.AddRange(args);
watchdogTask = RunWatchdog(watchdog, newArgs.ToArray(), cancellationTokenSource.Token);
}
/// <inheritdoc />
@@ -3,7 +3,7 @@
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>$(TgsNetVersion)-windows</TargetFramework>
<TargetFramework>$(TgsFrameworkVersion)-windows</TargetFramework>
<Version>$(TgsCoreVersion)</Version>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<!-- DO NOT ENABLE THIS, It makes the service require the desktop runtime instead of the ASP NET Core Hosting Bundle -->
@@ -26,6 +26,7 @@
<ItemGroup>
<!-- Usage: Command line argument support -->
<PackageReference Include="McMaster.Extensions.CommandLineUtils" Version="4.0.2" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.1" />
<!-- Usage: Windows event log logging plugin -->
<PackageReference Include="Microsoft.Extensions.Logging.EventLog" Version="7.0.0" />
<!-- Usage: Console logging plugin -->
@@ -48,5 +49,5 @@
<AdditionalFiles Include="../../build/stylecop.json" />
<AdditionalFiles Include="../../build/uac_elevation_manifest.xml" />
</ItemGroup>
</Project>
@@ -2,7 +2,7 @@
<Import Project="../../build/Common.props" />
<PropertyGroup>
<TargetFramework>$(TgsNetVersion)</TargetFramework>
<TargetFramework>$(TgsFrameworkVersion)</TargetFramework>
<DebugType>Full</DebugType>
<AddSyntheticProjectReferencesForSolutionDependencies>false</AddSyntheticProjectReferencesForSolutionDependencies>
<Version>$(TgsHostWatchdogVersion)</Version>
@@ -75,7 +75,8 @@ namespace Tgstation.Server.Host.Configuration
? Directory
: ioManager.ConcatPath(
directoryToUse,
assemblyInformationProvider.VersionPrefix);
assemblyInformationProvider.VersionPrefix,
"logs");
}
}
}
@@ -19,5 +19,10 @@
/// If the server is running under SystemD.
/// </summary>
public bool UsingSystemD { get; set; }
/// <summary>
/// The base path for the app settings configuration files.
/// </summary>
public string AppSettingsBasePath { get; set; }
}
}
+17 -3
View File
@@ -10,6 +10,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Tgstation.Server.Host.Configuration;
using Tgstation.Server.Host.Core;
using Tgstation.Server.Host.Extensions;
using Tgstation.Server.Host.IO;
@@ -59,14 +60,27 @@ namespace Tgstation.Server.Host
args[oldArgs.Length] = "--hostBuilder:reloadConfigOnChange=false";
}
var basePath = IOManager.ResolvePath();
const string AppSettings = "appsettings";
const string AppSettingsRelocationKey = $"--{AppSettings}-base-path=";
var appsettingsRelativeBasePathArgument = args.FirstOrDefault(arg => arg.StartsWith(AppSettingsRelocationKey, StringComparison.Ordinal));
string basePath;
if (appsettingsRelativeBasePathArgument != null)
basePath = IOManager.ResolvePath(appsettingsRelativeBasePathArgument[AppSettingsRelocationKey.Length..]);
else
basePath = IOManager.ResolvePath();
// this is a massive bloody hack but I don't know a better way to do it
// It's needed for the setup wizard
Environment.SetEnvironmentVariable($"{InternalConfiguration.Section}__{nameof(InternalConfiguration.AppSettingsBasePath)}", basePath);
IHostBuilder CreateDefaultBuilder() => Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, builder) =>
{
builder.SetBasePath(basePath);
builder.AddYamlFile("appsettings.yml", optional: true, reloadOnChange: false)
.AddYamlFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.yml", optional: true, reloadOnChange: false);
builder.AddYamlFile($"{AppSettings}.yml", optional: true, reloadOnChange: false)
.AddYamlFile($"{AppSettings}.{context.HostingEnvironment.EnvironmentName}.yml", optional: true, reloadOnChange: false);
// reorganize the builder so our yaml configs don't override the env/cmdline configs
// values obtained via debugger
+26 -8
View File
@@ -27,6 +27,7 @@ using Tgstation.Server.Host.Extensions.Converters;
using Tgstation.Server.Host.IO;
using Tgstation.Server.Host.System;
using Tgstation.Server.Host.Utils;
using YamlDotNet.Serialization;
namespace Tgstation.Server.Host.Setup
@@ -79,6 +80,11 @@ namespace Tgstation.Server.Host.Setup
/// </summary>
readonly GeneralConfiguration generalConfiguration;
/// <summary>
/// The <see cref="InternalConfiguration"/> for the <see cref="SetupWizard"/>.
/// </summary>
readonly InternalConfiguration internalConfiguration;
/// <summary>
/// A <see cref="TaskCompletionSource"/> that will complete when the <see cref="IConfiguration"/> is reloaded.
/// </summary>
@@ -97,6 +103,7 @@ namespace Tgstation.Server.Host.Setup
/// <param name="applicationLifetime">The value of <see cref="applicationLifetime"/>.</param>
/// <param name="configuration">The <see cref="IConfiguration"/> in use.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="generalConfiguration"/>.</param>
/// <param name="internalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="internalConfiguration"/>.</param>
public SetupWizard(
IIOManager ioManager,
IConsole console,
@@ -107,7 +114,8 @@ namespace Tgstation.Server.Host.Setup
IAsyncDelayer asyncDelayer,
IHostApplicationLifetime applicationLifetime,
IConfiguration configuration,
IOptions<GeneralConfiguration> generalConfigurationOptions)
IOptions<GeneralConfiguration> generalConfigurationOptions,
IOptions<InternalConfiguration> internalConfigurationOptions)
{
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
this.console = console ?? throw new ArgumentNullException(nameof(console));
@@ -120,6 +128,7 @@ namespace Tgstation.Server.Host.Setup
ArgumentNullException.ThrowIfNull(configuration);
generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions));
internalConfiguration = internalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(internalConfigurationOptions));
configuration
.GetReloadToken()
@@ -297,7 +306,13 @@ namespace Tgstation.Server.Host.Setup
/// <returns>A <see cref="Task{TResult}"/> resulting in the SQLite database path to store in the configuration.</returns>
async Task<string> ValidateNonExistantSqliteDBName(string databaseName, CancellationToken cancellationToken)
{
var resolvedPath = ioManager.ResolvePath(databaseName);
var dbPathIsRooted = Path.IsPathRooted(databaseName);
var resolvedPath = ioManager.ResolvePath(
dbPathIsRooted
? databaseName
: ioManager.ConcatPath(
internalConfiguration.AppSettingsBasePath,
databaseName));
try
{
var directoryName = ioManager.GetDirectoryName(resolvedPath);
@@ -319,9 +334,9 @@ namespace Tgstation.Server.Host.Setup
return null;
}
if (!Path.IsPathRooted(databaseName))
if (!dbPathIsRooted)
{
await console.WriteAsync("Note, this relative path (currently) resolves to the following:", true, cancellationToken);
await console.WriteAsync("Note, this relative path currently resolves to the following:", true, cancellationToken);
await console.WriteAsync(resolvedPath, true, cancellationToken);
bool writeResolved = await PromptYesNo(
"Would you like to save the relative path in the configuration? If not, the full path will be saved.",
@@ -355,8 +370,6 @@ namespace Tgstation.Server.Host.Setup
"It is, however, the easiest option to get started with and will pose few if any problems in a single user scenario.",
true,
cancellationToken);
await asyncDelayer.Delay(TimeSpan.FromSeconds(3), cancellationToken);
}
await console.WriteAsync("What SQL database type will you be using?", true, cancellationToken);
@@ -962,7 +975,10 @@ namespace Tgstation.Server.Host.Setup
try
{
await ioManager.WriteAllBytes(userConfigFileName, configBytes, cancellationToken);
await ioManager.WriteAllBytes(
userConfigFileName,
configBytes,
cancellationToken);
// Ensure the reload
if (generalConfiguration.SetupWizardMode != SetupWizardMode.Only)
@@ -1046,7 +1062,9 @@ namespace Tgstation.Server.Host.Setup
return;
}
var userConfigFileName = String.Format(CultureInfo.InvariantCulture, "appsettings.{0}.yml", hostingEnvironment.EnvironmentName);
var userConfigFileName = ioManager.ConcatPath(
internalConfiguration.AppSettingsBasePath,
String.Format(CultureInfo.InvariantCulture, "appsettings.{0}.yml", hostingEnvironment.EnvironmentName));
async Task HandleSetupCancel()
{
@@ -2,7 +2,7 @@
<Import Project="../../build/Common.props" />
<PropertyGroup>
<TargetFramework>$(TgsNetVersion)</TargetFramework>
<TargetFramework>$(TgsFrameworkVersion)</TargetFramework>
<Version>$(TgsCoreVersion)</Version>
<IncludeOpenAPIAnalyzers>true</IncludeOpenAPIAnalyzers>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
@@ -2,7 +2,7 @@
<Import Project="../../build/Common.props" />
<PropertyGroup>
<TargetFramework>$(TgsNetVersion)</TargetFramework>
<TargetFramework>$(TgsFrameworkVersion)</TargetFramework>
</PropertyGroup>
<ItemGroup>
@@ -2,7 +2,7 @@
<Import Project="../../build/Common.props" />
<PropertyGroup>
<TargetFramework>$(TgsNetVersion)</TargetFramework>
<TargetFramework>$(TgsFrameworkVersion)</TargetFramework>
</PropertyGroup>
<ItemGroup>
@@ -2,7 +2,7 @@
<Import Project="../../build/Common.props" />
<PropertyGroup>
<TargetFramework>$(TgsNetVersion)</TargetFramework>
<TargetFramework>$(TgsFrameworkVersion)</TargetFramework>
</PropertyGroup>
<ItemGroup>
@@ -19,9 +19,10 @@ namespace Tgstation.Server.Host.Service.Tests
[TestMethod]
public void TestConstructionAndDisposal()
{
Assert.ThrowsException<ArgumentNullException>(() => new ServerService(null, default));
Assert.ThrowsException<ArgumentNullException>(() => new ServerService(null, null, default));
var mockWatchdogFactory = new Mock<IWatchdogFactory>();
new ServerService(mockWatchdogFactory.Object, default).Dispose();
Assert.ThrowsException<ArgumentNullException>(() => new ServerService(mockWatchdogFactory.Object, null, default));
new ServerService(mockWatchdogFactory.Object, Array.Empty<string>(), default).Dispose();
}
[TestMethod]
@@ -38,7 +39,7 @@ namespace Tgstation.Server.Host.Service.Tests
var mockWatchdogFactory = new Mock<IWatchdogFactory>();
mockWatchdogFactory.Setup(x => x.CreateWatchdog(It.IsNotNull<ISignalChecker>(), It.IsNotNull<ILoggerFactory>())).Returns(mockWatchdog.Object).Verifiable();
using (var service = new ServerService(mockWatchdogFactory.Object, default))
using (var service = new ServerService(mockWatchdogFactory.Object, Array.Empty<string>(), default))
{
onStart.Invoke(service, new object[] { args });
onStop.Invoke(service, Array.Empty<object>());
@@ -2,7 +2,7 @@
<Import Project="../../build/Common.props" />
<PropertyGroup>
<TargetFramework>$(TgsNetVersion)-windows</TargetFramework>
<TargetFramework>$(TgsFrameworkVersion)-windows</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
@@ -2,7 +2,7 @@
<Import Project="../../build/Common.props" />
<PropertyGroup>
<TargetFramework>$(TgsNetVersion)</TargetFramework>
<TargetFramework>$(TgsFrameworkVersion)</TargetFramework>
<OutputType>Exe</OutputType>
</PropertyGroup>
@@ -27,26 +27,28 @@ namespace Tgstation.Server.Host.Setup.Tests
[TestMethod]
public void TestConstructionThrows()
{
Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(null, null, null, null, null, null, null, null, null, null));
Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(null, null, null, null, null, null, null, null, null, null, null));
var mockIOManager = new Mock<IIOManager>();
Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, null, null, null, null, null, null, null, null, null));
Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, null, null, null, null, null, null, null, null, null, null));
var mockConsole = new Mock<IConsole>();
Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, null, null, null, null, null, null, null, null));
Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, null, null, null, null, null, null, null, null, null));
var mockHostingEnvironment = new Mock<IWebHostEnvironment>();
Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, null, null, null, null, null, null, null));
Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, null, null, null, null, null, null, null, null));
var mockAssemblyInfoProvider = new Mock<IAssemblyInformationProvider>();
Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockAssemblyInfoProvider.Object, null, null, null, null, null, null));
Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockAssemblyInfoProvider.Object, null, null, null, null, null, null, null));
var mockDBConnectionFactory = new Mock<IDatabaseConnectionFactory>();
Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockAssemblyInfoProvider.Object, mockDBConnectionFactory.Object, null, null, null, null, null));
Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockAssemblyInfoProvider.Object, mockDBConnectionFactory.Object, null, null, null, null, null, null));
var mockPlatformIdentifier = new Mock<IPlatformIdentifier>();
Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockAssemblyInfoProvider.Object, mockDBConnectionFactory.Object, mockPlatformIdentifier.Object, null, null, null, null));
Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockAssemblyInfoProvider.Object, mockDBConnectionFactory.Object, mockPlatformIdentifier.Object, null, null, null, null, null));
var mockAsyncDelayer = new Mock<IAsyncDelayer>();
Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockAssemblyInfoProvider.Object, mockDBConnectionFactory.Object, mockPlatformIdentifier.Object, mockAsyncDelayer.Object, null, null, null));
Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockAssemblyInfoProvider.Object, mockDBConnectionFactory.Object, mockPlatformIdentifier.Object, mockAsyncDelayer.Object, null, null, null, null));
var mockLifetime = new Mock<IHostApplicationLifetime>();
Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockAssemblyInfoProvider.Object, mockDBConnectionFactory.Object, mockPlatformIdentifier.Object, mockAsyncDelayer.Object, mockLifetime.Object, null, null));
Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockAssemblyInfoProvider.Object, mockDBConnectionFactory.Object, mockPlatformIdentifier.Object, mockAsyncDelayer.Object, mockLifetime.Object, null, null, null));
var mockConfiguration = new Mock<IConfiguration>();
mockConfiguration.Setup(x => x.GetReloadToken()).Returns(Mock.Of<IChangeToken>());
Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockAssemblyInfoProvider.Object, mockDBConnectionFactory.Object, mockPlatformIdentifier.Object, mockAsyncDelayer.Object, mockLifetime.Object, mockConfiguration.Object, null));
Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockAssemblyInfoProvider.Object, mockDBConnectionFactory.Object, mockPlatformIdentifier.Object, mockAsyncDelayer.Object, mockLifetime.Object, mockConfiguration.Object, null, null));
var mockGeneralConfigurationOptions = Options.Create(new GeneralConfiguration());
Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockAssemblyInfoProvider.Object, mockDBConnectionFactory.Object, mockPlatformIdentifier.Object, mockAsyncDelayer.Object, mockLifetime.Object, mockConfiguration.Object, mockGeneralConfigurationOptions, null));
}
[TestMethod]
@@ -59,6 +61,7 @@ namespace Tgstation.Server.Host.Setup.Tests
var mockDBConnectionFactory = new Mock<IDatabaseConnectionFactory>();
var mockLifetime = new Mock<IHostApplicationLifetime>();
var mockGeneralConfigurationOptions = new Mock<IOptions<GeneralConfiguration>>();
var mockInternalConfigurationOptions = new Mock<IOptions<InternalConfiguration>>();
var mockPlatformIdentifier = new Mock<IPlatformIdentifier>();
var mockAsyncDelayer = new Mock<IAsyncDelayer>();
var mockConfiguration = new Mock<IConfiguration>();
@@ -85,8 +88,24 @@ namespace Tgstation.Server.Host.Setup.Tests
};
mockGeneralConfigurationOptions.SetupGet(x => x.Value).Returns(testGeneralConfig).Verifiable();
var wizard = new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockAssemblyInfoProvider.Object, mockDBConnectionFactory.Object, mockPlatformIdentifier.Object, mockAsyncDelayer.Object, mockLifetime.Object, mockConfiguration.Object, mockGeneralConfigurationOptions.Object);
var testInternalConfig = new InternalConfiguration
{
AppSettingsBasePath = "asdfasdfasdf"
};
mockInternalConfigurationOptions.SetupGet(x => x.Value).Returns(testInternalConfig).Verifiable();
var wizard = new SetupWizard(
mockIOManager.Object,
mockConsole.Object,
mockHostingEnvironment.Object,
mockAssemblyInfoProvider.Object,
mockDBConnectionFactory.Object,
mockPlatformIdentifier.Object,
mockAsyncDelayer.Object,
mockLifetime.Object,
mockConfiguration.Object,
mockGeneralConfigurationOptions.Object,
mockInternalConfigurationOptions.Object);
mockPlatformIdentifier.SetupGet(x => x.IsWindows).Returns(true).Verifiable();
mockAsyncDelayer.Setup(x => x.Delay(It.IsAny<TimeSpan>(), It.IsAny<CancellationToken>())).Returns(Task.CompletedTask).Verifiable();
@@ -100,6 +119,11 @@ namespace Tgstation.Server.Host.Setup.Tests
await Assert.ThrowsExceptionAsync<InvalidOperationException>(() => RunWizard());
mockConsole.SetupGet(x => x.Available).Returns(true).Verifiable();
mockIOManager.Setup(x => x.ConcatPath(testInternalConfig.AppSettingsBasePath, It.IsNotNull<string>())).Returns<string[]>(paths =>
{
Assert.AreEqual(2, paths.Length);
return $"{paths[0]}/{paths[1]}";
}).Verifiable();
mockIOManager.Setup(x => x.FileExists(It.IsNotNull<string>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(true)).Verifiable();
mockIOManager.Setup(x => x.ReadAllBytes(It.IsNotNull<string>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(Encoding.UTF8.GetBytes("less profane"))).Verifiable();
mockIOManager
@@ -323,6 +347,7 @@ namespace Tgstation.Server.Host.Setup.Tests
mockSuccessCommand.VerifyAll();
mockIOManager.VerifyAll();
mockGeneralConfigurationOptions.VerifyAll();
mockInternalConfigurationOptions.VerifyAll();
mockConsole.VerifyAll();
mockGoodDbConnection.VerifyAll();
mockBadDbConnection.VerifyAll();
@@ -2,7 +2,7 @@
<Import Project="../../build/Common.props" />
<PropertyGroup>
<TargetFramework>$(TgsNetVersion)</TargetFramework>
<TargetFramework>$(TgsFrameworkVersion)</TargetFramework>
</PropertyGroup>
<ItemGroup>
@@ -2,7 +2,7 @@
<Import Project="../../build/Common.props" />
<PropertyGroup>
<TargetFramework>$(TgsNetVersion)</TargetFramework>
<TargetFramework>$(TgsFrameworkVersion)</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
@@ -2,7 +2,7 @@
<Import Project="../../build/Common.props" />
<PropertyGroup>
<TargetFramework>$(TgsNetVersion)</TargetFramework>
<TargetFramework>$(TgsFrameworkVersion)</TargetFramework>
</PropertyGroup>
<ItemGroup>
+100 -89
View File
@@ -222,7 +222,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "debian", "debian", "{08E7C6
build\package\deb\debian\control = build\package\deb\debian\control
build\package\deb\debian\copyright = build\package\deb\debian\copyright
build\package\deb\install_artifacts.sh = build\package\deb\install_artifacts.sh
build\package\deb\debian\links = build\package\deb\debian\links
build\package\deb\debian\postinst = build\package\deb\debian\postinst
build\package\deb\debian\prerm = build\package\deb\debian\prerm
build\package\deb\debian\rules = build\package\deb\debian\rules
@@ -235,9 +234,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "upstream", "upstream", "{B4
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "winget", "winget", "{506B9092-AF88-4DA2-84FD-C11646B695B0}"
ProjectSection(SolutionItems) = preProject
build\package\winget\build_msi.ps1 = build\package\winget\build_msi.ps1
build\package\winget\installer.sln = build\package\winget\installer.sln
build\package\winget\install_banner.jpg = build\package\winget\install_banner.jpg
build\package\winget\prepare_installer_input_artifacts.ps1 = build\package\winget\prepare_installer_input_artifacts.ps1
build\package\winget\push_manifest.ps1 = build\package\winget\push_manifest.ps1
EndProjectSection
EndProject
@@ -248,174 +246,186 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "manifest", "manifest", "{3F
build\package\winget\manifest\Tgstation.Server.yaml = build\package\winget\manifest\Tgstation.Server.yaml
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tgstation.Server.Host.Service.Msi", "Tgstation.Server.Host.Service.Msi", "{F5B9D394-229B-44A1-AD12-D8C078F06814}"
ProjectSection(SolutionItems) = preProject
build\package\winget\Tgstation.Server.Host.Service.Msi\README.md = build\package\winget\Tgstation.Server.Host.Service.Msi\README.md
build\package\winget\Tgstation.Server.Host.Service.Msi\Tgstation.Server.Host.Service.Msi.vdproj = build\package\winget\Tgstation.Server.Host.Service.Msi\Tgstation.Server.Host.Service.Msi.vdproj
EndProjectSection
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tgstation.Server.Host.Service.Wix.Extensions", "build\package\winget\Tgstation.Server.Host.Service.Wix.Extensions\Tgstation.Server.Host.Service.Wix.Extensions.csproj", "{28669D98-E15D-4A62-B1D1-7C11D4CB1DE0}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tgstation.Server.Host.Service.Configure", "Tgstation.Server.Host.Service.Configure", "{5DDA72D5-DBFD-4FB2-9EAB-61D047145246}"
ProjectSection(SolutionItems) = preProject
build\package\winget\Tgstation.Server.Host.Service.Configure\Program.cs = build\package\winget\Tgstation.Server.Host.Service.Configure\Program.cs
build\package\winget\Tgstation.Server.Host.Service.Configure\Tgstation.Server.Host.Service.Configure.csproj = build\package\winget\Tgstation.Server.Host.Service.Configure\Tgstation.Server.Host.Service.Configure.csproj
EndProjectSection
Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "Tgstation.Server.Host.Service.Wix", "build\package\winget\Tgstation.Server.Host.Service.Wix\Tgstation.Server.Host.Service.Wix.wixproj", "{82996E9D-5E63-4CC5-8179-612C71B4F56C}"
EndProject
Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "Tgstation.Server.Host.Service.Wix.Bundle", "build\package\winget\Tgstation.Server.Host.Service.Wix.Bundle\Tgstation.Server.Host.Service.Wix.Bundle.wixproj", "{9E66C6F1-E235-4979-83B5-C2B3FDAD6E01}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
DebugNoFramework|Any CPU = DebugNoFramework|Any CPU
DebugNoWindows|Any CPU = DebugNoWindows|Any CPU
Release|Any CPU = Release|Any CPU
ReleaseNoFramework|Any CPU = ReleaseNoFramework|Any CPU
ReleaseNoWindows|Any CPU = ReleaseNoWindows|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2B69AD6D-2B5A-4023-8EAD-0BD1B18E028A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2B69AD6D-2B5A-4023-8EAD-0BD1B18E028A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2B69AD6D-2B5A-4023-8EAD-0BD1B18E028A}.DebugNoFramework|Any CPU.ActiveCfg = Debug|Any CPU
{2B69AD6D-2B5A-4023-8EAD-0BD1B18E028A}.DebugNoFramework|Any CPU.Build.0 = Debug|Any CPU
{2B69AD6D-2B5A-4023-8EAD-0BD1B18E028A}.DebugNoWindows|Any CPU.ActiveCfg = Debug|Any CPU
{2B69AD6D-2B5A-4023-8EAD-0BD1B18E028A}.DebugNoWindows|Any CPU.Build.0 = Debug|Any CPU
{2B69AD6D-2B5A-4023-8EAD-0BD1B18E028A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2B69AD6D-2B5A-4023-8EAD-0BD1B18E028A}.Release|Any CPU.Build.0 = Release|Any CPU
{2B69AD6D-2B5A-4023-8EAD-0BD1B18E028A}.ReleaseNoFramework|Any CPU.ActiveCfg = Release|Any CPU
{2B69AD6D-2B5A-4023-8EAD-0BD1B18E028A}.ReleaseNoFramework|Any CPU.Build.0 = Release|Any CPU
{2B69AD6D-2B5A-4023-8EAD-0BD1B18E028A}.ReleaseNoWindows|Any CPU.ActiveCfg = Release|Any CPU
{2B69AD6D-2B5A-4023-8EAD-0BD1B18E028A}.ReleaseNoWindows|Any CPU.Build.0 = Release|Any CPU
{A09C947F-4B9B-4AEE-AB50-47055EA05F18}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A09C947F-4B9B-4AEE-AB50-47055EA05F18}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A09C947F-4B9B-4AEE-AB50-47055EA05F18}.DebugNoFramework|Any CPU.ActiveCfg = Debug|Any CPU
{A09C947F-4B9B-4AEE-AB50-47055EA05F18}.DebugNoFramework|Any CPU.Build.0 = Debug|Any CPU
{A09C947F-4B9B-4AEE-AB50-47055EA05F18}.DebugNoWindows|Any CPU.ActiveCfg = Debug|Any CPU
{A09C947F-4B9B-4AEE-AB50-47055EA05F18}.DebugNoWindows|Any CPU.Build.0 = Debug|Any CPU
{A09C947F-4B9B-4AEE-AB50-47055EA05F18}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A09C947F-4B9B-4AEE-AB50-47055EA05F18}.Release|Any CPU.Build.0 = Release|Any CPU
{A09C947F-4B9B-4AEE-AB50-47055EA05F18}.ReleaseNoFramework|Any CPU.ActiveCfg = Release|Any CPU
{A09C947F-4B9B-4AEE-AB50-47055EA05F18}.ReleaseNoFramework|Any CPU.Build.0 = Release|Any CPU
{A09C947F-4B9B-4AEE-AB50-47055EA05F18}.ReleaseNoWindows|Any CPU.ActiveCfg = Release|Any CPU
{A09C947F-4B9B-4AEE-AB50-47055EA05F18}.ReleaseNoWindows|Any CPU.Build.0 = Release|Any CPU
{D36B99C4-E771-42D6-A95F-1102B3E236DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D36B99C4-E771-42D6-A95F-1102B3E236DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D36B99C4-E771-42D6-A95F-1102B3E236DF}.DebugNoFramework|Any CPU.ActiveCfg = Debug|Any CPU
{D36B99C4-E771-42D6-A95F-1102B3E236DF}.DebugNoFramework|Any CPU.Build.0 = Debug|Any CPU
{D36B99C4-E771-42D6-A95F-1102B3E236DF}.DebugNoWindows|Any CPU.ActiveCfg = Debug|Any CPU
{D36B99C4-E771-42D6-A95F-1102B3E236DF}.DebugNoWindows|Any CPU.Build.0 = Debug|Any CPU
{D36B99C4-E771-42D6-A95F-1102B3E236DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D36B99C4-E771-42D6-A95F-1102B3E236DF}.Release|Any CPU.Build.0 = Release|Any CPU
{D36B99C4-E771-42D6-A95F-1102B3E236DF}.ReleaseNoFramework|Any CPU.ActiveCfg = Release|Any CPU
{D36B99C4-E771-42D6-A95F-1102B3E236DF}.ReleaseNoFramework|Any CPU.Build.0 = Release|Any CPU
{D36B99C4-E771-42D6-A95F-1102B3E236DF}.ReleaseNoWindows|Any CPU.ActiveCfg = Release|Any CPU
{D36B99C4-E771-42D6-A95F-1102B3E236DF}.ReleaseNoWindows|Any CPU.Build.0 = Release|Any CPU
{8B4A208D-A48A-4A5D-8B94-E2661138865D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8B4A208D-A48A-4A5D-8B94-E2661138865D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8B4A208D-A48A-4A5D-8B94-E2661138865D}.DebugNoFramework|Any CPU.ActiveCfg = Debug|Any CPU
{8B4A208D-A48A-4A5D-8B94-E2661138865D}.DebugNoFramework|Any CPU.Build.0 = Debug|Any CPU
{8B4A208D-A48A-4A5D-8B94-E2661138865D}.DebugNoWindows|Any CPU.ActiveCfg = Debug|Any CPU
{8B4A208D-A48A-4A5D-8B94-E2661138865D}.DebugNoWindows|Any CPU.Build.0 = Debug|Any CPU
{8B4A208D-A48A-4A5D-8B94-E2661138865D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8B4A208D-A48A-4A5D-8B94-E2661138865D}.Release|Any CPU.Build.0 = Release|Any CPU
{8B4A208D-A48A-4A5D-8B94-E2661138865D}.ReleaseNoFramework|Any CPU.ActiveCfg = Release|Any CPU
{8B4A208D-A48A-4A5D-8B94-E2661138865D}.ReleaseNoFramework|Any CPU.Build.0 = Release|Any CPU
{8B4A208D-A48A-4A5D-8B94-E2661138865D}.ReleaseNoWindows|Any CPU.ActiveCfg = Release|Any CPU
{8B4A208D-A48A-4A5D-8B94-E2661138865D}.ReleaseNoWindows|Any CPU.Build.0 = Release|Any CPU
{29927416-3B78-49A7-A560-5CCAA638B6B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{29927416-3B78-49A7-A560-5CCAA638B6B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{29927416-3B78-49A7-A560-5CCAA638B6B4}.DebugNoFramework|Any CPU.ActiveCfg = Debug|Any CPU
{29927416-3B78-49A7-A560-5CCAA638B6B4}.DebugNoWindows|Any CPU.ActiveCfg = Debug|Any CPU
{29927416-3B78-49A7-A560-5CCAA638B6B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{29927416-3B78-49A7-A560-5CCAA638B6B4}.Release|Any CPU.Build.0 = Release|Any CPU
{29927416-3B78-49A7-A560-5CCAA638B6B4}.ReleaseNoFramework|Any CPU.ActiveCfg = Release|Any CPU
{29927416-3B78-49A7-A560-5CCAA638B6B4}.ReleaseNoWindows|Any CPU.ActiveCfg = Release|Any CPU
{E0AC911F-7675-4A91-9499-D8A2E2390AAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E0AC911F-7675-4A91-9499-D8A2E2390AAD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E0AC911F-7675-4A91-9499-D8A2E2390AAD}.DebugNoFramework|Any CPU.ActiveCfg = Debug|Any CPU
{E0AC911F-7675-4A91-9499-D8A2E2390AAD}.DebugNoFramework|Any CPU.Build.0 = Debug|Any CPU
{E0AC911F-7675-4A91-9499-D8A2E2390AAD}.DebugNoWindows|Any CPU.ActiveCfg = Debug|Any CPU
{E0AC911F-7675-4A91-9499-D8A2E2390AAD}.DebugNoWindows|Any CPU.Build.0 = Debug|Any CPU
{E0AC911F-7675-4A91-9499-D8A2E2390AAD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E0AC911F-7675-4A91-9499-D8A2E2390AAD}.Release|Any CPU.Build.0 = Release|Any CPU
{E0AC911F-7675-4A91-9499-D8A2E2390AAD}.ReleaseNoFramework|Any CPU.ActiveCfg = Release|Any CPU
{E0AC911F-7675-4A91-9499-D8A2E2390AAD}.ReleaseNoFramework|Any CPU.Build.0 = Release|Any CPU
{E0AC911F-7675-4A91-9499-D8A2E2390AAD}.ReleaseNoWindows|Any CPU.ActiveCfg = Release|Any CPU
{E0AC911F-7675-4A91-9499-D8A2E2390AAD}.ReleaseNoWindows|Any CPU.Build.0 = Release|Any CPU
{BE0E8F49-334F-49D7-A04D-D82E9AB7AA36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BE0E8F49-334F-49D7-A04D-D82E9AB7AA36}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BE0E8F49-334F-49D7-A04D-D82E9AB7AA36}.DebugNoFramework|Any CPU.ActiveCfg = Debug|Any CPU
{BE0E8F49-334F-49D7-A04D-D82E9AB7AA36}.DebugNoFramework|Any CPU.Build.0 = Debug|Any CPU
{BE0E8F49-334F-49D7-A04D-D82E9AB7AA36}.DebugNoWindows|Any CPU.ActiveCfg = Debug|Any CPU
{BE0E8F49-334F-49D7-A04D-D82E9AB7AA36}.DebugNoWindows|Any CPU.Build.0 = Debug|Any CPU
{BE0E8F49-334F-49D7-A04D-D82E9AB7AA36}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BE0E8F49-334F-49D7-A04D-D82E9AB7AA36}.Release|Any CPU.Build.0 = Release|Any CPU
{BE0E8F49-334F-49D7-A04D-D82E9AB7AA36}.ReleaseNoFramework|Any CPU.ActiveCfg = Release|Any CPU
{BE0E8F49-334F-49D7-A04D-D82E9AB7AA36}.ReleaseNoFramework|Any CPU.Build.0 = Release|Any CPU
{BE0E8F49-334F-49D7-A04D-D82E9AB7AA36}.ReleaseNoWindows|Any CPU.ActiveCfg = Release|Any CPU
{BE0E8F49-334F-49D7-A04D-D82E9AB7AA36}.ReleaseNoWindows|Any CPU.Build.0 = Release|Any CPU
{E5301AF1-4F74-4982-BF24-95F23CC5D5B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E5301AF1-4F74-4982-BF24-95F23CC5D5B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E5301AF1-4F74-4982-BF24-95F23CC5D5B2}.DebugNoFramework|Any CPU.ActiveCfg = Debug|Any CPU
{E5301AF1-4F74-4982-BF24-95F23CC5D5B2}.DebugNoFramework|Any CPU.Build.0 = Debug|Any CPU
{E5301AF1-4F74-4982-BF24-95F23CC5D5B2}.DebugNoWindows|Any CPU.ActiveCfg = Debug|Any CPU
{E5301AF1-4F74-4982-BF24-95F23CC5D5B2}.DebugNoWindows|Any CPU.Build.0 = Debug|Any CPU
{E5301AF1-4F74-4982-BF24-95F23CC5D5B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E5301AF1-4F74-4982-BF24-95F23CC5D5B2}.Release|Any CPU.Build.0 = Release|Any CPU
{E5301AF1-4F74-4982-BF24-95F23CC5D5B2}.ReleaseNoFramework|Any CPU.ActiveCfg = Release|Any CPU
{E5301AF1-4F74-4982-BF24-95F23CC5D5B2}.ReleaseNoFramework|Any CPU.Build.0 = Release|Any CPU
{E5301AF1-4F74-4982-BF24-95F23CC5D5B2}.ReleaseNoWindows|Any CPU.ActiveCfg = Release|Any CPU
{E5301AF1-4F74-4982-BF24-95F23CC5D5B2}.ReleaseNoWindows|Any CPU.Build.0 = Release|Any CPU
{A3362FF6-550F-480F-859E-8EC1EB6EAB31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A3362FF6-550F-480F-859E-8EC1EB6EAB31}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A3362FF6-550F-480F-859E-8EC1EB6EAB31}.DebugNoFramework|Any CPU.ActiveCfg = Debug|Any CPU
{A3362FF6-550F-480F-859E-8EC1EB6EAB31}.DebugNoFramework|Any CPU.Build.0 = Debug|Any CPU
{A3362FF6-550F-480F-859E-8EC1EB6EAB31}.DebugNoWindows|Any CPU.ActiveCfg = Debug|Any CPU
{A3362FF6-550F-480F-859E-8EC1EB6EAB31}.DebugNoWindows|Any CPU.Build.0 = Debug|Any CPU
{A3362FF6-550F-480F-859E-8EC1EB6EAB31}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A3362FF6-550F-480F-859E-8EC1EB6EAB31}.Release|Any CPU.Build.0 = Release|Any CPU
{A3362FF6-550F-480F-859E-8EC1EB6EAB31}.ReleaseNoFramework|Any CPU.ActiveCfg = Release|Any CPU
{A3362FF6-550F-480F-859E-8EC1EB6EAB31}.ReleaseNoFramework|Any CPU.Build.0 = Release|Any CPU
{A3362FF6-550F-480F-859E-8EC1EB6EAB31}.ReleaseNoWindows|Any CPU.ActiveCfg = Release|Any CPU
{A3362FF6-550F-480F-859E-8EC1EB6EAB31}.ReleaseNoWindows|Any CPU.Build.0 = Release|Any CPU
{5D2D682C-6BF0-439C-850B-6AB945BBEAEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5D2D682C-6BF0-439C-850B-6AB945BBEAEA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5D2D682C-6BF0-439C-850B-6AB945BBEAEA}.DebugNoFramework|Any CPU.ActiveCfg = Debug|Any CPU
{5D2D682C-6BF0-439C-850B-6AB945BBEAEA}.DebugNoFramework|Any CPU.Build.0 = Debug|Any CPU
{5D2D682C-6BF0-439C-850B-6AB945BBEAEA}.DebugNoWindows|Any CPU.ActiveCfg = Debug|Any CPU
{5D2D682C-6BF0-439C-850B-6AB945BBEAEA}.DebugNoWindows|Any CPU.Build.0 = Debug|Any CPU
{5D2D682C-6BF0-439C-850B-6AB945BBEAEA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5D2D682C-6BF0-439C-850B-6AB945BBEAEA}.Release|Any CPU.Build.0 = Release|Any CPU
{5D2D682C-6BF0-439C-850B-6AB945BBEAEA}.ReleaseNoFramework|Any CPU.ActiveCfg = Release|Any CPU
{5D2D682C-6BF0-439C-850B-6AB945BBEAEA}.ReleaseNoFramework|Any CPU.Build.0 = Release|Any CPU
{5D2D682C-6BF0-439C-850B-6AB945BBEAEA}.ReleaseNoWindows|Any CPU.ActiveCfg = Release|Any CPU
{5D2D682C-6BF0-439C-850B-6AB945BBEAEA}.ReleaseNoWindows|Any CPU.Build.0 = Release|Any CPU
{7500F776-4384-4B5F-A8D8-22461CAD108B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7500F776-4384-4B5F-A8D8-22461CAD108B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7500F776-4384-4B5F-A8D8-22461CAD108B}.DebugNoFramework|Any CPU.ActiveCfg = Debug|Any CPU
{7500F776-4384-4B5F-A8D8-22461CAD108B}.DebugNoFramework|Any CPU.Build.0 = Debug|Any CPU
{7500F776-4384-4B5F-A8D8-22461CAD108B}.DebugNoWindows|Any CPU.ActiveCfg = Debug|Any CPU
{7500F776-4384-4B5F-A8D8-22461CAD108B}.DebugNoWindows|Any CPU.Build.0 = Debug|Any CPU
{7500F776-4384-4B5F-A8D8-22461CAD108B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7500F776-4384-4B5F-A8D8-22461CAD108B}.Release|Any CPU.Build.0 = Release|Any CPU
{7500F776-4384-4B5F-A8D8-22461CAD108B}.ReleaseNoFramework|Any CPU.ActiveCfg = Release|Any CPU
{7500F776-4384-4B5F-A8D8-22461CAD108B}.ReleaseNoFramework|Any CPU.Build.0 = Release|Any CPU
{7500F776-4384-4B5F-A8D8-22461CAD108B}.ReleaseNoWindows|Any CPU.ActiveCfg = Release|Any CPU
{7500F776-4384-4B5F-A8D8-22461CAD108B}.ReleaseNoWindows|Any CPU.Build.0 = Release|Any CPU
{AA80A190-52E2-4BE3-BFEB-1F148D9E9007}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AA80A190-52E2-4BE3-BFEB-1F148D9E9007}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AA80A190-52E2-4BE3-BFEB-1F148D9E9007}.DebugNoFramework|Any CPU.ActiveCfg = Debug|Any CPU
{AA80A190-52E2-4BE3-BFEB-1F148D9E9007}.DebugNoWindows|Any CPU.ActiveCfg = Debug|Any CPU
{AA80A190-52E2-4BE3-BFEB-1F148D9E9007}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AA80A190-52E2-4BE3-BFEB-1F148D9E9007}.Release|Any CPU.Build.0 = Release|Any CPU
{AA80A190-52E2-4BE3-BFEB-1F148D9E9007}.ReleaseNoFramework|Any CPU.ActiveCfg = Release|Any CPU
{AA80A190-52E2-4BE3-BFEB-1F148D9E9007}.ReleaseNoWindows|Any CPU.ActiveCfg = Release|Any CPU
{09056964-1C74-445A-96EC-33F6DFC07916}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{09056964-1C74-445A-96EC-33F6DFC07916}.Debug|Any CPU.Build.0 = Debug|Any CPU
{09056964-1C74-445A-96EC-33F6DFC07916}.DebugNoFramework|Any CPU.ActiveCfg = Debug|Any CPU
{09056964-1C74-445A-96EC-33F6DFC07916}.DebugNoFramework|Any CPU.Build.0 = Debug|Any CPU
{09056964-1C74-445A-96EC-33F6DFC07916}.DebugNoWindows|Any CPU.ActiveCfg = Debug|Any CPU
{09056964-1C74-445A-96EC-33F6DFC07916}.DebugNoWindows|Any CPU.Build.0 = Debug|Any CPU
{09056964-1C74-445A-96EC-33F6DFC07916}.Release|Any CPU.ActiveCfg = Release|Any CPU
{09056964-1C74-445A-96EC-33F6DFC07916}.Release|Any CPU.Build.0 = Release|Any CPU
{09056964-1C74-445A-96EC-33F6DFC07916}.ReleaseNoFramework|Any CPU.ActiveCfg = Release|Any CPU
{09056964-1C74-445A-96EC-33F6DFC07916}.ReleaseNoFramework|Any CPU.Build.0 = Release|Any CPU
{09056964-1C74-445A-96EC-33F6DFC07916}.ReleaseNoWindows|Any CPU.ActiveCfg = Release|Any CPU
{09056964-1C74-445A-96EC-33F6DFC07916}.ReleaseNoWindows|Any CPU.Build.0 = Release|Any CPU
{5CB51532-55F0-4255-B6E5-69ED5CCD14CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5CB51532-55F0-4255-B6E5-69ED5CCD14CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5CB51532-55F0-4255-B6E5-69ED5CCD14CD}.DebugNoFramework|Any CPU.ActiveCfg = Debug|Any CPU
{5CB51532-55F0-4255-B6E5-69ED5CCD14CD}.DebugNoFramework|Any CPU.Build.0 = Debug|Any CPU
{5CB51532-55F0-4255-B6E5-69ED5CCD14CD}.DebugNoWindows|Any CPU.ActiveCfg = Debug|Any CPU
{5CB51532-55F0-4255-B6E5-69ED5CCD14CD}.DebugNoWindows|Any CPU.Build.0 = Debug|Any CPU
{5CB51532-55F0-4255-B6E5-69ED5CCD14CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5CB51532-55F0-4255-B6E5-69ED5CCD14CD}.Release|Any CPU.Build.0 = Release|Any CPU
{5CB51532-55F0-4255-B6E5-69ED5CCD14CD}.ReleaseNoFramework|Any CPU.ActiveCfg = Release|Any CPU
{5CB51532-55F0-4255-B6E5-69ED5CCD14CD}.ReleaseNoFramework|Any CPU.Build.0 = Release|Any CPU
{5CB51532-55F0-4255-B6E5-69ED5CCD14CD}.ReleaseNoWindows|Any CPU.ActiveCfg = Release|Any CPU
{5CB51532-55F0-4255-B6E5-69ED5CCD14CD}.ReleaseNoWindows|Any CPU.Build.0 = Release|Any CPU
{5813CC33-B16C-485D-A74D-20204DDF6542}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5813CC33-B16C-485D-A74D-20204DDF6542}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5813CC33-B16C-485D-A74D-20204DDF6542}.DebugNoFramework|Any CPU.ActiveCfg = Debug|Any CPU
{5813CC33-B16C-485D-A74D-20204DDF6542}.DebugNoFramework|Any CPU.Build.0 = Debug|Any CPU
{5813CC33-B16C-485D-A74D-20204DDF6542}.DebugNoWindows|Any CPU.ActiveCfg = Debug|Any CPU
{5813CC33-B16C-485D-A74D-20204DDF6542}.DebugNoWindows|Any CPU.Build.0 = Debug|Any CPU
{5813CC33-B16C-485D-A74D-20204DDF6542}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5813CC33-B16C-485D-A74D-20204DDF6542}.Release|Any CPU.Build.0 = Release|Any CPU
{5813CC33-B16C-485D-A74D-20204DDF6542}.ReleaseNoFramework|Any CPU.ActiveCfg = Release|Any CPU
{5813CC33-B16C-485D-A74D-20204DDF6542}.ReleaseNoFramework|Any CPU.Build.0 = Release|Any CPU
{5813CC33-B16C-485D-A74D-20204DDF6542}.ReleaseNoWindows|Any CPU.ActiveCfg = Release|Any CPU
{5813CC33-B16C-485D-A74D-20204DDF6542}.ReleaseNoWindows|Any CPU.Build.0 = Release|Any CPU
{CE499888-B22B-457C-891E-0EA9DC317228}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CE499888-B22B-457C-891E-0EA9DC317228}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CE499888-B22B-457C-891E-0EA9DC317228}.DebugNoFramework|Any CPU.ActiveCfg = Debug|Any CPU
{CE499888-B22B-457C-891E-0EA9DC317228}.DebugNoFramework|Any CPU.Build.0 = Debug|Any CPU
{CE499888-B22B-457C-891E-0EA9DC317228}.DebugNoWindows|Any CPU.ActiveCfg = Debug|Any CPU
{CE499888-B22B-457C-891E-0EA9DC317228}.DebugNoWindows|Any CPU.Build.0 = Debug|Any CPU
{CE499888-B22B-457C-891E-0EA9DC317228}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CE499888-B22B-457C-891E-0EA9DC317228}.Release|Any CPU.Build.0 = Release|Any CPU
{CE499888-B22B-457C-891E-0EA9DC317228}.ReleaseNoFramework|Any CPU.ActiveCfg = Release|Any CPU
{CE499888-B22B-457C-891E-0EA9DC317228}.ReleaseNoFramework|Any CPU.Build.0 = Release|Any CPU
{CE499888-B22B-457C-891E-0EA9DC317228}.ReleaseNoWindows|Any CPU.ActiveCfg = Release|Any CPU
{CE499888-B22B-457C-891E-0EA9DC317228}.ReleaseNoWindows|Any CPU.Build.0 = Release|Any CPU
{07ED0FD5-E46B-4841-931D-BA2B673E16B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{07ED0FD5-E46B-4841-931D-BA2B673E16B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{07ED0FD5-E46B-4841-931D-BA2B673E16B2}.DebugNoFramework|Any CPU.ActiveCfg = Debug|Any CPU
{07ED0FD5-E46B-4841-931D-BA2B673E16B2}.DebugNoFramework|Any CPU.Build.0 = Debug|Any CPU
{07ED0FD5-E46B-4841-931D-BA2B673E16B2}.DebugNoWindows|Any CPU.ActiveCfg = Debug|Any CPU
{07ED0FD5-E46B-4841-931D-BA2B673E16B2}.DebugNoWindows|Any CPU.Build.0 = Debug|Any CPU
{07ED0FD5-E46B-4841-931D-BA2B673E16B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{07ED0FD5-E46B-4841-931D-BA2B673E16B2}.Release|Any CPU.Build.0 = Release|Any CPU
{07ED0FD5-E46B-4841-931D-BA2B673E16B2}.ReleaseNoFramework|Any CPU.ActiveCfg = Release|Any CPU
{07ED0FD5-E46B-4841-931D-BA2B673E16B2}.ReleaseNoFramework|Any CPU.Build.0 = Release|Any CPU
{07ED0FD5-E46B-4841-931D-BA2B673E16B2}.ReleaseNoWindows|Any CPU.ActiveCfg = Release|Any CPU
{07ED0FD5-E46B-4841-931D-BA2B673E16B2}.ReleaseNoWindows|Any CPU.Build.0 = Release|Any CPU
{CF3968A0-EA81-4464-B2D4-C7D40F6B5BCB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CF3968A0-EA81-4464-B2D4-C7D40F6B5BCB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CF3968A0-EA81-4464-B2D4-C7D40F6B5BCB}.DebugNoFramework|Any CPU.ActiveCfg = Debug|Any CPU
{CF3968A0-EA81-4464-B2D4-C7D40F6B5BCB}.DebugNoFramework|Any CPU.Build.0 = Debug|Any CPU
{CF3968A0-EA81-4464-B2D4-C7D40F6B5BCB}.DebugNoWindows|Any CPU.ActiveCfg = Debug|Any CPU
{CF3968A0-EA81-4464-B2D4-C7D40F6B5BCB}.DebugNoWindows|Any CPU.Build.0 = Debug|Any CPU
{CF3968A0-EA81-4464-B2D4-C7D40F6B5BCB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CF3968A0-EA81-4464-B2D4-C7D40F6B5BCB}.Release|Any CPU.Build.0 = Release|Any CPU
{CF3968A0-EA81-4464-B2D4-C7D40F6B5BCB}.ReleaseNoFramework|Any CPU.ActiveCfg = Release|Any CPU
{CF3968A0-EA81-4464-B2D4-C7D40F6B5BCB}.ReleaseNoFramework|Any CPU.Build.0 = Release|Any CPU
{CF3968A0-EA81-4464-B2D4-C7D40F6B5BCB}.ReleaseNoWindows|Any CPU.ActiveCfg = Release|Any CPU
{CF3968A0-EA81-4464-B2D4-C7D40F6B5BCB}.ReleaseNoWindows|Any CPU.Build.0 = Release|Any CPU
{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.DebugNoFramework|Any CPU.ActiveCfg = Debug|Any CPU
{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.DebugNoFramework|Any CPU.Build.0 = Debug|Any CPU
{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.DebugNoWindows|Any CPU.ActiveCfg = Debug|Any CPU
{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.DebugNoWindows|Any CPU.Build.0 = Debug|Any CPU
{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.Release|Any CPU.Build.0 = Release|Any CPU
{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.ReleaseNoFramework|Any CPU.ActiveCfg = Release|Any CPU
{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.ReleaseNoFramework|Any CPU.Build.0 = Release|Any CPU
{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.ReleaseNoWindows|Any CPU.ActiveCfg = Release|Any CPU
{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.ReleaseNoWindows|Any CPU.Build.0 = Release|Any CPU
{28669D98-E15D-4A62-B1D1-7C11D4CB1DE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{28669D98-E15D-4A62-B1D1-7C11D4CB1DE0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{28669D98-E15D-4A62-B1D1-7C11D4CB1DE0}.DebugNoWindows|Any CPU.ActiveCfg = Debug|Any CPU
{28669D98-E15D-4A62-B1D1-7C11D4CB1DE0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{28669D98-E15D-4A62-B1D1-7C11D4CB1DE0}.Release|Any CPU.Build.0 = Release|Any CPU
{28669D98-E15D-4A62-B1D1-7C11D4CB1DE0}.ReleaseNoWindows|Any CPU.ActiveCfg = Release|Any CPU
{82996E9D-5E63-4CC5-8179-612C71B4F56C}.Debug|Any CPU.ActiveCfg = Debug|x86
{82996E9D-5E63-4CC5-8179-612C71B4F56C}.Debug|Any CPU.Build.0 = Debug|x86
{82996E9D-5E63-4CC5-8179-612C71B4F56C}.DebugNoWindows|Any CPU.ActiveCfg = Debug|x86
{82996E9D-5E63-4CC5-8179-612C71B4F56C}.Release|Any CPU.ActiveCfg = Release|x86
{82996E9D-5E63-4CC5-8179-612C71B4F56C}.Release|Any CPU.Build.0 = Release|x86
{82996E9D-5E63-4CC5-8179-612C71B4F56C}.ReleaseNoWindows|Any CPU.ActiveCfg = Release|x86
{9E66C6F1-E235-4979-83B5-C2B3FDAD6E01}.Debug|Any CPU.ActiveCfg = Debug|x86
{9E66C6F1-E235-4979-83B5-C2B3FDAD6E01}.Debug|Any CPU.Build.0 = Debug|x86
{9E66C6F1-E235-4979-83B5-C2B3FDAD6E01}.DebugNoWindows|Any CPU.ActiveCfg = Debug|x86
{9E66C6F1-E235-4979-83B5-C2B3FDAD6E01}.Release|Any CPU.ActiveCfg = Release|x86
{9E66C6F1-E235-4979-83B5-C2B3FDAD6E01}.Release|Any CPU.Build.0 = Release|x86
{9E66C6F1-E235-4979-83B5-C2B3FDAD6E01}.ReleaseNoWindows|Any CPU.ActiveCfg = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -450,8 +460,9 @@ Global
{B4B5570C-8071-46DE-BB55-64C13480C606} = {08E7C650-A447-4DE2-974E-ED123B50F8D6}
{506B9092-AF88-4DA2-84FD-C11646B695B0} = {2648A85F-61AE-428E-95E1-66D06C7A3768}
{3F141E03-6ABB-46A8-AA24-1B4B6814E58F} = {506B9092-AF88-4DA2-84FD-C11646B695B0}
{F5B9D394-229B-44A1-AD12-D8C078F06814} = {506B9092-AF88-4DA2-84FD-C11646B695B0}
{5DDA72D5-DBFD-4FB2-9EAB-61D047145246} = {506B9092-AF88-4DA2-84FD-C11646B695B0}
{28669D98-E15D-4A62-B1D1-7C11D4CB1DE0} = {506B9092-AF88-4DA2-84FD-C11646B695B0}
{82996E9D-5E63-4CC5-8179-612C71B4F56C} = {506B9092-AF88-4DA2-84FD-C11646B695B0}
{9E66C6F1-E235-4979-83B5-C2B3FDAD6E01} = {506B9092-AF88-4DA2-84FD-C11646B695B0}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DFD36C95-3E49-41C7-ACDB-86BAF5B18A79}
+1 -1
View File
@@ -3,7 +3,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>$(TgsNetVersion)</TargetFramework>
<TargetFramework>$(TgsFrameworkVersion)</TargetFramework>
</PropertyGroup>
<ItemGroup>
+4 -4
View File
@@ -22,6 +22,7 @@ using Octokit;
using Tgstation.Server.Api;
using Tgstation.Server.Client;
using Tgstation.Server.Common.Http;
using Tgstation.Server.Host.Common;
using Tgstation.Server.Host.IO;
using Tgstation.Server.Host.Setup;
@@ -121,7 +122,7 @@ try
Console.WriteLine("Checking for TGS3 service...");
const string OldServiceName = "TG Station Server";
const string NewServiceName = "tgstation-server";
const string NewServiceName = Constants.CanonicalPackageName;
static ServiceController GetTgs3Service(bool checkNewOneIsntInstalled)
{
@@ -153,7 +154,7 @@ try
return tgs3Service;
}
var tgs3Service = GetTgs3Service(true);
using var tgs3Service = GetTgs3Service(true);
if (tgs3Service.Status != ServiceControllerStatus.Running)
{
@@ -439,7 +440,7 @@ try
installer.DisplayName = "/tg/station server";
installer.StartType = ServiceStartMode.Automatic;
installer.ServicesDependedOn = new string[] { "Tcpip", "Dhcp", "Dnscache" };
installer.ServiceName = "tgstation-server";
installer.ServiceName = NewServiceName;
installer.Parent = processInstaller;
var state = new ListDictionary();
@@ -527,7 +528,6 @@ try
managementObject.InvokeMethod("ChangeStartMode", new object[] { "Disabled" });
}
tgs3Service = GetTgs3Service(false);
if(tgs3Service.StartType != ServiceStartMode.Disabled)
Console.WriteLine("Failed to disable TGS3 service! This isn't critical, however.");
@@ -1,20 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../../build/Common.props" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>$(TgsNetVersion)</TargetFramework>
<TargetFramework>$(TgsFrameworkVersion)</TargetFramework>
<RuntimeIdentifier>win-x86</RuntimeIdentifier>
<Version>$(TgsMigratorVersion)</Version>
<Nullable>enable</Nullable>
<NoWarn>CA1416</NoWarn>
<ValidateExecutableReferencesMatchSelfContained>false</ValidateExecutableReferencesMatchSelfContained>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Core.System.ServiceProcess" Version="2.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Tgstation.Server.Client\Tgstation.Server.Client.csproj" />
<ProjectReference Include="..\..\src\Tgstation.Server.Host\Tgstation.Server.Host.csproj" />