/// <summary> /// Main method; start of the program. /// </summary> /// <param name="args">Command-line parameters</param> /// <returns>Status/error code</returns> static int Main(string[] args) { try { int temperatureLowerThreshold = int.Parse(args[0]); int temperatureUpperThreshold = int.Parse(args[1]); ulong rpmThreshold = ulong.Parse(args[2]); int sleepInterval = 1; if (args.Length > 3) { sleepInterval = int.Parse(args[3]); } FixConsole(); Console.Title = "DellFanKeepAlive"; Console.OutputEncoding = Encoding.UTF8; Console.BackgroundColor = ConsoleColor.DarkRed; string titleText = "DellFanKeepAlive version " + DellFanLib.Version + " • By Aaron Kelley • GPLv3 • https://github.com/AaronKelley/DellFanManagement\n" + "Dell SMM I/O driver by 424778940z • https://github.com/424778940z/bzh-windrv-dell-smm-io\n" + "Open Hardware Monitor version 0.9.5 • Copyright © 2009-2020 Michael Möller and contributors (MPL 2.0)\n" + "Icon made from Icon Fonts (http://www.onlinewebfonts.com/icon/), licensed by CC BY 3.0\n" + "\n" + "Configuration: lower temperature threshold " + temperatureLowerThreshold + ", upper temperature threshold " + temperatureUpperThreshold + ", RPM threshold " + rpmThreshold + "\n" + "\n"; if (DellFanLib.Initialize()) { TemperatureReader temperatureReader = new TemperatureReader(); DellFanLib.EnableEcFanControl(); bool ecFanControlEnabled = true; DateTime ecFanControlChangeTime = DateTime.Now; DateTime lastUpdateTime = DateTime.Now; StringBuilder statusString = new StringBuilder(); ulong rpm1; ulong rpm2 = ulong.MaxValue; bool fan2Present = true; bool firstRun = true; Console.Clear(); while (true) { try { // Check last update time. DateTime currentTime = DateTime.Now; if (((DateTimeOffset)currentTime).ToUnixTimeSeconds() - ((DateTimeOffset)lastUpdateTime).ToUnixTimeSeconds() > 30) { lastUpdateTime = currentTime; throw new Exception(string.Format("A long time passed between updates - {0} - {1}", lastUpdateTime.ToString(), currentTime.ToString())); } lastUpdateTime = currentTime; statusString.Clear(); statusString.Append(titleText); statusString.AppendFormat("Current time: {0,-30}\n\n", lastUpdateTime); bool thresholdsMet = true; IReadOnlyDictionary <string, int> temperatures = temperatureReader.GetCpuCoreTemperatures(); foreach (string key in temperatures.Keys) { int temperature = temperatures[key]; if (temperature > (ecFanControlEnabled ? temperatureLowerThreshold : temperatureUpperThreshold)) { thresholdsMet = false; } } rpm1 = DellFanLib.GetFanRpm(FanIndex.Fan1); if (fan2Present) { rpm2 = DellFanLib.GetFanRpm(FanIndex.Fan2); if (rpm2 == uint.MaxValue && firstRun) { // No fan 2. fan2Present = false; } firstRun = false; } if (rpm1 == 0 || rpm1 > rpmThreshold || (fan2Present && (rpm2 == 0 || rpm2 > rpmThreshold))) { thresholdsMet = false; } statusString.AppendFormat("Temperature and fan speed thresholds are {0,-8}\n", thresholdsMet ? "met." : "not met."); statusString.AppendFormat("{0,-75}\n\n", ecFanControlEnabled ? string.Format("The EC has had control of the system fans since {0}.", ecFanControlChangeTime.ToString()) : string.Format("The fan speed has been locked since {0}.", ecFanControlChangeTime.ToString()) ); statusString.Append("System temperatures:\n"); foreach (string key in temperatures.Keys) { string temperature = temperatures[key] != 0 ? temperatures[key].ToString() : "--"; statusString.AppendFormat(" {0,-14}{1,3}", key, temperature); CheckValues(key, temperatures[key]); if (minValues.ContainsKey(key) && maxValues.ContainsKey(key)) { statusString.AppendFormat(" ( {0,3} - {1,3} )", minValues[key], maxValues[key]); } statusString.Append("\n"); } statusString.Append("\n"); statusString.Append("Fan speeds:\n"); statusString.AppendFormat(" {0,-9}{1,5}\n", "Fan #1", rpm1); if (fan2Present) { statusString.AppendFormat(" {0,-9}{1,5}\n", "Fan #2", rpm2); } if (ecFanControlEnabled && thresholdsMet) { DellFanLib.DisableEcFanControl(); ecFanControlEnabled = false; ecFanControlChangeTime = DateTime.Now; Console.BackgroundColor = ConsoleColor.DarkBlue; Console.Clear(); } else if (!ecFanControlEnabled && !thresholdsMet) { DellFanLib.EnableEcFanControl(); ecFanControlEnabled = true; ecFanControlChangeTime = DateTime.Now; Console.BackgroundColor = ConsoleColor.DarkRed; Console.Clear(); } if (errorsDetected) { statusString.Append("\n!! Errors detected, check error log file for details !!\n"); } FixConsole(); Console.CursorLeft = 0; Console.CursorTop = 0; Console.Write(statusString); } catch (Exception exception) { LogError(exception); } Thread.Sleep(1000 * sleepInterval); } } else { Console.Error.WriteLine("Failed to start driver."); Console.Error.WriteLine(); Console.Error.WriteLine("Please make sure that bzh_dell_smm_io_x64.sys is present in the working directory,"); Console.Error.WriteLine("and that measures needed to allow the signature to be verified have been performed."); Console.Error.WriteLine("Also, make sure that you are running the program \"as administrator\"."); } } catch (DllNotFoundException) { Console.Error.WriteLine("Unable to load DellFanLib.dll"); Console.Error.WriteLine("Make sure that the file is present. If it is, install the required Visual C++ redistributable:"); Console.Error.WriteLine("https://aka.ms/vs/16/release/vc_redist.x64.exe"); return(-1); } catch (Exception exception) { Console.Error.WriteLine("Error: {0}", exception.Message); Console.Error.WriteLine(exception.StackTrace); } DellFanLib.Shutdown(); return(0); }
/// <summary> /// Main method; start of the program. /// </summary> /// <param name="args">Command-line parameters</param> /// <returns>Status/error code</returns> static int Main(string[] args) { int returnCode = 0; try { Console.WriteLine("DellFanCmd {0}", DellFanLib.Version); Console.WriteLine("By Aaron Kelley"); Console.WriteLine("Licensed under GPLv3"); Console.WriteLine("Source code available at https://github.com/AaronKelley/DellFanManagement"); Console.WriteLine(); Console.WriteLine("Dell SMM I/O driver by 424778940z"); Console.WriteLine("https://github.com/424778940z/bzh-windrv-dell-smm-io"); Console.WriteLine(); Console.WriteLine("Derived from \"Dell fan utility\" by 424778940z"); Console.WriteLine("https://github.com/424778940z/dell-fan-utility"); Console.WriteLine(); if (args.Length != 1) { Usage(); } else { // Behavior variables. bool disableEcFanControl = false; bool enableEcFanControl = false; bool setFansToMax = false; bool useAlternateCommand = false; bool setFanLevel = false; bool getFanRpm = false; bool runTest = false; FanIndex fanSelection = FanIndex.Fan1; FanLevel fanLevel = FanLevel.Level0; // Figure out what was requested. if (args[0] == "ec-disable") { disableEcFanControl = true; setFansToMax = true; } else if (args[0] == "ec-disable-nofanchg") { disableEcFanControl = true; } else if (args[0] == "ec-enable") { enableEcFanControl = true; } else if (args[0] == "ec-disable-alt") { disableEcFanControl = true; setFansToMax = true; useAlternateCommand = true; } else if (args[0] == "ec-disable-alt-nofanchg") { disableEcFanControl = true; useAlternateCommand = true; } else if (args[0] == "ec-enable-alt") { enableEcFanControl = true; useAlternateCommand = true; } else if (args[0] == "fan1-level0") { setFanLevel = true; fanSelection = FanIndex.Fan1; fanLevel = FanLevel.Level0; } else if (args[0] == "fan1-level1") { setFanLevel = true; fanSelection = FanIndex.Fan1; fanLevel = FanLevel.Level1; } else if (args[0] == "fan1-level2") { setFanLevel = true; fanSelection = FanIndex.Fan1; fanLevel = FanLevel.Level2; } else if (args[0] == "fan2-level0") { setFanLevel = true; fanSelection = FanIndex.Fan2; fanLevel = FanLevel.Level0; } else if (args[0] == "fan2-level1") { setFanLevel = true; fanSelection = FanIndex.Fan2; fanLevel = FanLevel.Level1; } else if (args[0] == "fan2-level2") { setFanLevel = true; fanSelection = FanIndex.Fan2; fanLevel = FanLevel.Level2; } else if (args[0] == "rpm-fan1") { getFanRpm = true; fanSelection = FanIndex.Fan1; } else if (args[0] == "rpm-fan2") { getFanRpm = true; fanSelection = FanIndex.Fan2; } else if (args[0] == "test") { runTest = true; } else if (args[0] == "test-alt") { runTest = true; useAlternateCommand = true; } else { Usage(); return(-3); } // Execute request. // Load driver first. if (LoadDriver()) { if (disableEcFanControl) { // Disable EC fan control. Console.WriteLine("Attempting to disable EC control of the fan..."); ulong result = DellFanLib.DisableEcFanControl(useAlternateCommand); if (result == ulong.MaxValue) { Console.Error.WriteLine("Failed."); UnloadDriver(); return(-1); } Console.WriteLine(" ...Success."); if (setFansToMax) { // Crank the fans up, for safety. Console.WriteLine("Setting fan 1 speed to maximum..."); result = DellFanLib.SetFanLevel(FanIndex.Fan1, FanLevel.Level2); if (result == ulong.MaxValue) { Console.Error.WriteLine("Failed."); } Console.WriteLine("Setting fan 2 speed to maximum..."); result = DellFanLib.SetFanLevel(FanIndex.Fan2, FanLevel.Level2); if (result == ulong.MaxValue) { Console.Error.WriteLine("Failed. (Maybe your system just has one fan?)"); } } else { Console.WriteLine("WARNING: CPU and GPU are not designed to run under load without active cooling."); Console.WriteLine("Make sure that you have alternate fan speed control measures in place."); } } else if (enableEcFanControl) { // Enable EC fan control. Console.WriteLine("Attempting to enable EC control of the fan..."); ulong result = DellFanLib.EnableEcFanControl(useAlternateCommand); if (result == ulong.MaxValue) { Console.Error.WriteLine("Failed."); UnloadDriver(); return(-1); } Console.WriteLine(" ...Success."); } else if (setFanLevel) { // Set the fan to a specific level. Console.WriteLine("Attempting to set the fan level..."); ulong result = DellFanLib.SetFanLevel(fanSelection, fanLevel); if (result == ulong.MaxValue) { Console.Error.WriteLine("Failed."); UnloadDriver(); return(-1); } Console.WriteLine(" ...Success."); } else if (getFanRpm) { // Query the fan RPM. Console.WriteLine("Attempting to query the fan RPM..."); ulong result = DellFanLib.GetFanRpm(fanSelection); if (result == ulong.MaxValue) { Console.Error.WriteLine("Failed."); UnloadDriver(); return(-1); } Console.WriteLine(" Result: {0}", result); returnCode = int.Parse(result.ToString()); } else if (runTest) { // Test all of the fan levels and report RPMs. ulong rpmIdleFan1; ulong rpmLevel0Fan1; ulong rpmLevel1Fan1; ulong rpmLevel2Fan1; ulong?rpmIdleFan2 = null; ulong?rpmLevel0Fan2 = null; ulong?rpmLevel1Fan2 = null; ulong?rpmLevel2Fan2 = null; int sleepInterval = 7500; bool fan2Present = true; // Disable EC fan control. Console.WriteLine("Disabling EC fan control..."); DellFanLib.DisableEcFanControl(useAlternateCommand); // Query current idle fan levels. rpmIdleFan1 = DellFanLib.GetFanRpm(FanIndex.Fan1); DellFanLib.SetFanLevel(FanIndex.Fan1, FanLevel.Level0); rpmIdleFan2 = DellFanLib.GetFanRpm(FanIndex.Fan2); ulong result = DellFanLib.SetFanLevel(FanIndex.Fan2, FanLevel.Level0); if (result == uint.MaxValue) { // No fan 2? fan2Present = false; Console.WriteLine("Looks like fan 2 is not present, system only has one fan?"); } // Measure fan 1. Console.WriteLine("Measuring: Fan 1, level 0..."); Thread.Sleep(sleepInterval); rpmLevel0Fan1 = DellFanLib.GetFanRpm(FanIndex.Fan1); Console.WriteLine("Measuring: Fan 1, level 1..."); DellFanLib.SetFanLevel(FanIndex.Fan1, FanLevel.Level1); Thread.Sleep(sleepInterval); rpmLevel1Fan1 = DellFanLib.GetFanRpm(FanIndex.Fan1); Console.WriteLine("Measuring: Fan 1, level 2..."); DellFanLib.SetFanLevel(FanIndex.Fan1, FanLevel.Level2); Thread.Sleep(sleepInterval); rpmLevel2Fan1 = DellFanLib.GetFanRpm(FanIndex.Fan1); DellFanLib.SetFanLevel(FanIndex.Fan1, FanLevel.Level0); if (fan2Present) { // Measure fan 2. Console.WriteLine("Measuring: Fan 2, level 0..."); rpmLevel0Fan2 = DellFanLib.GetFanRpm(FanIndex.Fan2); Console.WriteLine("Measuring: Fan 2, level 1..."); DellFanLib.SetFanLevel(FanIndex.Fan2, FanLevel.Level1); Thread.Sleep(sleepInterval); rpmLevel1Fan2 = DellFanLib.GetFanRpm(FanIndex.Fan2); Console.WriteLine("Measuring: Fan 2, level 2..."); DellFanLib.SetFanLevel(FanIndex.Fan2, FanLevel.Level2); Thread.Sleep(sleepInterval); rpmLevel2Fan2 = DellFanLib.GetFanRpm(FanIndex.Fan2); } // Enable EC fan control. Console.WriteLine("Enabling EC fan control..."); DellFanLib.EnableEcFanControl(useAlternateCommand); Console.WriteLine("Test procedure is finished."); Console.WriteLine(); Console.WriteLine(); // Output results. Console.WriteLine("Fan 1 initial speed: {0}", rpmIdleFan1); if (fan2Present) { Console.WriteLine("Fan 2 initial speed: {0}", rpmIdleFan2); } Console.WriteLine(); Console.WriteLine("Fan 1 level 0 speed: {0}", rpmLevel0Fan1); Console.WriteLine("Fan 1 level 1 speed: {0}", rpmLevel1Fan1); Console.WriteLine("Fan 1 level 2 speed: {0}", rpmLevel2Fan1); Console.WriteLine(); if (fan2Present) { Console.WriteLine("Fan 2 level 0 speed: {0}", rpmLevel0Fan2); Console.WriteLine("Fan 2 level 1 speed: {0}", rpmLevel1Fan2); Console.WriteLine("Fan 2 level 2 speed: {0}", rpmLevel2Fan2); Console.WriteLine(); } } // Unload driver. UnloadDriver(); } } } catch (DllNotFoundException) { Console.Error.WriteLine("Unable to load DellFanLib.dll"); Console.Error.WriteLine("Make sure that the file is present. If it is, install the required Visual C++ redistributable:"); Console.Error.WriteLine("https://aka.ms/vs/16/release/vc_redist.x64.exe"); returnCode = -1; } catch (Exception exception) { Console.Error.WriteLine("Error: {0}", exception.Message); Console.Error.WriteLine(exception.StackTrace); returnCode = -1; UnloadDriver(); } return(returnCode); }