source code checkin

This commit is contained in:
Brett Hewitson 2021-01-07 16:23:23 +10:00
parent 5f8fb2c825
commit 7e57b72e35
675 changed files with 168433 additions and 0 deletions

View file

@ -0,0 +1,48 @@
using System;
using System.Reflection;
using System.Xml;
namespace ServerManagerTool.Common.Utils
{
public static class AppUtils
{
public static string GetDeployedVersion()
{
try
{
var assembly = Assembly.GetEntryAssembly();
return GetDeployedVersion(assembly);
}
catch
{
return "Unknown";
}
}
public static string GetDeployedVersion(Assembly assembly)
{
if (assembly == null)
return "Unknown";
try
{
string executePath = new Uri(assembly.GetName().CodeBase).LocalPath;
var xmlDoc = new XmlDocument();
xmlDoc.Load(executePath + ".manifest");
var ns = new XmlNamespaceManager(xmlDoc.NameTable);
ns.AddNamespace("asmv1", "urn:schemas-microsoft-com:asm.v1");
var xPath = "/asmv1:assembly/asmv1:assemblyIdentity/@version";
var node = xmlDoc.SelectSingleNode(xPath, ns);
return node.Value;
}
catch
{
return "Unknown";
}
}
}
}

View file

@ -0,0 +1,173 @@
using System;
using System.IO;
using System.Reflection;
namespace ServerManagerTool.Common.Utils
{
public static class AssemblyUtils
{
public static string GetAttributePropertyValue(Assembly assembly, Type attributeType, string propertyName)
{
var attributes = (Attribute[])assembly.GetCustomAttributes(attributeType, true);
if (attributes.Length > 0)
{
PropertyInfo property = attributeType.GetProperty(propertyName, typeof(string));
if (property != null)
{
//Get value on first attribute.
return (string)property.GetValue(attributes[0], null);
}
}
return "?";
}
public static string GetBuildDate()
{
return GetBuildDate(Assembly.GetEntryAssembly());
}
public static string GetBuildDate(Assembly assembly)
{
if (assembly != null && assembly.Location != null)
{
return File.GetLastWriteTime(assembly.Location).ToString();
}
return string.Empty;
}
public static string GetCompanyName()
{
return GetCompanyName(Assembly.GetEntryAssembly());
}
public static string GetCompanyName(Assembly assembly)
{
object[] attributes = assembly.GetCustomAttributes(typeof(AssemblyCompanyAttribute), false);
if (attributes.Length > 0)
{
var attribute = (AssemblyCompanyAttribute)attributes[0];
if (!string.IsNullOrWhiteSpace(attribute.Company))
{
return attribute.Company;
}
}
return string.Empty;
}
public static string GetCopyrightText()
{
return GetCopyrightText(Assembly.GetEntryAssembly());
}
public static string GetCopyrightText(Assembly assembly)
{
object[] attributes = assembly.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
if (attributes.Length > 0)
{
var attribute = (AssemblyCopyrightAttribute)attributes[0];
if (!string.IsNullOrWhiteSpace(attribute.Copyright))
{
return attribute.Copyright;
}
}
return string.Empty;
}
public static string GetDescription()
{
return GetDescription(Assembly.GetEntryAssembly());
}
public static string GetDescription(Assembly assembly)
{
object[] attributes = assembly.GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false);
if (attributes.Length > 0)
{
var attribute = (AssemblyDescriptionAttribute)attributes[0];
if (!string.IsNullOrWhiteSpace(attribute.Description))
{
return attribute.Description;
}
}
return string.Empty;
}
public static string GetFileVersion()
{
return GetFileVersion(Assembly.GetEntryAssembly());
}
public static string GetFileVersion(Assembly assembly)
{
object[] attributes = assembly.GetCustomAttributes(typeof(AssemblyFileVersionAttribute), false);
if (attributes.Length > 0)
{
var attribute = (AssemblyFileVersionAttribute)attributes[0];
if (!string.IsNullOrWhiteSpace(attribute.Version))
{
return attribute.Version;
}
}
return string.Empty;
}
public static string GetProductName()
{
return GetProductName(Assembly.GetEntryAssembly());
}
public static string GetProductName(Assembly assembly)
{
object[] attributes = assembly.GetCustomAttributes(typeof(AssemblyProductAttribute), false);
if (attributes.Length > 0)
{
var attribute = (AssemblyProductAttribute)attributes[0];
if (!string.IsNullOrWhiteSpace(attribute.Product))
{
return attribute.Product;
}
}
return string.Empty;
}
public static string GetTitle()
{
return GetTitle(Assembly.GetEntryAssembly());
}
public static string GetTitle(Assembly assembly)
{
object[] attributes = assembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
if (attributes.Length > 0)
{
var attribute = (AssemblyTitleAttribute)attributes[0];
if (!string.IsNullOrWhiteSpace(attribute.Title))
{
return attribute.Title;
}
}
// if there is no title attribute or if the title attribute was an empty string, then return the .exe name
return Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
}
public static string GetTrademark()
{
return GetTrademark(Assembly.GetEntryAssembly());
}
public static string GetTrademark(Assembly assembly)
{
object[] attributes = assembly.GetCustomAttributes(typeof(AssemblyTrademarkAttribute), false);
if (attributes.Length > 0)
{
var attribute = (AssemblyTrademarkAttribute)attributes[0];
if (!string.IsNullOrWhiteSpace(attribute.Trademark))
{
return attribute.Trademark;
}
}
return string.Empty;
}
public static string GetVersion()
{
return GetVersion(Assembly.GetEntryAssembly());
}
public static string GetVersion(Assembly assembly)
{
return assembly.GetName().Version.ToString();
}
}
}

View file

@ -0,0 +1,20 @@
using System;
namespace ServerManagerTool.Common.Utils
{
public static class DateTimeUtils
{
public static double DateTimeToUnixTimestamp(DateTime dateTime)
{
TimeSpan timespan = (dateTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc));
return timespan.TotalSeconds;
}
public static DateTime UnixTimeStampToDateTime(double unixTimeStamp)
{
// Unix timestamp is seconds past epoch
DateTime datetime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
return datetime.AddSeconds(unixTimeStamp).ToLocalTime();
}
}
}

View file

@ -0,0 +1,13 @@
using System.Diagnostics;
using System.Threading.Tasks;
namespace ServerManagerTool.Common.Utils
{
public static class DebugUtils
{
public static async Task WriteFormatThreadSafeAsync(string format, params object[] args)
{
await TaskUtils.RunOnUIThreadAsync(() => Debug.WriteLine(format, args));
}
}
}

View file

@ -0,0 +1,137 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Mail;
namespace ServerManagerTool.Common.Utils
{
public class EmailUtil
{
public EmailUtil()
{
Credentials = null;
DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure;
EnableSsl = false;
MailServer = string.Empty;
Port = 25;
Timeout = 100000;
UseDefaultCredentials = false;
}
public ICredentialsByHost Credentials
{
get;
set;
}
public DeliveryNotificationOptions DeliveryNotificationOptions
{
get;
set;
}
public bool EnableSsl
{
get;
set;
}
public string MailServer
{
get;
set;
}
public int Port
{
get;
set;
}
public int Timeout
{
get;
set;
}
public bool UseDefaultCredentials
{
get;
set;
}
public void SendEmail(string fromAddress, string toAddress, string subject, string body, bool isBodyHtml)
{
SendEmailImplementation(fromAddress, new[] { toAddress }, subject, body, isBodyHtml, null);
}
public void SendEmail(string fromAddress, string toAddress, string subject, string body, bool isBodyHtml, Attachment[] mailAttachments)
{
SendEmailImplementation(fromAddress, new[] { toAddress }, subject, body, isBodyHtml, mailAttachments);
}
public void SendEmail(string fromAddress, string[] toAddresses, string subject, string body, bool isBodyHtml)
{
SendEmailImplementation(fromAddress, toAddresses, subject, body, isBodyHtml, null);
}
public void SendEmail(string fromAddress, string[] toAddresses, string subject, string body, bool isBodyHtml, Attachment[] mailAttachments)
{
SendEmailImplementation(fromAddress, toAddresses, subject, body, isBodyHtml, mailAttachments);
}
private void SendEmailImplementation(string fromAddress, IEnumerable<string> toAddresses, string subject, string body, bool isBodyHtml, IEnumerable<Attachment> mailAttachments)
{
// Format mail message
using (var mailMessage = new MailMessage())
{
mailMessage.From = new MailAddress(fromAddress);
mailMessage.Subject = subject;
mailMessage.Body = body;
mailMessage.IsBodyHtml = isBodyHtml;
mailMessage.DeliveryNotificationOptions = DeliveryNotificationOptions;
if (mailAttachments != null)
{
foreach (var mailAttachment in mailAttachments)
{
if (mailAttachment == null)
continue;
mailMessage.Attachments.Add(mailAttachment);
}
}
mailMessage.To.Clear();
foreach (var toAddress in toAddresses)
{
mailMessage.To.Add(new MailAddress(toAddress));
}
if (mailMessage.To.Count > 0)
{
using (var smptClient = new SmtpClient())
{
smptClient.Host = MailServer;
smptClient.Port = Port;
smptClient.DeliveryMethod = SmtpDeliveryMethod.Network;
smptClient.EnableSsl = EnableSsl;
smptClient.Timeout = Timeout;
smptClient.UseDefaultCredentials = UseDefaultCredentials;
smptClient.Credentials = Credentials;
try
{
smptClient.Send(mailMessage);
}
catch (Exception ex)
{
throw new Exception("An error occurred trying to send an email.", ex);
}
}
}
}
}
}
}

View file

@ -0,0 +1,107 @@
using System;
using System.Collections.Generic;
using System.Linq;
using WindowsFirewallHelper;
using WindowsFirewallHelper.FirewallAPIv2.Rules;
/*
WindowsFirewallHelper
A class library to manage the Windows Firewall as well as adding your program to the Windows Firewall Exception list
=========================================================================
USAGE
Get an instance of the active firewall using FirewallManager class and
use the properties to get the list of firewall rules and profiles.
You can also use the methods on this class to add a new rule to the
firewall.
CODE SAMPLE FOR ADDING AN APPLICATION RULE TO THE ACTIVE PROFILE:
var rule = FirewallManager.Instance.CreateApplicationRule(FirewallManager.Instance.GetProfile().Type, @"MyApp Rule", FirewallAction.Allow, @"C:\MyApp.exe");
rule.Direction = FirewallDirection.Outbound;
FirewallManager.Instance.Rules.Add(rule);
CODE SAMPLE FOR ADDING A PORT RULE TO THE ACTIVE PROFILE:
var rule = FirewallManager.Instance.CreatePortRule(FirewallManager.Instance.GetProfile().Type, @"Port 80 - Any Protocol", FirewallAction.Allow, 80, FirewallProtocol.Any);
FirewallManager.Instance.Rules.Add(rule);
CODE SAMPLE TO GET A LIST OF ALL REGISTERED RULES:
var allRules = FirewallManager.Instance.Rules.ToArray();
MORE SAMPLES:
Check the Project's Github page at: https://github.com/falahati/WindowsFirewallHelper
*/
namespace ServerManagerTool.Common.Utils
{
/// <summary>
/// Code for dealing with firewalls
/// </summary>
public static class FirewallUtils
{
public static bool CreateFirewallRules(string exeName, List<int> ports, string ruleName, string description = "")
{
var firewallManager = FirewallManager.Instance;
if (firewallManager.IsSupported)
{
DeleteFirewallRules(exeName);
// create the TCP rule
var rule = firewallManager.CreateApplicationRule(FirewallProfiles.Domain | FirewallProfiles.Private | FirewallProfiles.Public, $"{ruleName} TCP", FirewallAction.Allow, exeName, FirewallProtocol.TCP);
if (rule != null)
{
rule.Direction = FirewallDirection.Inbound;
rule.IsEnable = true;
rule.LocalPorts = ports.Select(p => (ushort)p).ToArray();
if (rule is StandardRule)
{
((StandardRule)rule).Description = description;
}
firewallManager.Rules.Add(rule);
}
// create the UDP rule
rule = firewallManager.CreateApplicationRule(FirewallProfiles.Domain | FirewallProfiles.Private | FirewallProfiles.Public, $"{ruleName} UDP", FirewallAction.Allow, exeName, FirewallProtocol.UDP);
if (rule != null)
{
rule.Direction = FirewallDirection.Inbound;
rule.IsEnable = true;
rule.LocalPorts = ports.Select(p => (ushort)p).ToArray();
if (rule is StandardRule)
{
((StandardRule)rule).Description = description;
}
firewallManager.Rules.Add(rule);
}
return true;
}
return false;
}
public static bool DeleteFirewallRules(string exeName)
{
var firewallManager = FirewallManager.Instance;
if (firewallManager.IsSupported)
{
// check for existing rules
var rulesToDelete = firewallManager.Rules.Cast<StandardRule>().Where(r => !string.IsNullOrWhiteSpace(r.ApplicationName) && r.ApplicationName.Equals(exeName, StringComparison.OrdinalIgnoreCase)).ToList();
if (rulesToDelete != null && rulesToDelete.Count > 0)
{
// delete the existing rules
rulesToDelete.ForEach(r => firewallManager.Rules.Remove(r));
}
return true;
}
return false;
}
}
}

View file

@ -0,0 +1,20 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace ServerManagerTool.Common.Utils
{
public static class IOUtils
{
[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DeleteFile(string name);
public static bool Unblock(string fileName)
{
return DeleteFile(fileName + ":Zone.Identifier");
}
public static string NormalizePath(string path) => Path.GetFullPath(new Uri(path).LocalPath).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar).ToLowerInvariant();
}
}

View file

@ -0,0 +1,172 @@
using ServerManagerTool.Common.Serialization;
using System;
using System.IO;
using System.Text.RegularExpressions;
namespace ServerManagerTool.Common.Utils
{
public static class IniFileUtils
{
/// <summary>
/// Retrieves all the keys and values for the specified section of an initialization file.
/// </summary>
/// <param name="file">The name of the initialization file.</param>
/// <param name="sectionName">The name of the section in the initialization file.</param>
/// <returns>A string array containing the key name and value pairs associated with the named section.</returns>
public static string[] ReadSection(string file, string sectionName)
{
if (sectionName == null)
return new string[0];
var iniFile = ReadFromFile(file);
return iniFile?.GetSection(sectionName)?.KeysToStringArray() ?? new string[0];
}
/// <summary>
/// Retrieves a string from the specified section in an initialization file.
/// </summary>
/// <param name="file">The name of the initialization file.</param>
/// <param name="sectionName">The name of the section containing the key name.</param>
/// <param name="keyName">The name of the key whose associated string is to be retrieved.</param>
/// <param name="defaultValue">A default string. If the keyName key cannot be found in the initialization file, the default string is returned. If this parameter is NULL, the default is an empty string, "".</param>
/// <returns></returns>
public static string ReadValue(string file, string sectionName, string keyName, string defaultValue)
{
if (sectionName == null || keyName == null)
return defaultValue ?? string.Empty;
var iniFile = ReadFromFile(file);
return iniFile?.GetSection(sectionName)?.GetKey(keyName)?.KeyValue ?? defaultValue ?? string.Empty;
}
/// <summary>
/// Replaces the keys and values for the specified section in an initialization file.
/// </summary>
/// <param name="file">The name of the initialization file.</param>
/// <param name="sectionName">The name of the section in which data is written.</param>
/// <param name="keysValuePairs">An array of key names and associated values that are to be written to the named section.</param>
/// <returns>True if the function succeeds; otherwise False.</returns>
public static bool WriteSection(string file, string sectionName, string[] keysValuePairs)
{
if (sectionName == null)
return false;
var iniFile = ReadFromFile(file) ?? new IniFile();
var result = iniFile.WriteSection(sectionName, keysValuePairs);
if (!result)
return false;
return result = SaveToFile(file, iniFile);
}
/// <summary>
/// Copies a string into the specified section of an initialization file.
/// </summary>
/// <param name="file">The name of the initialization file.</param>
/// <param name="sectionName">The name of the section to which the string will be copied. If the section does not exist, it is created. The name of the section is case-independent; the string can be any combination of uppercase and lowercase letters.</param>
/// <param name="keyName">The name of the key to be associated with a string. If the key does not exist in the specified section, it is created. If this parameter is NULL, the entire section, including all entries within the section, is deleted.</param>
/// <param name="keyValue">A null-terminated string to be written to the file. If this parameter is NULL, the key pointed to by the keyName parameter is deleted.</param>
/// <returns>True if the function succeeds; otherwise False.</returns>
public static bool WriteValue(string file, string sectionName, string keyName, string keyValue)
{
if (sectionName == null)
return false;
var iniFile = ReadFromFile(file) ?? new IniFile();
var result = iniFile.WriteKey(sectionName, keyName, keyValue);
if (!result)
return false;
return result = SaveToFile(file, iniFile);
}
public static IniFile ReadFromFile(string file)
{
if (string.IsNullOrWhiteSpace(file))
return null;
if (!File.Exists(file))
return new IniFile();
var iniFile = new IniFile();
using (StreamReader reader = new StreamReader(file))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
if (string.IsNullOrWhiteSpace(line) || line.StartsWith(";") || line.StartsWith("#"))
continue;
var sectionName = Regex.Match(line, @"(?<=^\[).*(?=\]$)").Value.Trim();
var section = iniFile.AddSection(sectionName);
if (section != null)
continue;
iniFile.AddKey(line);
}
reader.Close();
}
return iniFile;
}
public static IniFile ReadString(string text)
{
if (string.IsNullOrWhiteSpace(text))
return new IniFile();
var iniFile = new IniFile();
var lines = text.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
for (int index = 0; index < lines.Length; index++)
{
var line = lines[index].Trim();
if (string.IsNullOrWhiteSpace(line) || line.StartsWith(";") || line.StartsWith("#"))
continue;
var sectionName = Regex.Match(line, @"(?<=^\[).*(?=\]$)").Value.Trim();
var section = iniFile.AddSection(sectionName);
if (section != null)
continue;
iniFile.AddKey(line);
}
return iniFile;
}
public static bool SaveToFile(string file, IniFile iniFile)
{
if (string.IsNullOrWhiteSpace(file) || iniFile == null)
return false;
using (StreamWriter writer = new StreamWriter(file, false))
{
foreach (var section in iniFile.Sections)
{
writer.WriteLine($"[{section.SectionName}]");
foreach (var keyString in section.KeysToStringArray())
{
writer.WriteLine(keyString);
}
writer.WriteLine();
}
writer.Close();
}
return true;
}
}
}

View file

@ -0,0 +1,138 @@
using Newtonsoft.Json;
namespace ServerManagerTool.Common.Utils
{
public static class JsonUtils
{
public static string Serialize<T>(T value, JsonSerializerSettings settings = null)
{
if (value == null)
return string.Empty;
try
{
if (settings != null)
return JsonConvert.SerializeObject(value, Formatting.Indented, settings);
return JsonConvert.SerializeObject(value, Formatting.Indented);
}
catch
{
return string.Empty;
}
}
public static bool SerializeToFile<T>(T value, string filename, JsonSerializerSettings settings = null)
{
if (value == null)
return false;
try
{
var jsonString = Serialize(value, settings);
System.IO.File.WriteAllText(filename, jsonString);
return true;
}
catch
{
return false;
}
}
public static T Deserialize<T>(string jsonString, JsonSerializerSettings settings = null)
{
if (string.IsNullOrEmpty(jsonString))
return default(T);
try
{
if (settings != null)
return JsonConvert.DeserializeObject<T>(jsonString, settings);
return JsonConvert.DeserializeObject<T>(jsonString);
}
catch
{
return default(T);
}
}
public static T DeserializeAnonymousType<T>(string jsonString, T anonTypeObject, JsonSerializerSettings settings = null)
{
if (string.IsNullOrEmpty(jsonString))
return anonTypeObject;
try
{
if (settings != null)
return JsonConvert.DeserializeAnonymousType<T>(jsonString, anonTypeObject, settings);
return JsonConvert.DeserializeAnonymousType<T>(jsonString, anonTypeObject);
}
catch
{
return anonTypeObject;
}
}
public static T DeserializeFromFile<T>(string file, JsonSerializerSettings settings = null)
{
if (string.IsNullOrEmpty(file) || !System.IO.File.Exists(file))
return default(T);
try
{
return Deserialize<T>(System.IO.File.ReadAllText(file), settings);
}
catch
{
return default(T);
}
}
public static T DeserializeFromFile<T>(string file, T anonTypeObject, JsonSerializerSettings settings = null)
{
if (string.IsNullOrEmpty(file) || !System.IO.File.Exists(file))
return anonTypeObject;
try
{
return DeserializeAnonymousType<T>(System.IO.File.ReadAllText(file), anonTypeObject, settings);
}
catch
{
return anonTypeObject;
}
}
public static void Populate(string jsonString, object target, JsonSerializerSettings settings = null)
{
if (string.IsNullOrEmpty(jsonString) || target == null)
return;
try
{
if (settings != null)
JsonConvert.PopulateObject(jsonString, target, settings);
else
JsonConvert.PopulateObject(jsonString, target);
}
catch
{
return;
}
}
public static void PopulateFromFile(string file, object target, JsonSerializerSettings settings = null)
{
if (string.IsNullOrEmpty(file) || !System.IO.File.Exists(file) || target == null)
return;
try
{
Populate(System.IO.File.ReadAllText(file), target, settings);
}
catch
{
return;
}
}
}
}

View file

@ -0,0 +1,60 @@
using NLog;
using System;
using System.DirectoryServices.ActiveDirectory;
using System.Linq;
using System.Management;
using System.Runtime.InteropServices;
namespace ServerManagerTool.Common.Utils
{
public static class MachineUtils
{
private const int OS_ANYSERVER = 29;
[DllImport("shlwapi.dll", SetLastError = true, EntryPoint = "#437")]
private static extern bool IsOS(int os);
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
public static bool IsWindowsServer()
{
return IsOS(OS_ANYSERVER);
}
public static bool IsThisMachineADomainController()
{
try
{
Domain domain = Domain.GetCurrentDomain();
if (domain == null)
return false;
string thisMachine = $"{Environment.MachineName}.{domain}".ToLower();
var domainControllers = domain.DomainControllers.OfType<DomainController>();
return domainControllers.Any(dc => dc.Name.Equals(thisMachine, StringComparison.OrdinalIgnoreCase));
}
catch (ActiveDirectoryObjectNotFoundException ex)
{
_logger.Debug($"{nameof(IsThisMachineADomainController)} checked. {ex.Message}");
return false;
}
catch (ActiveDirectoryOperationException ex)
{
_logger.Debug($"{nameof(IsThisMachineADomainController)} checked. {ex.Message}");
return false;
}
catch (Exception ex)
{
_logger.Error($"{nameof(IsThisMachineADomainController)}. {ex.Message}\r\n{ex.StackTrace}");
return false;
}
}
public static bool IsThisMachinePartOfADomain()
{
ManagementObject manObject = new ManagementObject(string.Format("Win32_ComputerSystem.Name='{0}'", Environment.MachineName));
return (bool)manObject["PartOfDomain"];
}
}
}

View file

@ -0,0 +1,174 @@
using Newtonsoft.Json.Linq;
using NLog;
using ServerManagerTool.Common.Lib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Threading.Tasks;
namespace ServerManagerTool.Common.Utils
{
public static class NetworkUtils
{
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
public static List<NetworkAdapterEntry> GetAvailableIPV4NetworkAdapters()
{
List<NetworkAdapterEntry> adapters = new List<NetworkAdapterEntry>();
var interfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach(var ifc in interfaces)
{
var ipProperties = ifc.GetIPProperties();
if (ipProperties != null)
{
adapters.AddRange(ipProperties.UnicastAddresses.Select(a => a.Address)
.Where(a => a.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork && !IPAddress.IsLoopback(a))
.Select(a => new NetworkAdapterEntry(a, ifc.Description)));
}
}
return adapters;
}
public static async Task<Version> GetLatestServerManagerVersion(string url)
{
using (var webClient = new WebClient())
{
try
{
string latestVersion = await webClient.DownloadStringTaskAsync(url);
return Version.Parse(latestVersion);
}
catch (Exception ex)
{
_logger.Error($"{nameof(GetLatestServerManagerVersion)} - Exception checking for Server Manager version. {ex.Message}");
return new Version();
}
}
}
public static NetworkAdapterEntry GetPreferredIP(IEnumerable<NetworkAdapterEntry> adapters)
{
//
// Try for a 192.168. address first
//
var preferredIp = adapters.FirstOrDefault(a => a.IPAddress.StartsWith("192.168."));
if (preferredIp == null)
{
//
// Try a 10.0 address next
//
preferredIp = adapters.FirstOrDefault(a => a.IPAddress.StartsWith("10.0."));
if (preferredIp == null)
{
//
// Sad. Just take the first.
//
preferredIp = adapters.FirstOrDefault();
}
}
return preferredIp;
}
public static string DiscoverPublicIP()
{
using (var webClient = new WebClient())
{
try
{
var publicIP = webClient.DownloadString(CommonConfig.Default.PublicIPCheckUrl);
if (IPAddress.TryParse(publicIP, out IPAddress address))
{
return publicIP;
}
}
catch (Exception ex)
{
_logger.Error($"{nameof(DiscoverPublicIP)} - Exception checking for public ip. {ex.Message}");
}
return String.Empty;
}
}
public static async Task<string> DiscoverPublicIPAsync()
{
using (var webClient = new WebClient())
{
try
{
var publicIP = await webClient.DownloadStringTaskAsync(CommonConfig.Default.PublicIPCheckUrl);
if (IPAddress.TryParse(publicIP, out IPAddress address))
{
return publicIP;
}
}
catch (Exception ex)
{
_logger.Error($"{nameof(DiscoverPublicIPAsync)} - Exception checking for public ip. {ex.Message}");
}
return String.Empty;
}
}
public static async Task<bool> CheckServerStatusViaAPI(Uri uri, IPEndPoint endpoint)
{
try
{
string jsonString;
using (var client = new WebClient())
{
jsonString = await client.DownloadStringTaskAsync(uri);
}
if (jsonString == null)
{
_logger.Debug($"Server info request returned null string for {endpoint.Address}:{endpoint.Port}");
return false;
}
JObject query = JObject.Parse(jsonString);
if (query == null)
{
_logger.Debug($"Server info request failed to parse for {endpoint.Address}:{endpoint.Port} - '{jsonString}'");
return false;
}
var available = query.SelectToken("available");
if (available == null)
{
_logger.Debug($"Server at {endpoint.Address}:{endpoint.Port} returned no availability.");
return false;
}
return (bool)available;
}
catch (Exception ex)
{
_logger.Debug($"{nameof(CheckServerStatusViaAPI)} - Failed checking status via API for: {endpoint.Address}:{endpoint.Port}. {ex.Message}");
return false;
}
}
public static async Task PerformServerCallToAPI(Uri uri, IPEndPoint endpoint)
{
try
{
using (var client = new WebClient())
{
await client.DownloadStringTaskAsync(uri);
}
}
catch (Exception ex)
{
_logger.Debug($"{nameof(PerformServerCallToAPI)} - Failed calling API for: {endpoint.Address}:{endpoint.Port}. {ex.Message}");
}
}
}
}

View file

@ -0,0 +1,330 @@
using NLog;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management;
using System.Numerics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security;
using System.Threading;
using System.Threading.Tasks;
namespace ServerManagerTool.Common.Utils
{
public static class ProcessUtils
{
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
// Delegate type to be used as the Handler Routine for SCCH
delegate bool ConsoleCtrlDelegate(CtrlTypes CtrlType);
// Enumerated type for the control messages sent to the handler routine
enum CtrlTypes : uint
{
CTRL_C_EVENT = 0,
CTRL_BREAK_EVENT,
CTRL_CLOSE_EVENT,
CTRL_LOGOFF_EVENT = 5,
CTRL_SHUTDOWN_EVENT
}
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool AttachConsole(uint dwProcessId);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
private static extern bool FreeConsole();
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GenerateConsoleCtrlEvent(CtrlTypes dwCtrlEvent, uint dwProcessGroupId);
[DllImport("kernel32.dll")]
static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate HandlerRoutine, bool Add);
[DllImport("user32.dll")]
private static extern int ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
private static extern int SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern int IsIconic(IntPtr hWnd);
public static string FIELD_COMMANDLINE = "CommandLine";
public static string FIELD_EXECUTABLEPATH = "ExecutablePath";
public static string FIELD_PROCESSID = "ProcessId";
private const int SW_RESTORE = 9;
private static Mutex _mutex;
public static string GetCommandLineForProcess(int processId)
{
var wmiQueryString = $"SELECT {FIELD_COMMANDLINE} FROM Win32_Process WHERE {FIELD_PROCESSID} = {processId}";
using (var searcher = new ManagementObjectSearcher(wmiQueryString))
{
using (var results = searcher.Get())
{
ManagementObject mo = results.Cast<ManagementObject>().FirstOrDefault();
if (mo != null)
return (string)mo[FIELD_COMMANDLINE];
}
}
return null;
}
public static string GetMainModuleFilepath(int processId)
{
var wmiQueryString = $"SELECT {FIELD_EXECUTABLEPATH} FROM Win32_Process WHERE {FIELD_PROCESSID} = {processId}";
using (var searcher = new ManagementObjectSearcher(wmiQueryString))
{
using (var results = searcher.Get())
{
ManagementObject mo = results.Cast<ManagementObject>().FirstOrDefault();
if (mo != null)
return (string)mo[FIELD_EXECUTABLEPATH];
}
}
return null;
}
public static async Task SendStopAsync(Process process)
{
if (process == null)
return;
var ts = new TaskCompletionSource<bool>();
EventHandler handler = (s, e) => ts.TrySetResult(true);
try
{
process.Exited += handler;
//This does not require the console window to be visible.
var result = AttachConsole((uint)process.Id);
if (result)
{
// Disable Ctrl-C handling for our program
result = SetConsoleCtrlHandler(null, true);
if (result)
{
result = GenerateConsoleCtrlEvent(CtrlTypes.CTRL_C_EVENT, 0);
if (result)
{
FreeConsole();
// Must wait here. If we don't and re-enable Ctrl-C
// handling below too fast, we might terminate ourselves.
try
{
ts.Task.Wait(10000);
result = true;
}
catch (Exception)
{
result = false;
}
//Re-enable Ctrl-C handling or any subsequently started
//programs will inherit the disabled state.
SetConsoleCtrlHandler(null, false);
}
else
{
//Re-enable Ctrl-C handling or any subsequently started
//programs will inherit the disabled state.
SetConsoleCtrlHandler(null, false);
FreeConsole();
}
}
else
{
FreeConsole();
}
}
if (!result && !process.HasExited)
{
process.Kill();
}
}
finally
{
process.Exited -= handler;
}
}
public static Task<bool> RunProcessAsync(string file, string arguments, string verb, string workingDirectory, string username, SecureString password, DataReceivedEventHandler outputHandler, CancellationToken cancellationToken, ProcessWindowStyle windowStyle = ProcessWindowStyle.Normal)
{
try
{
if (string.IsNullOrWhiteSpace(file) || !File.Exists(file))
throw new FileNotFoundException("The specified file does not exist or could not be found.", file);
var fileName = Path.GetFileName(file);
var startInfo = new ProcessStartInfo()
{
FileName = file,
Arguments = arguments,
Verb = verb,
UseShellExecute = outputHandler == null && windowStyle == ProcessWindowStyle.Minimized && string.IsNullOrWhiteSpace(username),
RedirectStandardOutput = outputHandler != null,
CreateNoWindow = outputHandler != null || windowStyle == ProcessWindowStyle.Hidden,
WindowStyle = windowStyle,
UserName = string.IsNullOrWhiteSpace(username) ? null : username,
Password = string.IsNullOrWhiteSpace(username) ? null : password,
WorkingDirectory = string.IsNullOrWhiteSpace(workingDirectory) || !Directory.Exists(workingDirectory) ? Path.GetDirectoryName(file) : workingDirectory,
};
var process = Process.Start(startInfo);
process.EnableRaisingEvents = true;
if (startInfo.RedirectStandardOutput && outputHandler != null)
{
process.OutputDataReceived += outputHandler;
process.BeginOutputReadLine();
}
var tcs = new TaskCompletionSource<bool>();
using (var cancelRegistration = cancellationToken.Register(() =>
{
try
{
process.Kill();
}
finally
{
tcs.TrySetCanceled();
}
}))
{
process.Exited += (s, e) =>
{
var exitCode = process.ExitCode;
_logger.Debug($"{nameof(RunProcessAsync)}: filename {fileName}; exitcode = {exitCode}");
tcs.TrySetResult(exitCode == 0);
process.Close();
};
return tcs.Task;
}
}
catch (Exception ex)
{
_logger.Error($"{nameof(RunProcessAsync)}. {ex.Message}\r\n{ex.StackTrace}");
throw;
}
}
private static IntPtr GetCurrentInstanceWindowHandle()
{
var hWnd = IntPtr.Zero;
var currentProcess = Process.GetCurrentProcess();
var processes = Process.GetProcessesByName(currentProcess.ProcessName);
foreach (var process in processes)
{
// Get the first instance that is not this instance, has the same process name and was started from the same file name
// and location. Also check that the process has a valid window handle in this session to filter out other user's processes.
if (process.Id != currentProcess.Id && process.MainModule.FileName == currentProcess.MainModule.FileName && process.MainWindowHandle != IntPtr.Zero)
{
hWnd = process.MainWindowHandle;
break;
}
}
return hWnd;
}
public static bool IsAlreadyRunning()
{
var assemblyLocation = Assembly.GetEntryAssembly().Location;
var name = $"Global::{Path.GetFileName(assemblyLocation)}";
_mutex = new Mutex(true, name, out bool createdNew);
if (createdNew)
_mutex.ReleaseMutex();
return !createdNew;
}
public static bool SwitchToCurrentInstance()
{
var hWnd = GetCurrentInstanceWindowHandle();
if (hWnd == IntPtr.Zero)
return false;
// Restore window if minimised. Do not restore if already in normal or maximised window state, since we don't want to
// change the current state of the window.
if (IsIconic(hWnd) != 0)
ShowWindow(hWnd, SW_RESTORE);
// Set foreground window.
SetForegroundWindow(hWnd);
return true;
}
public static int ProcessorCount
{
get
{
var processorCount = Environment.ProcessorCount;
//#if DEBUG
// processorCount = 40;
//#endif
return processorCount;
}
}
public static BigInteger[] GetProcessorAffinityList()
{
var processorCount = ProcessorCount;
var results = new List<BigInteger>(processorCount + 1);
results.Add(BigInteger.Zero); // default - all processors
for (int index = 0; index < processorCount; index++)
{
results.Add((BigInteger)Math.Pow(2, index));
}
return results.ToArray();
}
public static string[] GetProcessPriorityList()
{
return new string[] { "low", "belownormal", "normal", "abovenormal", "high" };
}
public static bool IsProcessorAffinityValid(BigInteger affinityValue)
{
if (affinityValue == BigInteger.Zero)
return true;
var maxaffinity = (BigInteger)Math.Pow(2, ProcessorCount);
if (affinityValue < BigInteger.Zero || affinityValue > maxaffinity)
return false;
return true;
}
public static bool IsProcessPriorityValid(string priorityValue)
{
if (string.IsNullOrWhiteSpace(priorityValue))
return false;
var priorityList = GetProcessPriorityList();
if (!priorityList.Contains(priorityValue))
return false;
return true;
}
}
}

View file

@ -0,0 +1,25 @@
using System;
using System.Windows;
namespace ServerManagerTool.Common.Utils
{
public static class ResourceUtils
{
public static string GetResourceString(ResourceDictionary resources, string inKey)
{
if (resources == null)
throw new ArgumentNullException(nameof(resources), "parameter cannot be null.");
if (string.IsNullOrWhiteSpace(inKey))
throw new ArgumentNullException(nameof(inKey), "parameter cannot be null.");
if (resources.Contains(inKey) && resources[inKey] is string)
{
var resourceString = resources[inKey].ToString();
resourceString = resourceString.Replace("\\r", "\r");
resourceString = resourceString.Replace("\\n", "\n");
return resourceString;
}
return null;
}
}
}

View file

@ -0,0 +1,122 @@
using NLog;
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
namespace ServerManagerTool.Common.Utils
{
public static class ScriptUtils
{
public static Logger _logger = LogManager.GetCurrentClassLogger();
static int NextScriptId = 0;
public static bool RunElevatedShellScript(string scriptName, string script)
{
return RunShellScript(scriptName, script, withElevation: true);
}
public static bool RunShellScript(string scriptName, string script, bool withElevation = false, bool waitForExit = true, bool deleteOnExit = true, bool includePID = false)
{
var scriptNameBase = includePID ? $"{scriptName}_{Process.GetCurrentProcess().Id}" : scriptName;
string baseScriptPath = Path.Combine(Path.GetTempPath(), $"{scriptNameBase}.cmd");
string scriptWrapperPath = Path.Combine(Path.GetTempPath(), $"{scriptNameBase}_wrapper.cmd");
string scriptLogPath = null;
scriptLogPath = Path.ChangeExtension(baseScriptPath, ".out");
_logger.Debug($"Running Script (Elevation {withElevation}) : {script}");
var scriptId = NextScriptId++;
try
{
WriteCommandScript(baseScriptPath, script);
//
// Wrap to capture logging (necessary for running administrator scripts from non-admin contexts)
//
WriteCommandScript(scriptWrapperPath, $"CMD /C {baseScriptPath.AsQuoted()} > {scriptLogPath.AsQuoted()} 2>&1");
//
// Launch the process
//
ProcessStartInfo psInfo = new ProcessStartInfo()
{
FileName = $"{scriptWrapperPath.AsQuoted()}",
Verb = withElevation ? "runas" : String.Empty,
UseShellExecute = true,
CreateNoWindow = true,
//WindowStyle = ProcessWindowStyle.Hidden,
};
var process = new Process
{
EnableRaisingEvents = true,
StartInfo = psInfo,
};
process.Start();
//
// If we wait, copy the log files when the process is done.
//
if (waitForExit)
{
process.WaitForExit();
try
{
_logger.Debug($"SCRIPT {scriptId} OUTPUT: {File.ReadAllText(scriptLogPath)}");
}
catch { }
return process.ExitCode == 0;
}
return true;
}
catch (Exception ex)
{
_logger.Error($"{nameof(RunShellScript)} - Failed to run elevated script. {ex.Message}\r\n{ex.StackTrace}");
Debug.WriteLine("Failed to run elevated script: {0}", ex.Message);
Debugger.Break();
return false;
}
finally
{
//
// If we aren't waiting, we can't delete because we will kill the scripts before cmd.exe gets a chance to run them.
//
if (waitForExit && deleteOnExit)
{
File.Delete(baseScriptPath);
File.Delete(scriptWrapperPath);
File.Delete(scriptLogPath);
}
}
}
public static void WriteCommandScript(string destinationPath, string script)
{
var builder = new StringBuilder();
// Change to the UTF8 code page
builder.AppendLine("chcp 65001");
builder.Append(script);
File.WriteAllText(destinationPath, builder.ToString(), new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
}
public static string AsQuoted(this string parameter)
{
var newValue = parameter;
if (!newValue.StartsWith("\""))
newValue = "\"" + newValue;
if (!newValue.EndsWith("\""))
newValue += "\"";
return newValue;
}
}
}

View file

@ -0,0 +1,288 @@
using NLog;
using System;
using System.Diagnostics;
using System.DirectoryServices.AccountManagement;
using System.IO;
using System.Security;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Text;
namespace ServerManagerTool.Common.Utils
{
public static class SecurityUtils
{
private const string PasswordChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
private const string GROUP_USERSBUILTIN = @"BUILTIN\Users";
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
private static int callCount = 0;
public static string GeneratePassword(int count)
{
StringBuilder newPassword = new StringBuilder(count);
Random random;
unchecked
{
random = new Random((int)DateTime.Now.Ticks + callCount);
callCount++;
}
for(int i = 0; i < count; i++)
{
newPassword.Append(PasswordChars[random.Next(PasswordChars.Length)]);
}
return newPassword.ToString();
}
public static bool IsAdministrator()
{
WindowsIdentity identity = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
public static bool SetDirectoryOwnershipForAllUsers(string directory)
{
if (string.IsNullOrWhiteSpace(directory) || !Directory.Exists(directory))
return true;
try
{
var directoryInfo = new DirectoryInfo(directory);
var security = directoryInfo.GetAccessControl(AccessControlSections.Access);
bool result;
var iFlags = InheritanceFlags.None;
// *** Add Access Rule to the actual directory itself
var accessRule = new FileSystemAccessRule(GROUP_USERSBUILTIN, FileSystemRights.FullControl, iFlags, PropagationFlags.NoPropagateInherit, AccessControlType.Allow);
security.ModifyAccessRule(AccessControlModification.Set, accessRule, out result);
if (!result)
return false;
// *** Always allow objects to inherit on a directory
iFlags = InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit;
// *** Add Access rule for the inheritance
accessRule = new FileSystemAccessRule(GROUP_USERSBUILTIN, FileSystemRights.FullControl, iFlags, PropagationFlags.InheritOnly, AccessControlType.Allow);
security.ModifyAccessRule(AccessControlModification.Add, accessRule, out result);
if (!result)
return false;
directoryInfo.SetAccessControl(security);
return true;
}
catch (Exception ex)
{
// We give it a best-effort here. If we aren't running an enterprise OS, this group may not exist (or be needed.)
_logger.Error($"{nameof(SetDirectoryOwnershipForAllUsers)}. {ex.Message}\r\n{ex.StackTrace}");
return false;
}
}
public static bool SetFileOwnershipForAllUsers(string file)
{
if (string.IsNullOrWhiteSpace(file) || !File.Exists(file))
return true;
try
{
var fileInfo = new FileInfo(file);
var security = fileInfo.GetAccessControl(AccessControlSections.Access);
bool result;
var iFlags = InheritanceFlags.None;
// *** Add Access Rule to the actual file itself
var accessRule = new FileSystemAccessRule(GROUP_USERSBUILTIN, FileSystemRights.FullControl, iFlags, PropagationFlags.NoPropagateInherit, AccessControlType.Allow);
security.ModifyAccessRule(AccessControlModification.Set, accessRule, out result);
if (!result)
return false;
fileInfo.SetAccessControl(security);
return true;
}
catch (Exception ex)
{
// We give it a best-effort here. If we aren't running an enterprise OS, this group may not exist (or be needed.)
_logger.Error($"{nameof(SetFileOwnershipForAllUsers)}. {ex.Message}\r\n{ex.StackTrace}");
return false;
}
}
public static bool DoesLocalWindowsAccountExist(string username)
{
try
{
if (MachineUtils.IsThisMachineADomainController())
throw new Exception($"This computer reports to be a domain controller.");
var context = new PrincipalContext(ContextType.Machine, Environment.MachineName);
if (context == null)
context = new PrincipalContext(ContextType.Machine);
if (context == null)
throw new Exception($"Could not create instance of the PrincipalContext ({Environment.MachineName}).");
var user = UserPrincipal.FindByIdentity(context, IdentityType.Name, username);
if (user == null || !(user.Enabled.HasValue && user.Enabled.Value) || user.IsAccountLockedOut())
return false;
var usersGroupSID = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
GroupPrincipal group = GroupPrincipal.FindByIdentity(context, IdentityType.Sid, usersGroupSID.Value);
if (group == null || !group.Members.Contains(user))
return false;
return true;
}
catch (Exception ex)
{
_logger.Error($"{nameof(DoesLocalWindowsAccountExist)}. {ex.Message}\r\n{ex.StackTrace}");
return false;
}
}
public static bool CreateLocalWindowsAccount(string username, string password, string displayName, string description, bool userCannotChangePassword, bool passwordNeverExpires)
{
try
{
if (MachineUtils.IsThisMachineADomainController())
throw new Exception($"This computer reports to be a domain controller. User cannot be created.");
var context = new PrincipalContext(ContextType.Machine, Environment.MachineName);
if (context == null)
context = new PrincipalContext(ContextType.Machine);
if (context == null)
throw new Exception($"Could not create instance of the PrincipalContext ({Environment.MachineName}).");
// create the user if it does not exist
var user = UserPrincipal.FindByIdentity(context, IdentityType.Name, username);
if (user == null)
{
user = new UserPrincipal(context)
{
Name = username,
DisplayName = displayName,
Description = description,
};
if (user == null)
throw new Exception($"Could not create new instance of the UserPrincipal ({username}).");
}
user.Enabled = true;
user.PasswordNeverExpires = passwordNeverExpires;
user.UserCannotChangePassword = userCannotChangePassword;
user.SetPassword(password);
if (user.IsAccountLockedOut())
user.UnlockAccount();
user.Save();
// now add user to "Users" group
var usersGroupSID = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
if (usersGroupSID == null)
throw new Exception($"Could not find instance of the SecurityIdentifier (WellKnownSidType.BuiltinUsersSid).");
GroupPrincipal group = GroupPrincipal.FindByIdentity(context, IdentityType.Sid, usersGroupSID.Value);
if (group == null)
throw new Exception($"Could not find instance of the GroupPrincipal (USERS).");
if (!group.Members.Contains(user))
{
group.Members.Add(user);
group.Save();
}
return true;
}
catch (Exception ex)
{
_logger.Error($"{nameof(CreateLocalWindowsAccount)}. {ex.Message}\r\n{ex.StackTrace}");
return false;
}
}
public static bool ChangeWindowsAccountPassword(string username, string password)
{
try
{
if (MachineUtils.IsThisMachineADomainController())
throw new Exception($"This computer reports to be a domain controller. User password cannot be changed.");
var context = new PrincipalContext(ContextType.Machine, Environment.MachineName);
if (context == null)
context = new PrincipalContext(ContextType.Machine);
if (context == null)
throw new Exception($"Could not create instance of the PrincipalContext ({Environment.MachineName}).");
// create the user if it does not exist
var user = UserPrincipal.FindByIdentity(context, IdentityType.Name, username);
if (user == null)
throw new Exception($"Could not find instance of the UserPrincipal ({username}).");
user.SetPassword(password);
user.Save();
return true;
}
catch (Exception ex)
{
_logger.Error($"{nameof(ChangeWindowsAccountPassword)}. {ex.Message}\r\n{ex.StackTrace}");
return false;
}
}
public static bool DeleteLocalWindowsAccount(string username)
{
try
{
if (MachineUtils.IsThisMachineADomainController())
throw new Exception($"This computer reports to be a domain controller. User cannot be deleted.");
var context = new PrincipalContext(ContextType.Machine, Environment.MachineName);
if (context == null)
context = new PrincipalContext(ContextType.Machine);
if (context == null)
throw new Exception($"Could not create instance of the PrincipalContext ({Environment.MachineName}).");
// create the user if it does not exist
var user = UserPrincipal.FindByIdentity(context, IdentityType.Name, username);
if (user == null)
throw new Exception($"Could not find instance of the UserPrincipal ({username}).");
// now remove user from "Users" group
var usersGroupSID = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
if (usersGroupSID != null)
{
GroupPrincipal group = GroupPrincipal.FindByIdentity(context, IdentityType.Sid, usersGroupSID.Value);
if (group != null && group.Members.Contains(user))
group.Members.Remove(user);
}
user.Delete();
return true;
}
catch (Exception ex)
{
_logger.Error($"{nameof(DeleteLocalWindowsAccount)}. {ex.Message}\r\n{ex.StackTrace}");
return false;
}
}
public static SecureString GetSecureString(string sourceString)
{
var secureString = new SecureString();
foreach (var sourceChar in sourceString)
{
secureString.AppendChar(sourceChar);
}
return secureString;
}
}
}

View file

@ -0,0 +1,86 @@
using Newtonsoft.Json;
using ServerManagerTool.Common.Lib;
using System;
using System.IO;
using System.Linq;
namespace ServerManagerTool.Common.Utils
{
public static class SettingsUtils
{
public static void BackupUserConfigSettings(System.Configuration.ApplicationSettingsBase settings, string fileName, string settingsPath, string backupPath)
{
if (settings == null || string.IsNullOrWhiteSpace(fileName))
return;
var settingsFileName = Path.GetFileNameWithoutExtension(fileName);
var settingsFileExt = Path.GetExtension(fileName);
var settingsFile = IOUtils.NormalizePath(Path.Combine(settingsPath, $"{fileName}"));
try
{
// save the settings file to a json settings file
var jsonSettings = new JsonSerializerSettings
{
ContractResolver = new UserScopedSettingContractResolver(),
};
JsonUtils.SerializeToFile(settings, settingsFile, jsonSettings);
}
catch (Exception)
{
// do nothing, just exit
}
if (!string.IsNullOrWhiteSpace(backupPath))
{
// create a backup of the settings file
var backupFile = IOUtils.NormalizePath(Path.Combine(backupPath, $"{settingsFileName}_{DateTime.UtcNow.ToString("yyyyMMdd_HHmmss")}{settingsFileExt}"));
try
{
if (!Directory.Exists(backupPath))
Directory.CreateDirectory(backupPath);
File.Copy(settingsFile, backupFile);
}
catch (Exception)
{
// do nothing, just exit
}
var filesToDelete = new DirectoryInfo(backupPath).GetFiles($"{settingsFileName}_*{settingsFileExt}").Where(f => f.LastWriteTimeUtc.AddDays(7) < DateTime.UtcNow).ToArray();
foreach (var fileToDelete in filesToDelete)
{
try
{
fileToDelete.Delete();
}
catch (Exception)
{
// do nothing, just exit
}
}
}
}
public static void MigrateSettings(System.Configuration.ApplicationSettingsBase settings, string settingsFile)
{
if (settings == null || string.IsNullOrWhiteSpace(settingsFile) || !File.Exists(settingsFile))
return;
try
{
// read the json settings file to a settings file
var jsonSettings = new JsonSerializerSettings
{
//ContractResolver = new UserScopedSettingContractResolver(),
};
JsonUtils.PopulateFromFile(settingsFile, settings, jsonSettings);
}
catch (Exception)
{
// do nothing, just exit
}
}
}
}

View file

@ -0,0 +1,293 @@
using NeXt.Vdf;
using NLog;
using ServerManagerTool.Common.Model;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
namespace ServerManagerTool.Common.Utils
{
public static class SteamUtils
{
private const string KEYWORK_QUIT = "+quit";
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
public static WorkshopFileDetailResponse GetSteamModDetails(string appId)
{
const int MAX_IDS = 100;
var totalRequests = 0;
var requestIndex = 1;
var response = new WorkshopFileDetailResponse();
if (string.IsNullOrWhiteSpace(SteamWebApiKey))
return response;
try
{
do
{
var httpRequest = WebRequest.Create($"https://api.steampowered.com/IPublishedFileService/QueryFiles/v1/?key={SteamWebApiKey}&format=json&query_type=1&page={requestIndex}&numperpage={MAX_IDS}&appid={appId}&match_all_tags=0&include_recent_votes_only=0&totalonly=0&return_vote_data=0&return_tags=0&return_kv_tags=0&return_previews=0&return_children=0&return_short_description=0&return_for_sale_data=0&return_metadata=1");
httpRequest.Timeout = 30000;
var httpResponse = httpRequest.GetResponse();
var responseString = new StreamReader(httpResponse.GetResponseStream()).ReadToEnd();
var result = JsonUtils.Deserialize<WorkshopFileDetailResult>(responseString);
if (result == null || result.response == null)
break;
if (totalRequests == 0)
{
totalRequests = 1;
response = result.response;
if (response.total > MAX_IDS)
{
int remainder;
totalRequests = Math.DivRem(response.total, MAX_IDS, out remainder);
if (remainder > 0)
totalRequests++;
}
}
else
{
if (result.response.publishedfiledetails != null)
response.publishedfiledetails.AddRange(result.response.publishedfiledetails);
}
requestIndex++;
} while (requestIndex <= totalRequests);
return response;
}
catch (Exception ex)
{
_logger.Error($"{nameof(GetSteamModDetails)}. {ex.Message}\r\n{ex.StackTrace}");
Debug.WriteLine($"ERROR: {nameof(GetSteamModDetails)}\r\n{ex.Message}");
return null;
}
}
public static PublishedFileDetailsResponse GetSteamModDetails(List<string> modIdList)
{
const int MAX_IDS = 20;
PublishedFileDetailsResponse response = null;
if (string.IsNullOrWhiteSpace(SteamWebApiKey))
return response;
try
{
if (modIdList == null || modIdList.Count == 0)
return new PublishedFileDetailsResponse();
int remainder;
var totalRequests = Math.DivRem(modIdList.Count, MAX_IDS, out remainder);
if (remainder > 0)
totalRequests++;
var requestIndex = 0;
while (requestIndex < totalRequests)
{
var count = 0;
var postData = "";
for (var index = requestIndex * MAX_IDS; count < MAX_IDS && index < modIdList.Count; index++)
{
postData += $"&publishedfileids[{count}]={modIdList[index]}";
count++;
}
postData = $"key={SteamWebApiKey}&format=json&itemcount={count}{postData}";
var data = Encoding.ASCII.GetBytes(postData);
var httpRequest = WebRequest.Create("https://api.steampowered.com/ISteamRemoteStorage/GetPublishedFileDetails/v1/");
httpRequest.Timeout = 30000;
httpRequest.Method = "POST";
httpRequest.ContentType = "application/x-www-form-urlencoded";
httpRequest.ContentLength = data.Length;
using (var stream = httpRequest.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var httpResponse = (HttpWebResponse)httpRequest.GetResponse();
var responseString = new StreamReader(httpResponse.GetResponseStream()).ReadToEnd();
var result = JsonUtils.Deserialize<PublishedFileDetailsResult>(responseString);
if (result != null && result.response != null)
{
if (response == null)
response = result.response;
else
{
response.resultcount += result.response.resultcount;
response.publishedfiledetails.AddRange(result.response.publishedfiledetails);
}
}
requestIndex++;
};
return response ?? new PublishedFileDetailsResponse();
}
catch (Exception ex)
{
_logger.Error($"{nameof(GetSteamModDetails)}. {ex.Message}\r\n{ex.StackTrace}");
Debug.WriteLine($"ERROR: {nameof(GetSteamModDetails)}\r\n{ex.Message}");
return null;
}
}
public static SteamUserDetailResponse GetSteamUserDetails(List<string> steamIdList)
{
const int MAX_IDS = 100;
SteamUserDetailResponse response = null;
if (string.IsNullOrWhiteSpace(SteamWebApiKey))
return response;
try
{
if (steamIdList.Count == 0)
return new SteamUserDetailResponse();
steamIdList = steamIdList.Distinct().ToList();
steamIdList = steamIdList.Where(i => long.TryParse(i, out long id)).ToList();
if (steamIdList.Count == 0)
return new SteamUserDetailResponse();
int remainder;
var totalRequests = Math.DivRem(steamIdList.Count, MAX_IDS, out remainder);
if (remainder > 0)
totalRequests++;
var requestIndex = 0;
while (requestIndex < totalRequests)
{
var count = 0;
var postData = "";
var delimiter = "";
for (var index = requestIndex * MAX_IDS; count < MAX_IDS && index < steamIdList.Count; index++)
{
postData += $"{delimiter}{steamIdList[index]}";
delimiter = ",";
count++;
}
var httpRequest = WebRequest.Create($"https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v2/?key={SteamWebApiKey}&format=json&steamids={postData}");
httpRequest.Timeout = 30000;
var httpResponse = (HttpWebResponse)httpRequest.GetResponse();
var responseString = new StreamReader(httpResponse.GetResponseStream()).ReadToEnd();
var result = JsonUtils.Deserialize<SteamUserDetailResult>(responseString);
if (result != null && result.response != null)
{
if (response == null)
response = result.response;
else
{
response.players.AddRange(result.response.players);
}
}
requestIndex++;
}
return response ?? new SteamUserDetailResponse();
}
catch (Exception ex)
{
_logger.Error($"{nameof(GetSteamUserDetails)}. {ex.Message}\r\n{ex.StackTrace}");
Debug.WriteLine($"ERROR: {nameof(GetSteamUserDetails)}\r\n{ex.Message}");
return null;
}
}
public static SteamCmdAppManifest ReadSteamCmdAppManifestFile(string file)
{
if (string.IsNullOrWhiteSpace(file) || !File.Exists(file))
return null;
var vdfSerializer = VdfDeserializer.FromFile(file);
var vdf = vdfSerializer.Deserialize();
return SteamCmdManifestDetailsResult.Deserialize(vdf);
}
public static SteamCmdAppWorkshop ReadSteamCmdAppWorkshopFile(string file)
{
if (string.IsNullOrWhiteSpace(file) || !File.Exists(file))
return null;
var vdfSerializer = VdfDeserializer.FromFile(file);
var vdf = vdfSerializer.Deserialize();
return SteamCmdWorkshopDetailsResult.Deserialize(vdf);
}
public static string SteamWebApiKey
{
get
{
if (!string.IsNullOrWhiteSpace(CommonConfig.Default.SteamAPIKey))
return CommonConfig.Default.SteamAPIKey;
return CommonConfig.Default.DefaultSteamAPIKey;
}
}
public static Process GetSteamProcess()
{
if (string.IsNullOrWhiteSpace(CommonConfig.Default.SteamClientFile) || !File.Exists(CommonConfig.Default.SteamClientFile))
return null;
// Find the server process.
var expectedPath = IOUtils.NormalizePath(CommonConfig.Default.SteamClientFile);
var runningProcesses = Process.GetProcessesByName(CommonConfig.Default.SteamProcessName);
Process process = null;
foreach (var runningProcess in runningProcesses)
{
var runningPath = ProcessUtils.GetMainModuleFilepath(runningProcess.Id);
if (string.Equals(expectedPath, runningPath, StringComparison.OrdinalIgnoreCase))
{
process = runningProcess;
break;
}
}
return process;
}
public static string BuildSteamCmdArguments(bool removeQuit, string argumentString)
{
if (string.IsNullOrWhiteSpace(argumentString))
return argumentString;
var newArgumentString = argumentString.TrimEnd(' ');
if (newArgumentString.ToLower().EndsWith(KEYWORK_QUIT) && removeQuit)
return newArgumentString.Substring(0, newArgumentString.Length - KEYWORK_QUIT.Length);
else if (!newArgumentString.ToLower().EndsWith(KEYWORK_QUIT) && !removeQuit)
return newArgumentString += $" {KEYWORK_QUIT}";
return newArgumentString.TrimEnd(' ');
}
public static string BuildSteamCmdArguments(bool removeQuit, string argumentFormatString, params string[] argumentValues)
{
if (string.IsNullOrWhiteSpace(argumentFormatString) || argumentValues == null || argumentValues.Length == 0)
return argumentFormatString;
var argumentString = string.Format(argumentFormatString, argumentValues);
return BuildSteamCmdArguments(removeQuit, argumentString);
}
}
}

View file

@ -0,0 +1,161 @@
using ServerManagerTool.Common.Attibutes;
using ServerManagerTool.Common.Model;
using System;
using System.Globalization;
using System.Reflection;
namespace ServerManagerTool.Common.Utils
{
public static class StringUtils
{
public const string DEFAULT_CULTURE_CODE = "en-US";
public static string GetPropertyValue(object value, PropertyInfo property)
{
string convertedVal;
if (property.PropertyType == typeof(float))
convertedVal = ((float)value).ToString("0.000000####", CultureInfo.GetCultureInfo(DEFAULT_CULTURE_CODE));
else if (property.PropertyType == typeof(string))
convertedVal = $"\"{value}\"";
else
convertedVal = Convert.ToString(value, CultureInfo.GetCultureInfo(DEFAULT_CULTURE_CODE));
return convertedVal;
}
public static string GetPropertyValue(object value, PropertyInfo property, BaseIniFileEntryAttribute attribute)
{
string convertedVal;
if (property.PropertyType == typeof(int) || property.PropertyType == typeof(NullableValue<int>))
convertedVal = Convert.ToString(value, CultureInfo.GetCultureInfo(DEFAULT_CULTURE_CODE));
else if (property.PropertyType == typeof(float) || property.PropertyType == typeof(NullableValue<float>))
convertedVal = ((float)value).ToString("0.000000####", CultureInfo.GetCultureInfo(DEFAULT_CULTURE_CODE));
else if (property.PropertyType == typeof(bool))
{
var boolValue = (bool)value;
if (attribute.InvertBoolean)
boolValue = !boolValue;
if (attribute.WriteBooleanAsInteger)
convertedVal = boolValue ? "1" : "0";
else
convertedVal = boolValue.ToString(CultureInfo.GetCultureInfo(DEFAULT_CULTURE_CODE));
}
else
convertedVal = Convert.ToString(value, CultureInfo.GetCultureInfo(DEFAULT_CULTURE_CODE));
return convertedVal;
}
public static void SetPropertyValue(string value, object obj, PropertyInfo property)
{
if (property.PropertyType == typeof(bool) || property.PropertyType == typeof(bool?))
{
bool boolValue;
bool.TryParse(value, out boolValue);
property.SetValue(obj, boolValue);
}
else if (property.PropertyType == typeof(int) || property.PropertyType == typeof(int?))
{
int intValue;
int.TryParse(value, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.GetCultureInfo(DEFAULT_CULTURE_CODE), out intValue);
property.SetValue(obj, intValue);
}
else if (property.PropertyType == typeof(float) || property.PropertyType == typeof(float?))
{
var tempValue = value.Replace("f", "");
float floatValue;
float.TryParse(tempValue, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.GetCultureInfo(DEFAULT_CULTURE_CODE), out floatValue);
property.SetValue(obj, floatValue);
}
else if (property.PropertyType == typeof(NullableValue<int>))
{
int intValue;
int.TryParse(value, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.GetCultureInfo(DEFAULT_CULTURE_CODE), out intValue);
var field = property.GetValue(obj) as NullableValue<int>;
property.SetValue(obj, field.SetValue(true, intValue));
}
else if (property.PropertyType == typeof(NullableValue<float>))
{
var tempValue = value.Replace("f", "");
float floatValue;
float.TryParse(tempValue, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.GetCultureInfo(DEFAULT_CULTURE_CODE), out floatValue);
var field = property.GetValue(obj) as NullableValue<float>;
property.SetValue(obj, field.SetValue(true, floatValue));
}
else if (property.PropertyType.IsSubclassOf(typeof(AggregateIniValue)))
{
var field = property.GetValue(obj) as AggregateIniValue;
field?.InitializeFromINIValue(value);
}
else
{
var convertedValue = Convert.ChangeType(value, property.PropertyType, CultureInfo.GetCultureInfo(DEFAULT_CULTURE_CODE));
if (convertedValue is string)
convertedValue = (convertedValue as string).Trim('"');
property.SetValue(obj, convertedValue);
}
}
public static bool SetPropertyValue(string value, object obj, PropertyInfo property, BaseIniFileEntryAttribute attribute)
{
if (property.PropertyType == typeof(bool) || property.PropertyType == typeof(bool?))
{
bool boolValue;
if (attribute.WriteBooleanAsInteger)
boolValue = value.Equals("1", StringComparison.OrdinalIgnoreCase);
else
bool.TryParse(value, out boolValue);
if (attribute.InvertBoolean)
boolValue = !boolValue;
property.SetValue(obj, boolValue);
return true;
}
if (property.PropertyType == typeof(int) || property.PropertyType == typeof(int?))
{
int intValue;
int.TryParse(value, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.GetCultureInfo(DEFAULT_CULTURE_CODE), out intValue);
property.SetValue(obj, intValue);
return true;
}
if (property.PropertyType == typeof(float) || property.PropertyType == typeof(float?))
{
var tempValue = value.Replace("f", "");
float floatValue;
float.TryParse(tempValue, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.GetCultureInfo(DEFAULT_CULTURE_CODE), out floatValue);
property.SetValue(obj, floatValue);
return true;
}
if (property.PropertyType == typeof(NullableValue<int>))
{
int intValue;
int.TryParse(value, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.GetCultureInfo(DEFAULT_CULTURE_CODE), out intValue);
var field = property.GetValue(obj) as NullableValue<int>;
property.SetValue(obj, field.SetValue(true, intValue));
return true;
}
if (property.PropertyType == typeof(NullableValue<float>))
{
var tempValue = value.Replace("f", "");
float floatValue;
float.TryParse(tempValue, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.GetCultureInfo(DEFAULT_CULTURE_CODE), out floatValue);
var field = property.GetValue(obj) as NullableValue<float>;
property.SetValue(obj, field.SetValue(true, floatValue));
return true;
}
if (property.PropertyType.IsSubclassOf(typeof(AggregateIniValue)))
{
var field = property.GetValue(obj) as AggregateIniValue;
field?.InitializeFromINIValue(value);
return true;
}
return false;
}
}
}

View file

@ -0,0 +1,707 @@
using Microsoft.Win32.TaskScheduler;
using NLog;
using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
namespace ServerManagerTool.Common.Utils
{
public static class TaskSchedulerUtils
{
private const string PREFIX_BACKUP = "AutoBackup";
private const string PREFIX_SHUTDOWN = "AutoShutdown";
private const string PREFIX_START = "AutoStart";
private const string PREFIX_UPDATE = "AutoUpdate";
private const int EXECUTION_TIME_LIMIT = 3;
public enum ShutdownType
{
Shutdown1,
Shutdown2,
}
public enum TaskType
{
AutoBackup,
AutoShutdown,
AutoStart,
AutoUpdate,
}
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
static TaskSchedulerUtils()
{
TaskFolder = "ServerManager";
}
public static string TaskFolder
{
get;
set;
}
public static string ComputeKey(string folder)
{
try
{
using (var hashAlgo = MD5.Create())
{
var hashStr = Encoding.UTF8.GetBytes(folder);
var hash = hashAlgo.ComputeHash(hashStr);
StringBuilder sb = new StringBuilder();
foreach (var b in hash)
{
// can be "x2" if you want lowercase
sb.Append(b.ToString("x2"));
}
return sb.ToString();
}
}
catch (TargetInvocationException ex)
{
// Exception has been thrown by the target of an invocation.
// This error message seems to occur when using MD5 hash algorithm on an environment where FIPS is enabled.
// Swallow the exception and allow the SHA1 algorithm to be used.
_logger.Debug($"Unable to calculate the ComputeKey (MD5).\r\n{ex.Message}.");
}
// An error occurred using the MD5 hash, try using SHA1 instead.
using (var hashAlgo = SHA1.Create())
{
var hashStr = Encoding.UTF8.GetBytes(folder);
var hash = hashAlgo.ComputeHash(hashStr);
var sb = new StringBuilder(hash.Length * 2);
foreach (byte b in hash)
{
// can be "x2" if you want lowercase
sb.Append(b.ToString("x2"));
}
return sb.ToString();
}
}
public static string GetScheduleTaskInformation(TaskType taskType, string taskKey, string taskSuffix)
{
var taskName = GetScheduledTaskName(taskType, taskKey, taskSuffix);
var taskFolder = TaskService.Instance.RootFolder.SubFolders.Exists(TaskFolder) ? TaskService.Instance.RootFolder.SubFolders[TaskFolder] : null;
if (taskFolder == null)
return null;
var task = taskFolder.Tasks.Exists(taskName) ? taskFolder.Tasks[taskName] : null;
if (task == null)
return null;
return task.Xml;
}
public static string GetScheduledTaskName(TaskType taskType, string taskKey, string taskSuffix)
{
var taskName = string.Empty;
switch (taskType)
{
case TaskType.AutoBackup:
taskName = $"{PREFIX_BACKUP}_{taskKey}";
break;
case TaskType.AutoShutdown:
taskName = $"{PREFIX_SHUTDOWN}_{taskKey}";
break;
case TaskType.AutoStart:
taskName = $"{PREFIX_START}_{taskKey}";
break;
case TaskType.AutoUpdate:
taskName = $"{PREFIX_UPDATE}_{taskKey}";
break;
}
if (!string.IsNullOrWhiteSpace(taskName) && !string.IsNullOrWhiteSpace(taskSuffix))
taskName += $"_{taskSuffix}";
return taskName;
}
public static void RunAutoBackup(string taskKey, string taskSuffix)
{
var taskName = GetScheduledTaskName(TaskType.AutoBackup, taskKey, taskSuffix);
var taskFolder = TaskService.Instance.RootFolder.SubFolders.Exists(TaskFolder) ? TaskService.Instance.RootFolder.SubFolders[TaskFolder] : null;
if (taskFolder == null)
return;
var task = taskFolder.Tasks.Exists(taskName) ? taskFolder.Tasks[taskName] : null;
if (task == null)
return;
task.Run();
}
public static void RunAutoUpdate(string taskKey, string taskSuffix)
{
var taskName = GetScheduledTaskName(TaskType.AutoUpdate, taskKey, taskSuffix);
var taskFolder = TaskService.Instance.RootFolder.SubFolders.Exists(TaskFolder) ? TaskService.Instance.RootFolder.SubFolders[TaskFolder] : null;
if (taskFolder == null)
return;
var task = taskFolder.Tasks.Exists(taskName) ? taskFolder.Tasks[taskName] : null;
if (task == null)
return;
task.Run();
}
public static bool ScheduleAutoBackup(string taskKey, string taskSuffix, string command, int autoBackupPeriod)
{
var taskName = GetScheduledTaskName(TaskType.AutoBackup, taskKey, taskSuffix);
var taskFolder = TaskService.Instance.RootFolder.SubFolders.Exists(TaskFolder) ? TaskService.Instance.RootFolder.SubFolders[TaskFolder] : null;
if (autoBackupPeriod > 0)
{
// create the task folder
if (taskFolder == null)
{
try
{
taskFolder = TaskService.Instance.RootFolder.CreateFolder(TaskFolder, null, false);
}
catch (Exception ex)
{
_logger.Error($"{nameof(ScheduleAutoBackup)} - Unable to create the Server Manager task folder. {ex.Message}\r\n{ex.StackTrace}");
return false;
}
}
if (taskFolder == null)
return false;
var task = taskFolder.Tasks.Exists(taskName) ? taskFolder.Tasks[taskName] : null;
var taskDefinition = task?.Definition ?? TaskService.Instance.NewTask();
if (taskDefinition == null)
return false;
Version.TryParse(AppUtils.GetDeployedVersion(), out Version appVersion);
taskDefinition.Principal.LogonType = TaskLogonType.InteractiveToken;
taskDefinition.Principal.RunLevel = TaskRunLevel.Highest;
taskDefinition.RegistrationInfo.Description = "Server Auto-Backup";
taskDefinition.RegistrationInfo.Source = "Server Manager";
taskDefinition.RegistrationInfo.Version = appVersion;
taskDefinition.Settings.ExecutionTimeLimit = TimeSpan.FromHours(EXECUTION_TIME_LIMIT);
taskDefinition.Settings.Priority = ProcessPriorityClass.Normal;
// Add/Edit the trigger that will fire every x minutes
var triggers = taskDefinition.Triggers.OfType<TimeTrigger>();
if (triggers.Count() == 0)
{
var trigger = new TimeTrigger
{
StartBoundary = DateTime.Today.AddHours(DateTime.Now.Hour + 1),
ExecutionTimeLimit = TimeSpan.FromHours(EXECUTION_TIME_LIMIT),
Repetition = { Interval = TimeSpan.FromMinutes(autoBackupPeriod) },
};
taskDefinition.Triggers.Add(trigger);
}
else
{
foreach (var trigger in triggers)
{
trigger.Repetition.Interval = TimeSpan.FromMinutes(autoBackupPeriod);
}
}
// Create an action that will launch whenever the trigger fires
taskDefinition.Actions.Clear();
var action = new ExecAction
{
Path = command,
Arguments = Constants.ARG_AUTOBACKUP
};
taskDefinition.Actions.Add(action);
try
{
task = taskFolder.RegisterTaskDefinition(taskName, taskDefinition, TaskCreation.CreateOrUpdate, null, null, TaskLogonType.InteractiveToken);
return task != null;
}
catch (Exception ex)
{
_logger.Error($"{nameof(ScheduleAutoBackup)} - Unable to create the ScheduleAutoBackup task. {ex.Message}\r\n{ex.StackTrace}");
}
}
else
{
if (taskFolder == null)
return true;
// Retrieve the task to be deleted
var task = taskFolder.Tasks.Exists(taskName) ? taskFolder.Tasks[taskName] : null;
if (task == null)
return true;
try
{
// Delete the task
taskFolder.DeleteTask(taskName, false);
return true;
}
catch (Exception ex)
{
_logger.Error($"{nameof(ScheduleAutoBackup)} - Unable to delete the ScheduleAutoBackup task. {ex.Message}\r\n{ex.StackTrace}");
}
}
return false;
}
public static bool ScheduleAutoShutdown(string taskKey, string taskSuffix, string command, TimeSpan? restartTime, string profileName, ShutdownType type)
{
return ScheduleAutoShutdown(taskKey, taskSuffix, command, restartTime, DaysOfTheWeek.AllDays, profileName, type);
}
public static bool ScheduleAutoShutdown(string taskKey, string taskSuffix, string command, TimeSpan? restartTime, DaysOfTheWeek daysOfTheWeek, string profileName, ShutdownType type)
{
var taskName = GetScheduledTaskName(TaskType.AutoShutdown, taskKey, taskSuffix);
var taskFolder = TaskService.Instance.RootFolder.SubFolders.Exists(TaskFolder) ? TaskService.Instance.RootFolder.SubFolders[TaskFolder] : null;
if (restartTime.HasValue)
{
// create the task folder
if (taskFolder == null)
{
try
{
taskFolder = TaskService.Instance.RootFolder.CreateFolder(TaskFolder, null, false);
}
catch (Exception ex)
{
_logger.Error($"{nameof(ScheduleAutoShutdown)} - Unable to create the Server Manager task folder. {ex.Message}\r\n{ex.StackTrace}");
return false;
}
}
if (taskFolder == null)
return false;
var task = taskFolder.Tasks.Exists(taskName) ? taskFolder.Tasks[taskName] : null;
var taskDefinition = task?.Definition ?? TaskService.Instance.NewTask();
if (taskDefinition == null)
return false;
Version.TryParse(AppUtils.GetDeployedVersion(), out Version appVersion);
taskDefinition.Principal.LogonType = TaskLogonType.InteractiveToken;
taskDefinition.Principal.RunLevel = TaskRunLevel.Highest;
taskDefinition.RegistrationInfo.Description = $"Server Auto-Shutdown - {profileName}";
taskDefinition.RegistrationInfo.Source = "Server Manager";
taskDefinition.RegistrationInfo.Version = appVersion;
taskDefinition.Settings.ExecutionTimeLimit = TimeSpan.FromHours(EXECUTION_TIME_LIMIT);
taskDefinition.Settings.Priority = ProcessPriorityClass.Normal;
// Add/Edit the trigger that will fire every day at the specified restart time
var triggers = taskDefinition.Triggers.OfType<WeeklyTrigger>().ToList();
if (triggers.Count == 0)
{
var trigger = new WeeklyTrigger
{
StartBoundary = DateTime.Today.Add(restartTime.Value),
ExecutionTimeLimit = TimeSpan.FromHours(EXECUTION_TIME_LIMIT),
DaysOfWeek = daysOfTheWeek,
};
taskDefinition.Triggers.Add(trigger);
}
else
{
foreach (var trigger in triggers)
{
trigger.StartBoundary = DateTime.Today.Add(restartTime.Value);
trigger.DaysOfWeek = daysOfTheWeek;
}
}
// remove any old triggers
var oldTriggers = taskDefinition.Triggers.OfType<DailyTrigger>().ToList();
if (oldTriggers.Count > 0)
{
foreach (var oldTrigger in oldTriggers)
{
taskDefinition.Triggers.Remove(oldTrigger);
}
}
// Create an action that will launch whenever the trigger fires
var arguments = string.Empty;
switch (type)
{
case ShutdownType.Shutdown1:
arguments = Constants.ARG_AUTOSHUTDOWN1;
break;
case ShutdownType.Shutdown2:
arguments = Constants.ARG_AUTOSHUTDOWN2;
break;
default:
return false;
}
taskDefinition.Actions.Clear();
var action = new ExecAction
{
Path = command,
Arguments = $"{arguments}{taskKey}"
};
taskDefinition.Actions.Add(action);
try
{
task = taskFolder.RegisterTaskDefinition(taskName, taskDefinition, TaskCreation.CreateOrUpdate, null, null, TaskLogonType.InteractiveToken);
return task != null;
}
catch (Exception ex)
{
_logger.Error($"{nameof(ScheduleAutoShutdown)} - Unable to create the ScheduleAutoShutdown task. {ex.Message}\r\n{ex.StackTrace}");
}
}
else
{
if (taskFolder == null)
return true;
// Retrieve the task to be deleted
var task = taskFolder.Tasks.Exists(taskName) ? taskFolder.Tasks[taskName] : null;
if (task == null)
return true;
try
{
// Delete the task
taskFolder.DeleteTask(taskName, false);
return true;
}
catch (Exception ex)
{
_logger.Error($"{nameof(ScheduleAutoShutdown)} - Unable to delete the ScheduleAutoShutdown task. {ex.Message}\r\n{ex.StackTrace}");
}
}
return false;
}
public static bool ScheduleAutoStart(string taskKey, string taskSuffix, bool enableAutoStart, string command, string profileName, bool onBoot)
{
var taskName = GetScheduledTaskName(TaskType.AutoStart, taskKey, taskSuffix);
var taskFolder = TaskService.Instance.RootFolder.SubFolders.Exists(TaskFolder) ? TaskService.Instance.RootFolder.SubFolders[TaskFolder] : null;
if (enableAutoStart)
{
// create the task folder
if (taskFolder == null)
{
try
{
taskFolder = TaskService.Instance.RootFolder.CreateFolder(TaskFolder, null, false);
}
catch (Exception ex)
{
_logger.Error($"{nameof(ScheduleAutoStart)} - Unable to create the Server Manager task folder. {ex.Message}\r\n{ex.StackTrace}");
return false;
}
}
if (taskFolder == null)
return false;
var task = taskFolder.Tasks.Exists(taskName) ? taskFolder.Tasks[taskName] : null;
var taskDefinition = task?.Definition ?? TaskService.Instance.NewTask();
if (taskDefinition == null)
return false;
Version.TryParse(AppUtils.GetDeployedVersion(), out Version appVersion);
taskDefinition.Principal.LogonType = TaskLogonType.ServiceAccount;
taskDefinition.Principal.RunLevel = TaskRunLevel.Highest;
taskDefinition.RegistrationInfo.Description = $"Server Auto-Start - {profileName}";
taskDefinition.RegistrationInfo.Source = "Server Manager";
taskDefinition.RegistrationInfo.Version = appVersion;
taskDefinition.Settings.ExecutionTimeLimit = TimeSpan.FromHours(EXECUTION_TIME_LIMIT);
taskDefinition.Settings.Priority = ProcessPriorityClass.Normal;
// Add a trigger that will fire after the machine has started
if (onBoot)
{
var triggers = taskDefinition.Triggers.OfType<BootTrigger>();
if (triggers.Count() == 0)
{
var trigger = new BootTrigger
{
Delay = TimeSpan.FromMinutes(1),
ExecutionTimeLimit = TimeSpan.FromHours(EXECUTION_TIME_LIMIT)
};
taskDefinition.Triggers.Add(trigger);
}
else
{
foreach (var trigger in triggers)
{
trigger.Delay = TimeSpan.FromMinutes(1);
}
}
}
else
{
var triggers = taskDefinition.Triggers.OfType<LogonTrigger>();
if (triggers.Count() == 0)
{
var trigger = new LogonTrigger
{
Delay = TimeSpan.FromMinutes(1),
ExecutionTimeLimit = TimeSpan.FromHours(EXECUTION_TIME_LIMIT)
};
taskDefinition.Triggers.Add(trigger);
}
else
{
foreach (var trigger in triggers)
{
trigger.Delay = TimeSpan.FromMinutes(1);
}
}
}
// Create an action that will launch whenever the trigger fires
taskDefinition.Actions.Clear();
var action = new ExecAction
{
Path = command,
Arguments = string.Empty
};
taskDefinition.Actions.Add(action);
try
{
task = taskFolder.RegisterTaskDefinition(taskName, taskDefinition, TaskCreation.CreateOrUpdate, "SYSTEM", null, TaskLogonType.ServiceAccount);
return task != null;
}
catch (Exception ex)
{
_logger.Error($"{nameof(ScheduleAutoStart)} - Unable to create the ScheduleAutoStart task. {ex.Message}\r\n{ex.StackTrace}");
}
}
else
{
if (taskFolder == null)
return true;
// Retrieve the task to be deleted
var task = taskFolder.Tasks.Exists(taskName) ? taskFolder.Tasks[taskName] : null;
if (task == null)
return true;
try
{
// Delete the task
taskFolder.DeleteTask(taskName, false);
return true;
}
catch (Exception ex)
{
_logger.Error($"{nameof(ScheduleAutoStart)} - Unable to delete the ScheduleAutoStart task. {ex.Message}\r\n{ex.StackTrace}");
}
}
return false;
}
public static bool ScheduleAutoUpdate(string taskKey, string taskSuffix, string command, int autoUpdatePeriod)
{
var taskName = GetScheduledTaskName(TaskType.AutoUpdate, taskKey, taskSuffix);
var taskFolder = TaskService.Instance.RootFolder.SubFolders.Exists(TaskFolder) ? TaskService.Instance.RootFolder.SubFolders[TaskFolder] : null;
if (autoUpdatePeriod > 0)
{
// create the task folder
if (taskFolder == null)
{
try
{
taskFolder = TaskService.Instance.RootFolder.CreateFolder(TaskFolder, null, false);
}
catch (Exception ex)
{
_logger.Error($"{nameof(ScheduleAutoUpdate)} - Unable to create the Server Manager task folder. {ex.Message}\r\n{ex.StackTrace}");
return false;
}
}
if (taskFolder == null)
return false;
var task = taskFolder.Tasks.Exists(taskName) ? taskFolder.Tasks[taskName] : null;
var taskDefinition = task?.Definition ?? TaskService.Instance.NewTask();
if (taskDefinition == null)
return false;
Version.TryParse(AppUtils.GetDeployedVersion(), out Version appVersion);
taskDefinition.Principal.LogonType = TaskLogonType.InteractiveToken;
taskDefinition.Principal.RunLevel = TaskRunLevel.Highest;
taskDefinition.RegistrationInfo.Description = "Server Auto-Update";
taskDefinition.RegistrationInfo.Source = "Server Manager";
taskDefinition.RegistrationInfo.Version = appVersion;
taskDefinition.Settings.ExecutionTimeLimit = TimeSpan.FromHours(EXECUTION_TIME_LIMIT);
taskDefinition.Settings.Priority = ProcessPriorityClass.Normal;
// Add/Edit the trigger that will fire every x minutes
var triggers = taskDefinition.Triggers.OfType<TimeTrigger>();
if (triggers.Count() == 0)
{
var trigger = new TimeTrigger
{
StartBoundary = DateTime.Today.AddHours(DateTime.Now.Hour + 1),
ExecutionTimeLimit = TimeSpan.FromHours(EXECUTION_TIME_LIMIT),
Repetition = { Interval = TimeSpan.FromMinutes(autoUpdatePeriod) },
};
taskDefinition.Triggers.Add(trigger);
}
else
{
foreach (var trigger in triggers)
{
trigger.Repetition.Interval = TimeSpan.FromMinutes(autoUpdatePeriod);
}
}
// Create an action that will launch whenever the trigger fires
taskDefinition.Actions.Clear();
var action = new ExecAction
{
Path = command,
Arguments = Constants.ARG_AUTOUPDATE
};
taskDefinition.Actions.Add(action);
try
{
task = taskFolder.RegisterTaskDefinition(taskName, taskDefinition, TaskCreation.CreateOrUpdate, null, null, TaskLogonType.InteractiveToken);
return task != null;
}
catch (Exception ex)
{
_logger.Error($"{nameof(ScheduleAutoUpdate)} - Unable to create the ScheduleAutoUpdate task. {ex.Message}\r\n{ex.StackTrace}");
}
}
else
{
if (taskFolder == null)
return true;
// Retrieve the task to be deleted
var task = taskFolder.Tasks.Exists(taskName) ? taskFolder.Tasks[taskName] : null;
if (task == null)
return true;
try
{
// Delete the task
taskFolder.DeleteTask(taskName, false);
return true;
}
catch (Exception ex)
{
_logger.Error($"{nameof(ScheduleAutoUpdate)} - Unable to delete the ScheduleAutoUpdate task. {ex.Message}\r\n{ex.StackTrace}");
}
}
return false;
}
public static void SetAutoBackupState(string taskKey, string taskSuffix, bool? enable)
{
var taskName = GetScheduledTaskName(TaskType.AutoBackup, taskKey, taskSuffix);
var taskFolder = TaskService.Instance.RootFolder.SubFolders.Exists(TaskFolder) ? TaskService.Instance.RootFolder.SubFolders[TaskFolder] : null;
if (taskFolder == null)
return;
var task = taskFolder.Tasks.Exists(taskName) ? taskFolder.Tasks[taskName] : null;
if (task == null)
return;
if (task.State == TaskState.Disabled || task.State == TaskState.Ready)
{
task.Definition.Settings.Enabled = enable ?? !task.Enabled;
task.RegisterChanges();
}
}
public static void SetAutoUpdateState(string taskKey, string taskSuffix, bool? enable)
{
var taskName = GetScheduledTaskName(TaskType.AutoUpdate, taskKey, taskSuffix);
var taskFolder = TaskService.Instance.RootFolder.SubFolders.Exists(TaskFolder) ? TaskService.Instance.RootFolder.SubFolders[TaskFolder] : null;
if (taskFolder == null)
return;
var task = taskFolder.Tasks.Exists(taskName) ? taskFolder.Tasks[taskName] : null;
if (task == null)
return;
if (task.State == TaskState.Disabled || task.State == TaskState.Ready)
{
task.Definition.Settings.Enabled = enable ?? !task.Enabled;
task.RegisterChanges();
}
}
public static TaskState TaskStateAutoBackup(string taskKey, string taskSuffix, out DateTime nextRunTime)
{
nextRunTime = DateTime.MinValue;
var taskName = GetScheduledTaskName(TaskType.AutoBackup, taskKey, taskSuffix);
var taskFolder = TaskService.Instance.RootFolder.SubFolders.Exists(TaskFolder) ? TaskService.Instance.RootFolder.SubFolders[TaskFolder] : null;
if (taskFolder == null)
return TaskState.Unknown;
var task = taskFolder.Tasks.Exists(taskName) ? taskFolder.Tasks[taskName] : null;
if (task == null)
return TaskState.Unknown;
nextRunTime = task.NextRunTime;
return task.State;
}
public static TaskState TaskStateAutoUpdate(string taskKey, string taskSuffix, out DateTime nextRunTime)
{
nextRunTime = DateTime.MinValue;
var taskName = GetScheduledTaskName(TaskType.AutoUpdate, taskKey, taskSuffix);
var taskFolder = TaskService.Instance.RootFolder.SubFolders.Exists(TaskFolder) ? TaskService.Instance.RootFolder.SubFolders[TaskFolder] : null;
if (taskFolder == null)
return TaskState.Unknown;
var task = taskFolder.Tasks.Exists(taskName) ? taskFolder.Tasks[taskName] : null;
if (task == null)
return TaskState.Unknown;
nextRunTime = task.NextRunTime;
return task.State;
}
}
}

View file

@ -0,0 +1,60 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
namespace ServerManagerTool.Common.Utils
{
public static class TaskUtils
{
public static void DoNotWait(this Task task)
{
// Do nothing, let the task continue. Eliminates compiler warning about non-awaited tasks in an async method.
}
public static async Task RunOnUIThreadAsync(Action action)
{
var app = Application.Current;
if (app != null)
{
await app.Dispatcher.InvokeAsync(action);
}
}
public static readonly Task FinishedTask = Task.FromResult(true);
public static async Task TimeoutAfterAsync(this Task task, int millisecondsDelay)
{
using (var timeoutCancellationTokenSource = new CancellationTokenSource())
{
var completedTask = await Task.WhenAny(task, Task.Delay(millisecondsDelay, timeoutCancellationTokenSource.Token));
if (completedTask == task)
{
timeoutCancellationTokenSource.Cancel();
await task; // Very important in order to propagate exceptions
}
else
{
throw new TimeoutException("The operation has timed out.");
}
}
}
public static async Task<TResult> TimeoutAfterAsync<TResult>(this Task<TResult> task, int millisecondsDelay)
{
using (var timeoutCancellationTokenSource = new CancellationTokenSource())
{
var completedTask = await Task.WhenAny(task, Task.Delay(millisecondsDelay, timeoutCancellationTokenSource.Token));
if (completedTask == task)
{
timeoutCancellationTokenSource.Cancel();
return await task; // Very important in order to propagate exceptions
}
else
{
throw new TimeoutException("The operation has timed out.");
}
}
}
}
}

View file

@ -0,0 +1,54 @@
using ServerManagerTool.Common.Model;
using System;
using System.ServiceModel.Syndication;
using System.Xml;
namespace ServerManagerTool.Common.Utils
{
public static class VersionFeedUtils
{
public static VersionFeed LoadVersionFeed(string inputUri, string currentVersion)
{
try
{
var reader = XmlReader.Create(inputUri);
var feed = SyndicationFeed.Load(reader);
var versionFeed = new VersionFeed
{
Id = feed.Id,
Title = feed.Title?.Text,
SubTitle = feed.Description?.Text,
Link = feed.Links?[0].Uri,
Updated = feed.LastUpdatedTime.ToLocalTime(),
};
//Loop through all items in the SyndicationFeed
foreach (var item in feed.Items)
{
var textContent = item.Content as TextSyndicationContent;
var versionFeedEntry = new VersionFeedEntry
{
Id = item.Id,
Title = item.Title?.Text,
Summary = item.Summary?.Text,
Link = item.Links?[0].Uri,
Updated = item.LastUpdatedTime.ToLocalTime(),
Content = textContent?.Text,
Author = item.Authors?[0].Name,
IsCurrent = (item.Summary?.Text ?? string.Empty).Equals(currentVersion),
};
versionFeed.Entries.Add(versionFeedEntry);
}
return versionFeed;
}
catch (Exception)
{
return new VersionFeed();
}
}
}
}

View file

@ -0,0 +1,28 @@
using System;
using System.IO;
namespace ServerManagerTool.Common.Utils
{
public static class VersionUtils
{
public static Version GetVersionFromFile(string versionFile)
{
if (!string.IsNullOrWhiteSpace(versionFile) && File.Exists(versionFile))
{
var fileValue = File.ReadAllText(versionFile);
if (!string.IsNullOrWhiteSpace(fileValue))
{
string versionString = fileValue.ToString();
if (versionString.IndexOf('.') == -1)
versionString = versionString + ".0";
if (Version.TryParse(versionString, out Version version))
return version;
}
}
return new Version(0, 0);
}
}
}

View file

@ -0,0 +1,122 @@
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
namespace ServerManagerTool.Common.Utils
{
public static class WindowUtils
{
public static void RemoveDefaultResourceDictionary(Window window, string defaultDictionary)
{
if (window == null)
return;
var dictToRemove = window.Resources.MergedDictionaries.FirstOrDefault(d => d.Source.OriginalString.Contains(defaultDictionary));
if (dictToRemove != null)
{
window.Resources.MergedDictionaries.Remove(dictToRemove);
}
}
public static void RemoveDefaultResourceDictionary(UserControl control, string defaultDictionary)
{
if (control == null)
return;
var dictToRemove = control.Resources.MergedDictionaries.FirstOrDefault(d => d.Source.OriginalString.Contains(defaultDictionary));
if (dictToRemove != null)
{
control.Resources.MergedDictionaries.Remove(dictToRemove);
}
}
/// <summary>
/// Finds a parent of a given item on the visual tree.
/// </summary>
/// <typeparam name="T">The type of the queried item.</typeparam>
/// <param name="child">A direct or indirect child of the queried item.</param>
/// <returns>The first parent item that matches the submitted type parameter. If not matching item can be found, a null reference is being returned.</returns>
public static T TryFindParent<T>(DependencyObject child)
where T : DependencyObject
{
//get parent item
DependencyObject parentObject = GetParentObject(child);
//we've reached the end of the tree
if (parentObject == null) return null;
//check if the parent matches the type we're looking for
T parent = parentObject as T;
if (parent != null)
return parent;
//use recursion to proceed with next level
return TryFindParent<T>(parentObject);
}
/// <summary>
/// This method is an alternative to WPF's <see cref="VisualTreeHelper.GetParent"/> method, which also supports content elements.
/// Do note, that for content element, this method falls back to the logical tree of the element.
/// </summary>
/// <param name="child">The item to be processed.</param>
/// <returns>The submitted item's parent, if available. Otherwise null.</returns>
public static DependencyObject GetParentObject(DependencyObject child)
{
if (child == null) return null;
var contentElement = child as ContentElement;
if (contentElement != null)
{
var parent = ContentOperations.GetParent(contentElement);
if (parent != null) return parent;
var fce = contentElement as FrameworkContentElement;
return fce?.Parent;
}
//if it's not a ContentElement, rely on VisualTreeHelper
return VisualTreeHelper.GetParent(child);
}
/// <summary>
/// Recursively processes a given dependency object and all its children, and updates sources of all objects that use a binding expression on a given property.
/// </summary>
/// <param name="obj">The dependency object that marks a starting point. This could be a dialog window or a panel control that hosts bound controls.</param>
/// <param name="properties">The properties to be updated if
/// <paramref name="obj"/> or one of its childs provide it along with a binding expression.</param>
public static void UpdateBindingSources(DependencyObject obj, params DependencyProperty[] properties)
{
foreach (var depProperty in properties)
{
//check whether the submitted object provides a bound property that matches the property parameters
var be = BindingOperations.GetBindingExpression(obj, depProperty);
be?.UpdateSource();
}
int count = VisualTreeHelper.GetChildrenCount(obj);
for (int i = 0; i < count; i++)
{
//process child items recursively
var childObject = VisualTreeHelper.GetChild(obj, i);
UpdateBindingSources(childObject, properties);
}
}
/// <summary>
/// Tries to locate a given item within the visual tree, starting with the dependency object at a given position.
/// </summary>
/// <typeparam name="T">The type of the element to be found on the visual tree of the element at the given location.</typeparam>
/// <param name="reference">The main element which is used to perform hit testing.</param>
/// <param name="point">The position to be evaluated on the origin.</param>
public static T TryFindFromPoint<T>(UIElement reference, Point point)
where T : DependencyObject
{
var element = reference.InputHitTest(point) as DependencyObject;
if (element == null) return null;
if (element is T) return (T)element;
return TryFindParent<T>(element);
}
}
}

View file

@ -0,0 +1,182 @@
using Ionic.Zip;
using System;
using System.IO;
using System.Linq;
namespace ServerManagerTool.Common.Utils
{
public static class ZipUtils
{
public static bool DoesFileExist(string zipFile, string entryName)
{
if (string.IsNullOrWhiteSpace(zipFile))
throw new ArgumentNullException(nameof(zipFile));
if (string.IsNullOrWhiteSpace(entryName))
throw new ArgumentNullException(nameof(entryName));
if (!File.Exists(zipFile))
throw new FileNotFoundException();
using (var zip = ZipFile.Read(zipFile))
{
return zip.Entries.Any(e => Path.GetFileName(e.FileName).Equals(entryName, StringComparison.OrdinalIgnoreCase));
}
}
public static int ExtractAFile(string zipFile, string entryName, string destinationPath)
{
if (string.IsNullOrWhiteSpace(zipFile))
throw new ArgumentNullException(nameof(zipFile));
if (string.IsNullOrWhiteSpace(entryName))
throw new ArgumentNullException(nameof(entryName));
if (string.IsNullOrWhiteSpace(destinationPath))
throw new ArgumentNullException(nameof(destinationPath));
if (!File.Exists(zipFile))
throw new FileNotFoundException();
if (!Directory.Exists(destinationPath))
Directory.CreateDirectory(destinationPath);
using (var zip = ZipFile.Read(zipFile))
{
var selection = zip.Entries.Where(e => Path.GetFileName(e.FileName).Equals(entryName, StringComparison.OrdinalIgnoreCase));
foreach (var entry in selection)
{
entry.Extract(destinationPath, ExtractExistingFileAction.OverwriteSilently);
}
return selection.Count();
}
}
public static int ExtractAllFiles(string zipFile, string destinationPath)
{
if (string.IsNullOrWhiteSpace(zipFile))
throw new ArgumentNullException(nameof(zipFile));
if (string.IsNullOrWhiteSpace(destinationPath))
throw new ArgumentNullException(nameof(destinationPath));
if (!Directory.Exists(destinationPath))
Directory.CreateDirectory(destinationPath);
using (var zip = ZipFile.Read(zipFile))
{
zip.ExtractAll(destinationPath, ExtractExistingFileAction.OverwriteSilently);
return zip.Entries.Count;
}
}
public static void UpdateFiles(string zipFile, string[] filesToZip, string comment = "", bool preserveDirHierarchy = true, string directoryPathInArchive = "")
{
if (string.IsNullOrWhiteSpace(zipFile))
throw new ArgumentNullException(nameof(zipFile));
if (filesToZip == null || filesToZip.Length == 0)
return;
if (!File.Exists(zipFile))
{
ZipFiles(zipFile, filesToZip, comment, preserveDirHierarchy, directoryPathInArchive);
}
else
{
using (var zip = ZipFile.Read(zipFile))
{
zip.AddFiles(filesToZip.Where(f => !string.IsNullOrWhiteSpace(f) && File.Exists(f)), preserveDirHierarchy, directoryPathInArchive);
if (!string.IsNullOrWhiteSpace(comment))
zip.Comment = comment;
zip.Save();
}
}
}
public static void ZipAFile(string zipFile, string entryName, string content)
{
if (string.IsNullOrWhiteSpace(zipFile))
throw new ArgumentNullException(nameof(zipFile));
if (string.IsNullOrWhiteSpace(entryName))
throw new ArgumentNullException(nameof(entryName));
if (string.IsNullOrWhiteSpace(content))
throw new ArgumentNullException(nameof(content));
if (!File.Exists(zipFile))
{
using (var zip = new ZipFile())
{
zip.AddEntry(entryName, content);
zip.CompressionLevel = Ionic.Zlib.CompressionLevel.Default;
zip.Save(zipFile);
}
}
else
{
using (var zip = ZipFile.Read(zipFile))
{
zip.AddEntry(entryName, content);
zip.Save();
}
}
}
public static void ZipAFile(string zipFile, string entryName, string content, string comment)
{
if (string.IsNullOrWhiteSpace(zipFile))
throw new ArgumentNullException(nameof(zipFile));
if (string.IsNullOrWhiteSpace(entryName))
throw new ArgumentNullException(nameof(entryName));
if (string.IsNullOrWhiteSpace(content))
throw new ArgumentNullException(nameof(content));
if (!File.Exists(zipFile))
{
using (var zip = new ZipFile())
{
zip.AddEntry(entryName, File.ReadAllBytes(content));
zip.CompressionLevel = Ionic.Zlib.CompressionLevel.Default;
if (!string.IsNullOrWhiteSpace(comment))
zip.Comment = comment;
zip.Save(zipFile);
}
}
else
{
using (var zip = ZipFile.Read(zipFile))
{
zip.AddEntry(entryName, File.ReadAllBytes(content));
if (!string.IsNullOrWhiteSpace(comment))
zip.Comment = comment;
zip.Save();
}
}
}
public static void ZipFiles(string zipFile, string[] filesToZip, string comment = "", bool preserveDirHierarchy = true, string directoryPathInArchive = "")
{
if (string.IsNullOrWhiteSpace(zipFile))
throw new ArgumentNullException(nameof(zipFile));
if (filesToZip == null || filesToZip.Length == 0)
throw new ArgumentNullException(nameof(filesToZip));
using (var zip = new ZipFile(zipFile))
{
zip.AddFiles(filesToZip.Where(f => !string.IsNullOrWhiteSpace(f) && File.Exists(f)), preserveDirHierarchy, directoryPathInArchive);
zip.CompressionLevel = Ionic.Zlib.CompressionLevel.Default;
if (!string.IsNullOrWhiteSpace(comment))
zip.Comment = comment;
zip.Save();
}
}
}
}