using Unosquare.Swan.Components; using System; using System.IO; using System.Threading; using Unosquare.Swan.Reflection; #if !NETSTANDARD1_3 using System.Reflection; #endif namespace Unosquare.Swan { /// /// Provides utility methods to retrieve information about the current application. /// #if !NETSTANDARD1_3 public class Runtime : MarshalByRefObject #else public static class Runtime #endif { private static readonly Lazy _propertyTypeCache = new Lazy(() => new PropertyTypeCache()); private static readonly Lazy _attributeCache = new Lazy(() => new AttributeCache()); private static readonly Lazy _objectValidator = new Lazy(() => new ObjectValidator()); private static readonly Lazy _fieldTypeCache = new Lazy(() => new FieldTypeCache()); private static readonly Lazy _methodInfoCache = new Lazy(() => new MethodInfoCache()); #if NET452 private static readonly Lazy EntryAssemblyLazy = new Lazy(() => Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly()); #endif #if NETSTANDARD2_0 private static readonly Lazy EntryAssemblyLazy = new Lazy(Assembly.GetEntryAssembly); #endif #if NET452 private static readonly Lazy ProcessLazy = new Lazy(System.Diagnostics.Process.GetCurrentProcess); #endif #if !NETSTANDARD1_3 private static readonly Lazy CompanyNameLazy = new Lazy(() => { AssemblyCompanyAttribute attribute = EntryAssembly.GetCustomAttribute(typeof(AssemblyCompanyAttribute)) as AssemblyCompanyAttribute; return attribute?.Company ?? String.Empty; }); private static readonly Lazy ProductNameLazy = new Lazy(() => { AssemblyProductAttribute attribute = EntryAssembly.GetCustomAttribute(typeof(AssemblyProductAttribute)) as AssemblyProductAttribute; return attribute?.Product ?? String.Empty; }); private static readonly Lazy ProductTrademarkLazy = new Lazy(() => { AssemblyTrademarkAttribute attribute = EntryAssembly.GetCustomAttribute(typeof(AssemblyTrademarkAttribute)) as AssemblyTrademarkAttribute; return attribute?.Trademark ?? String.Empty; }); #endif private static readonly Lazy _argumentParser = new Lazy(() => new ArgumentParser()); private static readonly Lazy _objectMapper = new Lazy(() => new ObjectMapper()); #if !NETSTANDARD1_3 private static readonly String ApplicationMutexName = "Global\\{{" + EntryAssembly.FullName + "}}"; #else private const string ApplicationMutexName = "Global\\{{SWANINSTANCE}}"; #endif private static readonly Object SyncLock = new Object(); private static OperatingSystem? _oS; #region Properties /// /// Gets the current Operating System. /// /// /// The os. /// public static OperatingSystem OS { get { if(_oS.HasValue == false) { String windowsDirectory = Environment.GetEnvironmentVariable("windir"); _oS = String.IsNullOrEmpty(windowsDirectory) == false && windowsDirectory.Contains(@"\") && Directory.Exists(windowsDirectory) ? (OperatingSystem?)OperatingSystem.Windows : (OperatingSystem?)(File.Exists(@"/proc/sys/kernel/ostype") ? OperatingSystem.Unix : OperatingSystem.Osx); } return _oS ?? OperatingSystem.Unknown; } } #if NET452 /// /// Gets the process associated with the current application. /// /// /// The process. /// public static System.Diagnostics.Process Process => ProcessLazy.Value; #endif /// /// Checks if this application (including version number) is the only instance currently running. /// /// /// true if this instance is the only instance; otherwise, false. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Codequalität", "IDE0067:Objekte verwerfen, bevor Bereich verloren geht", Justification = "")] public static Boolean IsTheOnlyInstance { get { lock(SyncLock) { try { // Try to open existing mutex. _ = Mutex.OpenExisting(ApplicationMutexName); } catch { try { // If exception occurred, there is no such mutex. Mutex appMutex = new Mutex(true, ApplicationMutexName); $"Application Mutex created {appMutex} named '{ApplicationMutexName}'".Debug( typeof(Runtime)); // Only one instance. return true; } catch { // Sometimes the user can't create the Global Mutex } } // More than one instance. return false; } } } /// /// Gets a value indicating whether this application instance is using the MONO runtime. /// /// /// true if this instance is using MONO runtime; otherwise, false. /// public static Boolean IsUsingMonoRuntime => Type.GetType("Mono.Runtime") != null; /// /// Gets the property type cache. /// /// /// The property type cache. /// public static PropertyTypeCache PropertyTypeCache => _propertyTypeCache.Value; /// /// Gets the attribute cache. /// /// /// The attribute cache. /// public static AttributeCache AttributeCache => _attributeCache.Value; /// /// Gets the object validator. /// /// /// The object validator. /// public static ObjectValidator ObjectValidator => _objectValidator.Value; /// /// Gets the field type cache. /// /// /// The field type cache. /// public static FieldTypeCache FieldTypeCache => _fieldTypeCache.Value; /// /// Gets the method information cache. /// /// /// The method information cache. /// public static MethodInfoCache MethodInfoCache => _methodInfoCache.Value; #if !NETSTANDARD1_3 /// /// Gets the assembly that started the application. /// /// /// The entry assembly. /// public static Assembly EntryAssembly => EntryAssemblyLazy.Value; /// /// Gets the name of the entry assembly. /// /// /// The name of the entry assembly. /// public static AssemblyName EntryAssemblyName => EntryAssemblyLazy.Value.GetName(); /// /// Gets the entry assembly version. /// public static Version EntryAssemblyVersion => EntryAssemblyName.Version; /// /// Gets the full path to the folder containing the assembly that started the application. /// /// /// The entry assembly directory. /// public static String EntryAssemblyDirectory { get { UriBuilder uri = new UriBuilder(EntryAssembly.CodeBase); String path = Uri.UnescapeDataString(uri.Path); return Path.GetDirectoryName(path); } } /// /// Gets the name of the company. /// /// /// The name of the company. /// public static String CompanyName => CompanyNameLazy.Value; /// /// Gets the name of the product. /// /// /// The name of the product. /// public static String ProductName => ProductNameLazy.Value; /// /// Gets the trademark. /// /// /// The product trademark. /// public static String ProductTrademark => ProductTrademarkLazy.Value; #endif /// /// Gets a local storage path with a version. /// /// /// The local storage path. /// public static String LocalStoragePath { get { #if !NETSTANDARD1_3 String localAppDataPath = #if NET452 Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), EntryAssemblyName.Name); #else Path.GetDirectoryName(EntryAssembly.Location); #endif String returnPath = Path.Combine(localAppDataPath, EntryAssemblyVersion.ToString()); #else var returnPath = Directory.GetCurrentDirectory(); // Use current path... #endif if(Directory.Exists(returnPath) == false) { Directory.CreateDirectory(returnPath); } return returnPath; } } /// /// Gets the singleton instance created with basic defaults. /// /// /// The argument parser. /// public static ArgumentParser ArgumentParser => _argumentParser.Value; /// /// Gets the object mapper instance created with basic defaults. /// /// /// The object mapper. /// public static ObjectMapper ObjectMapper => _objectMapper.Value; #endregion #region Methods #if !NETSTANDARD1_3 /// /// Writes a standard banner to the standard output /// containing the company name, product name, assembly version and trademark. /// /// The color. public static void WriteWelcomeBanner(ConsoleColor color = ConsoleColor.Gray) { $"{CompanyName} {ProductName} [Version {EntryAssemblyVersion}]".WriteLine(color); $"{ProductTrademark}".WriteLine(color); } /// /// Gets all the loaded assemblies in the current application domain. /// /// An array of assemblies. public static Assembly[] GetAssemblies() => AppDomain.CurrentDomain.GetAssemblies(); /// /// Build a full path pointing to the current user's desktop with the given filename. /// /// The filename. /// /// The fully qualified location of path, such as "C:\MyFile.txt". /// /// filename. public static String GetDesktopFilePath(String filename) { if(String.IsNullOrWhiteSpace(filename)) { throw new ArgumentNullException(nameof(filename)); } String pathWithFilename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), filename); return Path.GetFullPath(pathWithFilename); } #endif #endregion } }