mirror of
https://github.com/tribufu/ServerManagers
synced 2026-05-06 15:17:34 +00:00
source code checkin
This commit is contained in:
parent
5f8fb2c825
commit
7e57b72e35
675 changed files with 168433 additions and 0 deletions
53
src/ServerManager.Common/Lib/ActionQueue.cs
Normal file
53
src/ServerManager.Common/Lib/ActionQueue.cs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
using ServerManagerTool.Common.Interfaces;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks.Dataflow;
|
||||
|
||||
namespace ServerManagerTool.Common.Lib
|
||||
{
|
||||
/// <summary>
|
||||
/// This class ensures the following:
|
||||
/// 1. All work items run in the order posted.
|
||||
/// 2. Work items run on a background thread.
|
||||
/// 3. Work items do not overlap
|
||||
/// 4. If requested, the completion status of a work item is returned via a task.
|
||||
/// </summary>
|
||||
public class ActionQueue : IAsyncDisposable
|
||||
{
|
||||
public ActionBlock<Action> workQueue;
|
||||
|
||||
public ActionQueue(TaskScheduler scheduler = null)
|
||||
{
|
||||
this.workQueue = new ActionBlock<Action>(a => a.Invoke(), new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 1, TaskScheduler = scheduler ?? TaskScheduler.Default });
|
||||
|
||||
}
|
||||
|
||||
public Task<T> PostAction<T>(Func<T> action)
|
||||
{
|
||||
TaskCompletionSource<T> tcs = new TaskCompletionSource<T>();
|
||||
this.workQueue.Post(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = action.Invoke();
|
||||
Task.Run(() => tcs.TrySetResult(result));
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Task.Run(() => tcs.TrySetException(ex));
|
||||
}
|
||||
});
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
public Task PostAction(Action action)
|
||||
{
|
||||
return PostAction(() => { action.Invoke(); return true; });
|
||||
}
|
||||
|
||||
public async Task DisposeAsync()
|
||||
{
|
||||
await PostAction(() => this.workQueue.Complete());
|
||||
}
|
||||
}
|
||||
}
|
||||
21
src/ServerManager.Common/Lib/BindingProxy.cs
Normal file
21
src/ServerManager.Common/Lib/BindingProxy.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Common.Lib
|
||||
{
|
||||
public class BindingProxy : Freezable
|
||||
{
|
||||
public static readonly DependencyProperty DataProperty = DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
|
||||
public object Data
|
||||
{
|
||||
get { return (object)GetValue(DataProperty); }
|
||||
set { SetValue(DataProperty, value); }
|
||||
}
|
||||
|
||||
#region Overrides of Freezable
|
||||
protected override Freezable CreateInstanceCore()
|
||||
{
|
||||
return new BindingProxy();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
32
src/ServerManager.Common/Lib/BrowserBehavior.cs
Normal file
32
src/ServerManager.Common/Lib/BrowserBehavior.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace ServerManagerTool.Common.Lib
|
||||
{
|
||||
public static class BrowserBehavior
|
||||
{
|
||||
public static readonly DependencyProperty HtmlProperty = DependencyProperty.RegisterAttached("Html", typeof(string), typeof(BrowserBehavior), new FrameworkPropertyMetadata(OnHtmlChanged));
|
||||
|
||||
[AttachedPropertyBrowsableForType(typeof(WebBrowser))]
|
||||
public static string GetHtml(WebBrowser d)
|
||||
{
|
||||
return (string)d.GetValue(HtmlProperty);
|
||||
}
|
||||
|
||||
public static void SetHtml(WebBrowser d, string value)
|
||||
{
|
||||
d.SetValue(HtmlProperty, value);
|
||||
}
|
||||
|
||||
static void OnHtmlChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.NewValue == null)
|
||||
return;
|
||||
|
||||
if (d is WebBrowser wb)
|
||||
{
|
||||
wb.NavigateToString(e.NewValue as string);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
15
src/ServerManager.Common/Lib/CommandListener.cs
Normal file
15
src/ServerManager.Common/Lib/CommandListener.cs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
|
||||
namespace ServerManagerTool.Common.Lib
|
||||
{
|
||||
public class CommandListener : IDisposable
|
||||
{
|
||||
public Action<ConsoleCommand> Callback { get; set; }
|
||||
public Action<CommandListener> DisposeAction { get; set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DisposeAction(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
18
src/ServerManager.Common/Lib/ConsoleCommand.cs
Normal file
18
src/ServerManager.Common/Lib/ConsoleCommand.cs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
using ServerManagerTool.Common.Enums;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ServerManagerTool.Common.Lib
|
||||
{
|
||||
public class ConsoleCommand
|
||||
{
|
||||
public ConsoleStatus status;
|
||||
public string rawCommand;
|
||||
|
||||
public string command;
|
||||
public string args;
|
||||
|
||||
public bool suppressCommand;
|
||||
public bool suppressOutput;
|
||||
public IEnumerable<string> lines = new string[0];
|
||||
}
|
||||
}
|
||||
179
src/ServerManager.Common/Lib/ListViewSorting.cs
Normal file
179
src/ServerManager.Common/Lib/ListViewSorting.cs
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ServerManagerTool.Common.Lib
|
||||
{
|
||||
public static class SortBehavior
|
||||
{
|
||||
public static readonly DependencyProperty CanUserSortColumnsProperty = DependencyProperty.RegisterAttached("CanUserSortColumns", typeof(bool), typeof(SortBehavior), new FrameworkPropertyMetadata(OnCanUserSortColumnsChanged));
|
||||
public static readonly DependencyProperty CanUseSortProperty = DependencyProperty.RegisterAttached("CanUseSort", typeof(bool), typeof(SortBehavior), new FrameworkPropertyMetadata(true));
|
||||
public static readonly DependencyProperty SortDirectionProperty = DependencyProperty.RegisterAttached("SortDirection", typeof(ListSortDirection?), typeof(SortBehavior));
|
||||
public static readonly DependencyProperty SortExpressionProperty = DependencyProperty.RegisterAttached("SortExpression", typeof(string), typeof(SortBehavior));
|
||||
public static readonly DependencyProperty IsDefaultSortProperty = DependencyProperty.RegisterAttached("IsDefaultSort", typeof(bool), typeof(SortBehavior), new FrameworkPropertyMetadata(false));
|
||||
|
||||
[AttachedPropertyBrowsableForType(typeof(ListView))]
|
||||
public static bool GetCanUserSortColumns(ListView element)
|
||||
{
|
||||
return (bool)(element?.GetValue(CanUserSortColumnsProperty) ?? false);
|
||||
}
|
||||
|
||||
[AttachedPropertyBrowsableForType(typeof(ListView))]
|
||||
public static void SetCanUserSortColumns(ListView element, bool value)
|
||||
{
|
||||
element?.SetValue(CanUserSortColumnsProperty, value);
|
||||
}
|
||||
|
||||
[AttachedPropertyBrowsableForType(typeof(GridViewColumn))]
|
||||
public static bool GetCanUseSort(GridViewColumn element)
|
||||
{
|
||||
return (bool)(element?.GetValue(CanUseSortProperty) ?? false);
|
||||
}
|
||||
|
||||
[AttachedPropertyBrowsableForType(typeof(GridViewColumn))]
|
||||
public static void SetCanUseSort(GridViewColumn element, bool value)
|
||||
{
|
||||
element?.SetValue(CanUseSortProperty, value);
|
||||
}
|
||||
|
||||
[AttachedPropertyBrowsableForType(typeof(GridViewColumn))]
|
||||
public static ListSortDirection? GetSortDirection(GridViewColumn element)
|
||||
{
|
||||
return (ListSortDirection?)element.GetValue(SortDirectionProperty);
|
||||
}
|
||||
|
||||
[AttachedPropertyBrowsableForType(typeof(GridViewColumn))]
|
||||
public static void SetSortDirection(GridViewColumn element, ListSortDirection? value)
|
||||
{
|
||||
element?.SetValue(SortDirectionProperty, value);
|
||||
}
|
||||
|
||||
[AttachedPropertyBrowsableForType(typeof(GridViewColumn))]
|
||||
public static string GetSortExpression(GridViewColumn element)
|
||||
{
|
||||
return (string)element?.GetValue(SortExpressionProperty);
|
||||
}
|
||||
|
||||
[AttachedPropertyBrowsableForType(typeof(GridViewColumn))]
|
||||
public static void SetSortExpression(GridViewColumn element, string value)
|
||||
{
|
||||
element?.SetValue(SortExpressionProperty, value);
|
||||
}
|
||||
|
||||
[AttachedPropertyBrowsableForType(typeof(GridViewColumn))]
|
||||
public static bool GetIsDefaultSort(GridViewColumn element)
|
||||
{
|
||||
return (bool)(element?.GetValue(IsDefaultSortProperty) ?? false);
|
||||
}
|
||||
|
||||
[AttachedPropertyBrowsableForType(typeof(GridViewColumn))]
|
||||
public static void SetIsDefaultSort(GridViewColumn element, bool value)
|
||||
{
|
||||
element?.SetValue(IsDefaultSortProperty, value);
|
||||
}
|
||||
|
||||
private static void OnCanUserSortColumnsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var listView = (ListView)d;
|
||||
if ((bool)e.NewValue)
|
||||
{
|
||||
listView.AddHandler(GridViewColumnHeader.ClickEvent, (RoutedEventHandler)OnColumnHeaderClick);
|
||||
if (listView.IsLoaded)
|
||||
{
|
||||
DoInitialSort(listView);
|
||||
}
|
||||
else
|
||||
{
|
||||
listView.Loaded += OnLoaded;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
listView.RemoveHandler(GridViewColumnHeader.ClickEvent, (RoutedEventHandler)OnColumnHeaderClick);
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var listView = (ListView)e.Source;
|
||||
listView.Loaded -= OnLoaded;
|
||||
DoInitialSort(listView);
|
||||
}
|
||||
|
||||
private static void DoInitialSort(ListView listView)
|
||||
{
|
||||
var gridView = (GridView)listView.View;
|
||||
var column = gridView.Columns.FirstOrDefault(c => GetIsDefaultSort(c));
|
||||
if (column != null)
|
||||
{
|
||||
DoSort(listView, column);
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnColumnHeaderClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var columnHeader = e.OriginalSource as GridViewColumnHeader;
|
||||
if (columnHeader != null && GetCanUseSort(columnHeader.Column))
|
||||
{
|
||||
DoSort((ListView)e.Source, columnHeader.Column);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DoSort(ListView listView, GridViewColumn newColumn)
|
||||
{
|
||||
var gridView = (GridView)listView.View;
|
||||
|
||||
var sortDescriptions = listView.Items.SortDescriptions;
|
||||
var newDirection = ListSortDirection.Ascending;
|
||||
|
||||
var propertyPath = ResolveSortExpression(newColumn);
|
||||
if (propertyPath != null)
|
||||
{
|
||||
if (sortDescriptions.Count > 0)
|
||||
{
|
||||
if (sortDescriptions[0].PropertyName == propertyPath)
|
||||
{
|
||||
newDirection = GetSortDirection(newColumn) == ListSortDirection.Ascending ? ListSortDirection.Descending : ListSortDirection.Ascending;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var column in gridView.Columns.Where(c => GetSortDirection(c) != null))
|
||||
{
|
||||
SetSortDirection(column, null);
|
||||
}
|
||||
}
|
||||
|
||||
sortDescriptions.Clear();
|
||||
}
|
||||
|
||||
sortDescriptions.Add(new SortDescription(propertyPath, newDirection));
|
||||
SetSortDirection(newColumn, newDirection);
|
||||
|
||||
// check if there is a default sort column
|
||||
var defaultColumn = gridView.Columns.FirstOrDefault(c => GetIsDefaultSort(c));
|
||||
if (defaultColumn != null)
|
||||
{
|
||||
var defaultPropertyPath = ResolveSortExpression(defaultColumn);
|
||||
if (defaultPropertyPath != null && !defaultPropertyPath.Equals(propertyPath))
|
||||
{
|
||||
sortDescriptions.Add(new SortDescription(defaultPropertyPath, ListSortDirection.Ascending));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string ResolveSortExpression(GridViewColumn column)
|
||||
{
|
||||
var propertyPath = GetSortExpression(column);
|
||||
if (propertyPath == null)
|
||||
{
|
||||
var binding = column.DisplayMemberBinding as Binding;
|
||||
return binding != null ? binding.Path.Path : null;
|
||||
}
|
||||
|
||||
return propertyPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
31
src/ServerManager.Common/Lib/NetworkAdapterEntry.cs
Normal file
31
src/ServerManager.Common/Lib/NetworkAdapterEntry.cs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
using System.Net;
|
||||
|
||||
namespace ServerManagerTool.Common.Lib
|
||||
{
|
||||
public class NetworkAdapterEntry
|
||||
{
|
||||
public NetworkAdapterEntry(IPAddress address, string description)
|
||||
{
|
||||
this.IPAddress = address.ToString();
|
||||
this.Description = description;
|
||||
}
|
||||
|
||||
public NetworkAdapterEntry(string address, string description)
|
||||
{
|
||||
this.IPAddress = address;
|
||||
this.Description = description;
|
||||
}
|
||||
|
||||
public string IPAddress
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string Description
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
||||
136
src/ServerManager.Common/Lib/PropertyChangeNotifier.cs
Normal file
136
src/ServerManager.Common/Lib/PropertyChangeNotifier.cs
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ServerManagerTool.Common.Lib
|
||||
{
|
||||
public sealed class PropertyChangeNotifier : DependencyObject, IDisposable
|
||||
{
|
||||
#region Member Variables
|
||||
|
||||
private WeakReference _propertySource;
|
||||
|
||||
#endregion // Member Variables
|
||||
|
||||
#region Constructor
|
||||
|
||||
public PropertyChangeNotifier(DependencyObject propertySource, string path)
|
||||
: this(propertySource, new PropertyPath(path))
|
||||
{
|
||||
}
|
||||
|
||||
public PropertyChangeNotifier(DependencyObject propertySource, DependencyProperty property)
|
||||
: this(propertySource, new PropertyPath(property))
|
||||
{
|
||||
}
|
||||
public PropertyChangeNotifier(DependencyObject propertySource, DependencyProperty property, DependencyPropertyChangedEventHandler handler)
|
||||
: this(propertySource, property)
|
||||
{
|
||||
this.ValueChanged += handler;
|
||||
}
|
||||
|
||||
public PropertyChangeNotifier(DependencyObject propertySource, PropertyPath property)
|
||||
{
|
||||
if (null == propertySource)
|
||||
throw new ArgumentNullException("propertySource");
|
||||
if (null == property)
|
||||
throw new ArgumentNullException("property");
|
||||
this._propertySource = new WeakReference(propertySource);
|
||||
Binding binding = new Binding();
|
||||
binding.Path = property;
|
||||
binding.Mode = BindingMode.OneWay;
|
||||
binding.Source = propertySource;
|
||||
BindingOperations.SetBinding(this, ValueProperty, binding);
|
||||
}
|
||||
|
||||
public static IEnumerable<PropertyChangeNotifier> GetNotifiers(DependencyObject propertySource, IEnumerable<DependencyProperty> properties, DependencyPropertyChangedEventHandler handler)
|
||||
{
|
||||
foreach(var property in properties)
|
||||
{
|
||||
var notifier = new PropertyChangeNotifier(propertySource, property, handler);
|
||||
yield return notifier;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // Constructor
|
||||
|
||||
#region PropertySource
|
||||
|
||||
public DependencyObject PropertySource
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
// note, it is possible that accessing the target property
|
||||
// will result in an exception so i’ve wrapped this check
|
||||
// in a try catch
|
||||
return this._propertySource.IsAlive
|
||||
? this._propertySource.Target as DependencyObject
|
||||
: null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // PropertySource
|
||||
|
||||
#region Value
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the <see cref=”Value”/> dependency property
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(nameof(Value),
|
||||
typeof(object), typeof(PropertyChangeNotifier), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnPropertyChanged)));
|
||||
|
||||
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
PropertyChangeNotifier notifier = (PropertyChangeNotifier)d;
|
||||
if (null != notifier.ValueChanged)
|
||||
{
|
||||
notifier.ValueChanged(notifier.PropertySource, e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns/sets the value of the property
|
||||
/// </summary>
|
||||
/// <seealso cref=”ValueProperty”/>
|
||||
[Description("Returns/sets the value of the property")]
|
||||
[Category("Behavior")]
|
||||
[Bindable(true)]
|
||||
public object Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return (object)this.GetValue(PropertyChangeNotifier.ValueProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.SetValue(PropertyChangeNotifier.ValueProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion //Value
|
||||
|
||||
#region Events
|
||||
|
||||
public event DependencyPropertyChangedEventHandler ValueChanged;
|
||||
|
||||
#endregion // Events
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
BindingOperations.ClearBinding(this, ValueProperty);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
84
src/ServerManager.Common/Lib/RelayCommand.cs
Normal file
84
src/ServerManager.Common/Lib/RelayCommand.cs
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
using System;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace ServerManagerTool.Common.Lib
|
||||
{
|
||||
public class RelayCommand<T> : ICommand
|
||||
{
|
||||
#region Fields
|
||||
|
||||
readonly Action<T> _execute = null;
|
||||
readonly Predicate<T> _canExecute = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="DelegateCommand{T}"/>.
|
||||
/// </summary>
|
||||
/// <param name="execute">Delegate to execute when Execute is called on the command. This can be null to just hook up a CanExecute delegate.</param>
|
||||
/// <remarks><seealso cref="CanExecute"/> will always return true.</remarks>
|
||||
public RelayCommand(Action<T> execute)
|
||||
: this(execute, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new command.
|
||||
/// </summary>
|
||||
/// <param name="execute">The execution logic.</param>
|
||||
/// <param name="canExecute">The execution status logic.</param>
|
||||
public RelayCommand(Action<T> execute, Predicate<T> canExecute)
|
||||
{
|
||||
if (execute == null)
|
||||
throw new ArgumentNullException("execute");
|
||||
|
||||
_execute = execute;
|
||||
_canExecute = canExecute;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ICommand Members
|
||||
|
||||
///<summary>
|
||||
///Defines the method that determines whether the command can execute in its current state.
|
||||
///</summary>
|
||||
///<param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param>
|
||||
///<returns>
|
||||
///true if this command can be executed; otherwise, false.
|
||||
///</returns>
|
||||
public bool CanExecute(object parameter)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _canExecute == null ? true : _canExecute((T)parameter);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Occurs when changes occur that affect whether or not the command should execute.
|
||||
///</summary>
|
||||
public event EventHandler CanExecuteChanged
|
||||
{
|
||||
add { CommandManager.RequerySuggested += value; }
|
||||
remove { CommandManager.RequerySuggested -= value; }
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Defines the method to be called when the command is invoked.
|
||||
///</summary>
|
||||
///<param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to <see langword="null" />.</param>
|
||||
public void Execute(object parameter)
|
||||
{
|
||||
_execute((T)parameter);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
24
src/ServerManager.Common/Lib/ServerUpdater.cs
Normal file
24
src/ServerManager.Common/Lib/ServerUpdater.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
using ServerManagerTool.Common.Utils;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Security;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ServerManagerTool.Common.Lib
|
||||
{
|
||||
public static class ServerUpdater
|
||||
{
|
||||
public static Task<bool> UpgradeServerAsync(string steamCmdFile, string steamCmdArgs, string workingDirectory, string username, SecureString password, string serverInstallDirectory, DataReceivedEventHandler outputHandler, CancellationToken cancellationToken, ProcessWindowStyle windowStyle = ProcessWindowStyle.Normal)
|
||||
{
|
||||
Directory.CreateDirectory(serverInstallDirectory);
|
||||
|
||||
return ProcessUtils.RunProcessAsync(steamCmdFile, steamCmdArgs, string.Empty, workingDirectory, username, password, outputHandler, cancellationToken, windowStyle);
|
||||
}
|
||||
|
||||
public static Task<bool> UpgradeModsAsync(string steamCmdFile, string steamCmdArgs, string workingDirectory, string username, SecureString password, DataReceivedEventHandler outputHandler, CancellationToken cancellationToken, ProcessWindowStyle windowStyle = ProcessWindowStyle.Normal)
|
||||
{
|
||||
return ProcessUtils.RunProcessAsync(steamCmdFile, steamCmdArgs, string.Empty, workingDirectory, username, password, outputHandler, cancellationToken, windowStyle);
|
||||
}
|
||||
}
|
||||
}
|
||||
196
src/ServerManager.Common/Lib/SteamCmdUpdater.cs
Normal file
196
src/ServerManager.Common/Lib/SteamCmdUpdater.cs
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
using ServerManagerTool.Common.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ServerManagerTool.Common.Lib
|
||||
{
|
||||
public delegate void ProgressDelegate(int progress, string message, bool newLine = true);
|
||||
|
||||
public class SteamCmdUpdater
|
||||
{
|
||||
public const string OUTPUT_PREFIX = "[UPDATER]";
|
||||
|
||||
public struct Update
|
||||
{
|
||||
public Update(string statusKey, float completionPercent)
|
||||
{
|
||||
this.StatusKey = statusKey;
|
||||
this.CompletionPercent = completionPercent;
|
||||
this.Cancelled = false;
|
||||
this.FailureText = null;
|
||||
}
|
||||
|
||||
public Update SetFailed(string failureText)
|
||||
{
|
||||
this.FailureText = failureText;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static Update AsCompleted(string statusKey)
|
||||
{
|
||||
return new Update { StatusKey = statusKey, CompletionPercent = 100, Cancelled = false };
|
||||
}
|
||||
|
||||
public static Update AsCancelled(string statusKey)
|
||||
{
|
||||
return new Update { StatusKey = statusKey, CompletionPercent = 100, Cancelled = true };
|
||||
}
|
||||
|
||||
public string StatusKey;
|
||||
public float CompletionPercent;
|
||||
public bool Cancelled;
|
||||
public string FailureText;
|
||||
}
|
||||
|
||||
enum Status
|
||||
{
|
||||
CleaningSteamCmd,
|
||||
DownloadingSteamCmd,
|
||||
UnzippingSteamCmd,
|
||||
RunningSteamCmd,
|
||||
InstallSteamCmdComplete,
|
||||
Complete,
|
||||
Cancelled
|
||||
}
|
||||
|
||||
Dictionary<Status, Update> statuses = new Dictionary<Status, Update>()
|
||||
{
|
||||
{ Status.CleaningSteamCmd, new Update("AutoUpdater_Status_CleaningSteamCmd", 0) },
|
||||
{ Status.DownloadingSteamCmd, new Update("AutoUpdater_Status_DownloadingSteamCmd", 10) },
|
||||
{ Status.UnzippingSteamCmd, new Update("AutoUpdater_Status_UnzippingSteamCmd", 30) },
|
||||
{ Status.RunningSteamCmd, new Update("AutoUpdater_Status_RunningSteamCmd", 50) },
|
||||
{ Status.InstallSteamCmdComplete, new Update("AutoUpdater_Status_InstallSteamCmdComplete", 80) },
|
||||
{ Status.Complete, Update.AsCompleted("AutoUpdater_Status_Complete") },
|
||||
{ Status.Cancelled, Update.AsCancelled("AutoUpdater_Status_Cancelled") }
|
||||
};
|
||||
|
||||
public static string GetSteamCmdFile(string dataPath) => IOUtils.NormalizePath(Path.Combine(dataPath, CommonConfig.Default.SteamCmdRelativePath, CommonConfig.Default.SteamCmdExeFile));
|
||||
|
||||
public async Task ReinstallSteamCmdAsync(string dataPath, IProgress<Update> reporter, CancellationToken cancellationToken)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dataPath))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
reporter?.Report(statuses[Status.CleaningSteamCmd]);
|
||||
|
||||
string steamCmdDirectory = Path.Combine(dataPath, CommonConfig.Default.SteamCmdRelativePath);
|
||||
if (Directory.Exists(steamCmdDirectory))
|
||||
{
|
||||
Directory.Delete(steamCmdDirectory, true);
|
||||
}
|
||||
|
||||
await Task.Delay(5000);
|
||||
await InstallSteamCmdAsync(dataPath, reporter, cancellationToken);
|
||||
|
||||
reporter?.Report(statuses[Status.InstallSteamCmdComplete]);
|
||||
reporter?.Report(statuses[Status.Complete]);
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
reporter?.Report(statuses[Status.Cancelled]);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
reporter?.Report(statuses[Status.Complete].SetFailed(ex.ToString()));
|
||||
}
|
||||
}
|
||||
|
||||
private async Task InstallSteamCmdAsync(string dataPath, IProgress<Update> reporter, CancellationToken cancellationToken)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dataPath))
|
||||
return;
|
||||
|
||||
string steamCmdDirectory = Path.Combine(dataPath, CommonConfig.Default.SteamCmdRelativePath);
|
||||
if (!Directory.Exists(steamCmdDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(steamCmdDirectory);
|
||||
}
|
||||
|
||||
reporter?.Report(statuses[Status.DownloadingSteamCmd]);
|
||||
|
||||
// Get SteamCmd.exe if necessary
|
||||
string steamCmdPath = Path.Combine(steamCmdDirectory, CommonConfig.Default.SteamCmdExeFile);
|
||||
if (!File.Exists(steamCmdPath))
|
||||
{
|
||||
// download the SteamCMD zip file
|
||||
var steamZipPath = Path.Combine(steamCmdDirectory, CommonConfig.Default.SteamCmdZipFile);
|
||||
using (var webClient = new WebClient())
|
||||
{
|
||||
using (var cancelRegistration = cancellationToken.Register(webClient.CancelAsync))
|
||||
{
|
||||
await webClient.DownloadFileTaskAsync(CommonConfig.Default.SteamCmdUrl, steamZipPath);
|
||||
}
|
||||
}
|
||||
|
||||
// Unzip the downloaded file
|
||||
reporter?.Report(statuses[Status.UnzippingSteamCmd]);
|
||||
|
||||
ZipFile.ExtractToDirectory(steamZipPath, steamCmdDirectory);
|
||||
File.Delete(steamZipPath);
|
||||
|
||||
// Run the SteamCmd updater
|
||||
reporter?.Report(statuses[Status.RunningSteamCmd]);
|
||||
|
||||
var arguments = SteamUtils.BuildSteamCmdArguments(false, CommonConfig.Default.SteamCmdInstallArgs);
|
||||
ProcessStartInfo startInfo = new ProcessStartInfo()
|
||||
{
|
||||
FileName = steamCmdPath,
|
||||
Arguments = arguments,
|
||||
UseShellExecute = false,
|
||||
};
|
||||
|
||||
var process = Process.Start(startInfo);
|
||||
process.EnableRaisingEvents = true;
|
||||
|
||||
var ts = new TaskCompletionSource<bool>();
|
||||
using (var cancelRegistration = cancellationToken.Register(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
process.Kill();
|
||||
}
|
||||
finally
|
||||
{
|
||||
ts.TrySetCanceled();
|
||||
}
|
||||
}))
|
||||
{
|
||||
process.Exited += (s, e) =>
|
||||
{
|
||||
ts.TrySetResult(process.ExitCode == 0);
|
||||
};
|
||||
await ts.Task;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public async void UpdateSteamCmdAsync(string dataPath, IProgress<Update> reporter, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
await InstallSteamCmdAsync(dataPath, reporter, cancellationToken);
|
||||
|
||||
reporter?.Report(statuses[Status.InstallSteamCmdComplete]);
|
||||
reporter?.Report(statuses[Status.Complete]);
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
reporter?.Report(statuses[Status.Cancelled]);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
reporter?.Report(statuses[Status.Complete].SetFailed(ex.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ServerManagerTool.Common.Lib
|
||||
{
|
||||
public class UserScopedSettingContractResolver : DefaultContractResolver
|
||||
{
|
||||
public static readonly UserScopedSettingContractResolver Instance = new UserScopedSettingContractResolver();
|
||||
|
||||
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
|
||||
{
|
||||
JsonProperty property = base.CreateProperty(member, memberSerialization);
|
||||
|
||||
var customAttributes = member.CustomAttributes?.ToArray() ?? new CustomAttributeData[0];
|
||||
if (customAttributes.Any(a => a.AttributeType == typeof(System.Configuration.UserScopedSettingAttribute)))
|
||||
{
|
||||
property.ShouldSerialize = instance => { return property.PropertyType.IsValueType || property.PropertyType == typeof(string); };
|
||||
}
|
||||
else
|
||||
{
|
||||
property.ShouldSerialize = instance => { return false; };
|
||||
}
|
||||
|
||||
return property;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue