//****************************************************************************************************** // Common.cs - Gbtc // // Copyright © 2012, Grid Protection Alliance. All Rights Reserved. // // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See // the NOTICE file distributed with this work for additional information regarding copyright ownership. // The GPA licenses this file to you under the MIT License (MIT), the "License"; you may // not use this file except in compliance with the License. You may obtain a copy of the License at: // // http://www.opensource.org/licenses/MIT // // Unless agreed to in writing, the subject software distributed under the License is distributed on an // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the // License for the specific language governing permissions and limitations. // // Code Modification History: // ---------------------------------------------------------------------------------------------------- // 04/03/2006 - J. Ritchie Carroll // Generated original version of source code. // 12/13/2007 - Darrell Zuercher // Edited code comments. // 09/08/2008 - J. Ritchie Carroll // Converted to C#. // 02/13/2009 - Josh L. Patterson // Edited Code Comments. // 09/14/2009 - Stephen C. Wills // Added new header and license agreement. // 09/17/2009 - Pinal C. Patel // Modified GetApplicationType() to remove dependency on HttpContext.Current. // 09/28/2010 - Pinal C. Patel // Cached the current ApplicationType returned by GetApplicationType() for better performance. // 12/05/2010 - Pinal C. Patel // Added an overload for TypeConvertToString() that takes CultureInfo as a parameter. // 12/07/2010 - Pinal C. Patel // Updated TypeConvertToString() to return an empty string if the passed in value is null. // 03/09/2011 - Pinal C. Patel // Moved UpdateType enumeration from GSF.Services.ServiceProcess namespace for broader usage. // 04/07/2011 - J. Ritchie Carroll // Added ToNonNullNorEmptyString() and ToNonNullNorWhiteSpace() extensions. // 12/14/2012 - Starlynn Danyelle Gilliam // Modified Header. // //****************************************************************************************************** using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Web.Hosting; using GSF.Collections; using GSF.Console; using GSF.Interop; using GSF.IO; using GSF.Reflection; using GSF.Units; using Microsoft.Win32; namespace GSF { #region [ Enumerations ] /// /// Specifies the type of the application. /// public enum ApplicationType { /// /// Application is of unknown type. /// Unknown = 0, /// /// Application doesn't require a subsystem. /// Native = 1, /// /// Application runs in the Windows GUI subsystem. /// WindowsGui = 2, /// /// Application runs in the Windows character subsystem. /// WindowsCui = 3, /// /// Application runs in the OS/2 character subsystem. /// OS2Cui = 5, /// /// Application runs in the POSIX character subsystem. /// PosixCui = 7, /// /// Application is a native Win9x driver. /// NativeWindows = 8, /// /// Application runs in the Windows CE subsystem. /// WindowsCEGui = 9, /// /// The application is a web site or web application. /// Web = 100 } /// /// Indicates the type of update. /// public enum UpdateType { /// /// Update is informational. /// Information, /// /// Update is a warning. /// Warning, /// /// Update is an alarm. /// Alarm } #endregion // This is the location for handy miscellaneous functions that are difficult to categorize elsewhere. For the most // part these functions may have the most value in a Visual Basic application which supports importing functions // down to a class level, e.g.: Imports GSF.Common /// /// Defines common global functions. /// public static partial class Common { private static ApplicationType? s_applicationType; private static string s_osPlatformName; private static PlatformID s_osPlatformID = PlatformID.Win32S; /// /// Gets the type of the currently executing application. /// /// One of the values. public static ApplicationType GetApplicationType() { if (s_applicationType.HasValue) return s_applicationType.Value; if (HostingEnvironment.IsHosted) { s_applicationType = ApplicationType.Web; } else { try { // References: // - http://support.microsoft.com/kb/65122 // - http://support.microsoft.com/kb/90493/en-us // - http://www.codeguru.com/cpp/w-p/system/misc/article.php/c2897/ // We will always have an entry assembly for windows application. FileStream exe = new FileStream(AssemblyInfo.EntryAssembly.Location, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); byte[] dosHeader = new byte[64]; byte[] exeHeader = new byte[248]; byte[] subSystem = new byte[2]; exe.Read(dosHeader, 0, dosHeader.Length); exe.Seek(BitConverter.ToInt16(dosHeader, 60), SeekOrigin.Begin); exe.Read(exeHeader, 0, exeHeader.Length); exe.Close(); Buffer.BlockCopy(exeHeader, 92, subSystem, 0, 2); s_applicationType = ((ApplicationType)(LittleEndian.ToInt16(subSystem, 0))); } catch { // We are unable to determine the application type. s_applicationType = ApplicationType.Unknown; } } return s_applicationType.Value; } /// /// Gets the operating system /// /// The operating system . /// /// This function will properly detect the platform ID, even if running on Mac. /// public static PlatformID GetOSPlatformID() { if (s_osPlatformID != PlatformID.Win32S) return s_osPlatformID; s_osPlatformID = Environment.OSVersion.Platform; if (s_osPlatformID == PlatformID.Unix) { // Environment.OSVersion.Platform can report Unix when running on Mac OS X try { s_osPlatformID = Command.Execute("uname").StandardOutput.StartsWith("Darwin", StringComparison.OrdinalIgnoreCase) ? PlatformID.MacOSX : PlatformID.Unix; } catch { // Fall back on looking for Mac specific root folders: if (Directory.Exists("/Applications") && Directory.Exists("/System") && Directory.Exists("/Users") && Directory.Exists("/Volumes")) s_osPlatformID = PlatformID.MacOSX; } } return s_osPlatformID; } /// /// Gets the operating system product name. /// /// Operating system product name. public static string GetOSProductName() { if ((object)s_osPlatformName != null) return s_osPlatformName; switch (GetOSPlatformID()) { case PlatformID.Unix: case PlatformID.MacOSX: // Call sw_vers on Mac to get product name and version information, Linux could have this try { string output = Command.Execute("sw_vers").StandardOutput; Dictionary kvps = output.ParseKeyValuePairs('\n', ':'); if (kvps.Count > 0) s_osPlatformName = kvps.Values.Select(val => val.Trim()).ToDelimitedString(" "); } catch { s_osPlatformName = null; } if (string.IsNullOrEmpty(s_osPlatformName)) { // Try some common ways to get product name on Linux, some might work on Mac try { foreach (string fileName in FilePath.GetFileList("/etc/*release*")) { using (StreamReader reader = new StreamReader(fileName)) { string line = reader.ReadLine(); while ((object)line != null) { if (line.StartsWith("PRETTY_NAME", StringComparison.OrdinalIgnoreCase) && !line.Contains('#')) { string[] parts = line.Split('='); if (parts.Length == 2) { s_osPlatformName = parts[1].Replace("\"", ""); break; } } line = reader.ReadLine(); } } if (!string.IsNullOrEmpty(s_osPlatformName)) break; } } catch { try { string output = Command.Execute("lsb_release", "-a").StandardOutput; Dictionary kvps = output.ParseKeyValuePairs('\n', ':'); if (kvps.TryGetValue("Description", out s_osPlatformName) && !string.IsNullOrEmpty(s_osPlatformName)) s_osPlatformName = s_osPlatformName.Trim(); } catch { s_osPlatformName = null; } } } break; default: // Get Windows product name try { s_osPlatformName = Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductName", null).ToString(); } catch { s_osPlatformName = null; } break; } if (string.IsNullOrWhiteSpace(s_osPlatformName)) s_osPlatformName = GetOSPlatformID().ToString(); if (IsMono) s_osPlatformName += " using Mono"; return s_osPlatformName; } /// /// Gets the memory usage by the current process. /// /// Memory usage by the current process. public static long GetProcessMemory() { long processMemory = Environment.WorkingSet; if (processMemory == 0 && IsPosixEnvironment) { try { double percentOfTotal; ulong totalMemory = GetTotalPhysicalMemory(); //using (PerformanceCounter counter = new PerformanceCounter("Mono Memory", "Total Physical Memory")) // totalMemory = counter.RawValue; // Get percent of total memory used by current process string output = Command.Execute("ps", $"-p {Process.GetCurrentProcess().Id} -o %mem").StandardOutput; string[] lines = output.Split('\n'); if (lines.Length > 1 && double.TryParse(lines[1].Trim(), out percentOfTotal)) processMemory = (long)Math.Round(percentOfTotal / 100.0D * totalMemory); } catch { processMemory = -1; } } return processMemory; } /// /// Gets the total physical system memory. /// /// Total physical system memory. public static ulong GetTotalPhysicalMemory() { if (IsPosixEnvironment) { string output = Command.Execute("awk", "'/MemTotal/ {print $2}' /proc/meminfo").StandardOutput; return ulong.Parse(output) * SI2.Kilo; } WindowsApi.MEMORYSTATUSEX memStatus = new WindowsApi.MEMORYSTATUSEX(); return WindowsApi.GlobalMemoryStatusEx(memStatus) ? memStatus.ullTotalPhys : 0; } /// /// Gets the available physical system memory. /// /// Total available system memory. public static ulong GetAvailablePhysicalMemory() { if (IsPosixEnvironment) { string output = Command.Execute("awk", "'/MemAvailable/ {print $2}' /proc/meminfo").StandardOutput; return ulong.Parse(output) * SI2.Kilo; } WindowsApi.MEMORYSTATUSEX memStatus = new WindowsApi.MEMORYSTATUSEX(); return WindowsApi.GlobalMemoryStatusEx(memStatus) ? memStatus.ullAvailPhys : 0; } #region [ Old Code ] ///// Returns the smallest item from a list of parameters. ///// A variable number of parameters of type ///// Result is the minimum value of type in the . //public static object Min(params object[] itemList) //{ // return itemList.Min(CompareObjects); //} ///// Returns the largest item from a list of parameters. ///// A variable number of parameters of type ///// Result is the maximum value of type in the . //public static object Max(params object[] itemList) //{ // return itemList.Max(CompareObjects); //} ///// Compares two elements of any type. ///// Object which is compared to object . ///// Object which is compared against. ///// Result of comparison as an . //public static int CompareObjects(object x, object y) //{ // // Just using Visual Basic runtime to compare two objects of unknown types - this can be a very // // complex process and the VB runtime library is distributed with .NET anyway, so why not use it: // // Note that comparison is based on VB object comparison rules: // // ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStudio.v80.en/dv_vbalr/html/d6cb12a8-e52e-46a7-8aaf-f804d634a825.htm // return (Microsoft.VisualBasic.CompilerServices.Operators.ConditionalCompareObjectLess(x, y, false) ? -1 : // (Microsoft.VisualBasic.CompilerServices.Operators.ConditionalCompareObjectGreater(x, y, false) ? 1 : 0)); //} // This function is probably not that useful ///// Time zone names enumeration used to look up desired time zone in GetWin32TimeZone function. //public enum TimeZoneName //{ // DaylightName, // DisplayName, // StandardName //} ///// Returns the specified Win32 time zone, using specified name. ///// Value of name used for time zone lookup. ///// Type of name used for time zone lookup. //public static TimeZoneInfo GetTimeZone(string name, TimeZoneName lookupBy) //{ // foreach (TimeZoneInfo timeZone in TimeZoneInfo.GetSystemTimeZones()) // { // if (lookupBy == TimeZoneName.DaylightName) // { // if (string.Compare(timeZone.DaylightName, name, true) == 0) // return timeZone; // } // else if (lookupBy == TimeZoneName.DisplayName) // { // if (string.Compare(timeZone.DisplayName, name, true) == 0) // return timeZone; // } // else if (lookupBy == TimeZoneName.StandardName) // { // if (string.Compare(timeZone.StandardName, name, true) == 0) // return timeZone; // } // } // throw new ArgumentException("Windows time zone with " + lookupBy + " of \"" + name + "\" was not found!"); //} #endregion } }