Newer
Older
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management;
using NLog;
{
public static class SystemChecks
{
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
/// <summary>
/// Get the available physical memory in MB.
/// </summary>
/// <returns>Available physical memory in MB or -1 in case of an error.</returns>
public static long GetFreeMemory() {
try {
var searcher =
new ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem");
foreach (var mo in searcher.Get()) {
var queryObj = (ManagementObject)mo;
return Convert.ToInt64(queryObj["FreePhysicalMemory"]) / 1024;
}
}
catch (Exception ex) {
Log.Trace("Error in GetFreeMemory: {0}", ex.Message);
return -1;
}
/// <summary>
/// Get the CPU usage in percent over all cores.
/// </summary>
/// <returns>CPU usage in percent or -1 if an error occured.</returns>
public static int GetCpuUsage() {
Log.Trace("Querying WMI for CPU load...");
var searcher = new ManagementObjectSearcher("select * from Win32_PerfFormattedData_PerfOS_Processor");
Int32 usageInt32 = -1;
/*
var managementObjects = searcher.Get();
Log.Trace("WMI query returned {0} objects.", managementObjects.Count);
foreach (var mo in managementObjects) {
var obj = (ManagementObject)mo;
var usage = obj["PercentProcessorTime"];
var name = obj["Name"];
usageInt32 = Convert.ToInt32(usage);
Log.Trace("CPU usage {1}: {0}", usageInt32, name);
if (name.ToString().Equals("_Total")) {
usageInt32 = Convert.ToInt32(usage);
Log.Trace("CPU usage: {0}", usageInt32);
}
return usageInt32;
*/
var cpuTimes = searcher.Get()
.Cast<ManagementObject>()
.Select(mo => new {
Name = mo["Name"],
Usage = mo["PercentProcessorTime"]
}
)
.ToList();
if (cpuTimes.Count == 0)
return -1;
Log.Trace("WMI query returned {0} objects.", cpuTimes.Count);
// The '_Total' value represents the average usage across all cores,
// and is the best representation of overall CPU usage
var query = cpuTimes.Where(x => x.Name.ToString() == "_Total").Select(x => x.Usage);
var cpuUsage = query.SingleOrDefault();
usageInt32 = Convert.ToInt32(cpuUsage);
Log.Trace("CPU usage: {0}", usageInt32);
return usageInt32;
// */
}
catch (Exception ex) {
Log.Trace("Error in GetCpuUsage: {0}", ex.Message);
Log.Trace("Failed querying CPU usage!");
return -1;
}
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/// <summary>
/// Validate the WMI query methods work correctly and create a summary or warning message.
/// </summary>
/// <returns>A summary with current readings from WMI or a warning message.</returns>
public static string WmiSummary() {
var failed = new List<string>();
var load = GetCpuUsage();
var free = GetFreeMemory();
var summary = $"CPU load: {load}\n" +
$"Free system memory: {Conv.MegabytesToString(free)}\n";
Log.Warn(summary);
if (load == -1) {
failed.Add("CPU load");
}
if (free == -1) {
failed.Add("free RAM");
}
if (failed.Count > 0) {
summary = "*******************************************************\n" +
"WARNING: Checking system parameters via WMI failed for:\n";
foreach (var property in failed) {
summary += $" - {property}\n";
}
summary += "\n" +
"-------------------------------------------------------\n" +
"Limits configured for these properties will be IGNORED!\n" +
"-------------------------------------------------------\n\n";
Log.Error(summary);
}
return summary;
}
/// <summary>
/// Get the free space of a drive in bytes.
/// </summary>
/// /// <param name="drive">The drive name, e.g. "c:".</param>
/// <returns>Free space of a drive in bytes, zero if an error occured.</returns>
public static long GetFreeDriveSpace(string drive) {
try {
var dInfo = new DriveInfo(drive);
return dInfo.TotalFreeSpace;
}
catch (Exception ex) {
// log this as an error which then also gets sent via email (if configured) and
// let the rate-limiter take care of not flooding the admin with mails:
Log.Error("Error in GetFreeDriveSpace({0}): {1}", drive, ex.Message);
return 0;
}
/// <summary>
/// Check all configured disks for their free space and send a notification
/// if necessary (depending on the configured delta time).
/// </summary>
public static string CheckFreeDiskSpace(List<Serializables.DriveToCheck> drives) {
var msg = "";
foreach (var driveToCheck in drives) {
var freeSpace = GetFreeDriveSpace(driveToCheck.DriveName);
if (freeSpace >= driveToCheck.SpaceThreshold * Conv.GigaBytes) {
Log.Trace("Drive [{0}] free space: {1}, above threshold ({2})",
driveToCheck.DriveName, Conv.BytesToString(freeSpace),
Conv.GigabytesToString(driveToCheck.SpaceThreshold));
continue;
msg += $"Drive [{driveToCheck.DriveName}] " +
$"free space: {Conv.BytesToString(freeSpace)} " +
$"(threshold: {Conv.GigabytesToString(driveToCheck.SpaceThreshold)})\n";
}
return msg;
}
/// <summary>
/// Compares all processes against the ProcessNames in the BlacklistedProcesses list.
/// </summary>
/// <returns>Returns the name of the first matching process, an empty string otherwise.</returns>
public static string CheckForBlacklistedProcesses(List<string> processNames) {
foreach (var running in Process.GetProcesses()) {
try {
foreach (var blacklisted in processNames) {
if (running.ProcessName.ToLower().Equals(blacklisted)) {
return blacklisted;
}
}
}
catch (Exception ex) {
Log.Error("Error in checkProcesses(): {0}", ex.Message);
return "";
}
/// <summary>
/// Check if a user is currently logged into Windows.
///
/// WARNING: this DOES NOT ACCOUNT for users logged in via RDP!!
/// </summary>
/// See https://stackoverflow.com/questions/5218778/ for the RDP problem.
public static bool NoUserIsLoggedOn() {
var username = "";
try {
var searcher = new ManagementObjectSearcher("SELECT UserName " +
"FROM Win32_ComputerSystem");
var collection = searcher.Get();
username = (string)collection.Cast<ManagementBaseObject>().First()["UserName"];
}
catch (Exception ex) {
Log.Error("Error in getCurrentUsername(): {0}", ex.Message);
return username == "";
}
}
}