From d56d123e61d2f4347ac6d7c5a3ed4b697e986f5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Trzci=C5=84ski?= Date: Sat, 12 Nov 2022 12:22:19 +0100 Subject: [PATCH] Store Fan mode in settings and add startup on boot --- FanControl/App.config | 12 ++ FanControl/FanControl.csproj | 4 +- FanControl/FanControlForm.Designer.cs | 48 ++++- FanControl/FanControlForm.cs | 52 ++++- .../StartupManager.cs | 185 ++++++++++++++++++ FanControl/Properties/Settings.Designer.cs | 12 ++ FanControl/Properties/Settings.settings | 13 +- 7 files changed, 307 insertions(+), 19 deletions(-) create mode 100644 FanControl/FromLibreHardwareMonitor/StartupManager.cs diff --git a/FanControl/App.config b/FanControl/App.config index 49cc43e..4dd49e2 100644 --- a/FanControl/App.config +++ b/FanControl/App.config @@ -1,3 +1,15 @@  + + +
+ + + + + + Default + + + \ No newline at end of file diff --git a/FanControl/FanControl.csproj b/FanControl/FanControl.csproj index ab2ca79..3497e99 100644 --- a/FanControl/FanControl.csproj +++ b/FanControl/FanControl.csproj @@ -1,4 +1,4 @@ - + WinExe @@ -8,10 +8,12 @@ True FanControl.Program app.manifest + 0.1.0 + diff --git a/FanControl/FanControlForm.Designer.cs b/FanControl/FanControlForm.Designer.cs index 97746dc..4d606a0 100644 --- a/FanControl/FanControlForm.Designer.cs +++ b/FanControl/FanControlForm.Designer.cs @@ -39,11 +39,14 @@ this.menuStrip1 = new System.Windows.Forms.MenuStrip(); this.fanModeSelectMenu = new System.Windows.Forms.ToolStripComboBox(); this.controlToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItemStartupOnBoot = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.propertyGridUpdateTimer = new System.Windows.Forms.Timer(this.components); this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); this.sensorWarningLabel = new System.Windows.Forms.Label(); this.propertyGrid1 = new System.Windows.Forms.PropertyGrid(); + this.label1 = new System.Windows.Forms.Label(); this.contextMenu.SuspendLayout(); this.menuStrip1.SuspendLayout(); this.tableLayoutPanel1.SuspendLayout(); @@ -119,15 +122,29 @@ // controlToolStripMenuItem // this.controlToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItemStartupOnBoot, + this.toolStripSeparator2, this.exitToolStripMenuItem}); this.controlToolStripMenuItem.Name = "controlToolStripMenuItem"; this.controlToolStripMenuItem.Size = new System.Drawing.Size(113, 40); this.controlToolStripMenuItem.Text = "&Control"; // + // toolStripMenuItemStartupOnBoot + // + this.toolStripMenuItemStartupOnBoot.Name = "toolStripMenuItemStartupOnBoot"; + this.toolStripMenuItemStartupOnBoot.Size = new System.Drawing.Size(315, 44); + this.toolStripMenuItemStartupOnBoot.Text = "&Startup on Boot"; + this.toolStripMenuItemStartupOnBoot.Click += new System.EventHandler(this.toolStripMenuItemStartupOnBoot_Click); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(312, 6); + // // exitToolStripMenuItem // this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; - this.exitToolStripMenuItem.Size = new System.Drawing.Size(184, 44); + this.exitToolStripMenuItem.Size = new System.Drawing.Size(315, 44); this.exitToolStripMenuItem.Text = "&Exit"; this.exitToolStripMenuItem.Click += new System.EventHandler(this.formClose_Event); // @@ -143,12 +160,14 @@ this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.tableLayoutPanel1.Controls.Add(this.sensorWarningLabel, 0, 1); this.tableLayoutPanel1.Controls.Add(this.propertyGrid1, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.label1, 0, 2); this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 44); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; - this.tableLayoutPanel1.RowCount = 2; + this.tableLayoutPanel1.RowCount = 3; this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.Size = new System.Drawing.Size(712, 885); this.tableLayoutPanel1.TabIndex = 5; // @@ -159,7 +178,7 @@ this.sensorWarningLabel.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.sensorWarningLabel.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point); this.sensorWarningLabel.ForeColor = System.Drawing.Color.Red; - this.sensorWarningLabel.Location = new System.Drawing.Point(3, 757); + this.sensorWarningLabel.Location = new System.Drawing.Point(3, 725); this.sensorWarningLabel.Name = "sensorWarningLabel"; this.sensorWarningLabel.Size = new System.Drawing.Size(706, 128); this.sensorWarningLabel.TabIndex = 6; @@ -175,10 +194,25 @@ this.propertyGrid1.HelpVisible = false; this.propertyGrid1.Location = new System.Drawing.Point(3, 3); this.propertyGrid1.Name = "propertyGrid1"; - this.propertyGrid1.Size = new System.Drawing.Size(706, 751); + this.propertyGrid1.Size = new System.Drawing.Size(706, 719); this.propertyGrid1.TabIndex = 1; this.propertyGrid1.ToolbarVisible = false; // + // label1 + // + this.label1.AutoSize = true; + this.label1.Dock = System.Windows.Forms.DockStyle.Fill; + this.label1.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.label1.Font = new System.Drawing.Font("Segoe UI", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Underline))), System.Drawing.GraphicsUnit.Point); + this.label1.ForeColor = System.Drawing.SystemColors.HotTrack; + this.label1.Location = new System.Drawing.Point(3, 853); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(706, 32); + this.label1.TabIndex = 7; + this.label1.Text = "https://github.com/ayufan-research/SteamDeckTools"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + this.label1.DoubleClick += new System.EventHandler(this.label1_DoubleClick); + // // FanControlForm // this.AutoScaleDimensions = new System.Drawing.SizeF(13F, 32F); @@ -188,9 +222,12 @@ this.Controls.Add(this.menuStrip1); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.MainMenuStrip = this.menuStrip1; + this.MaximizeBox = false; this.Name = "FanControlForm"; + this.ShowInTaskbar = false; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Steam Deck Fan Control"; + this.WindowState = System.Windows.Forms.FormWindowState.Minimized; this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FanControlForm_FormClosing); this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.FanControlForm_FormClosed); this.contextMenu.ResumeLayout(false); @@ -219,5 +256,8 @@ private TableLayoutPanel tableLayoutPanel1; private Label sensorWarningLabel; private PropertyGrid propertyGrid1; + private ToolStripMenuItem toolStripMenuItemStartupOnBoot; + private ToolStripSeparator toolStripSeparator2; + private Label label1; } } \ No newline at end of file diff --git a/FanControl/FanControlForm.cs b/FanControl/FanControlForm.cs index 42d565c..1fcb4a9 100644 --- a/FanControl/FanControlForm.cs +++ b/FanControl/FanControlForm.cs @@ -1,8 +1,10 @@ -using System; +using FanControl.FromLibreHardwareMonitor; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Data.Common; +using System.Diagnostics; using System.Drawing; using System.Linq; using System.Net.Sockets; @@ -15,11 +17,18 @@ namespace FanControl public partial class FanControlForm : Form { private FanController fanControl = new FanController(); + private StartupManager startupManager = new StartupManager(); public FanControlForm() { InitializeComponent(); + Text += " v" + Application.ProductVersion.ToString(); + notifyIcon.Text = Text; + + toolStripMenuItemStartupOnBoot.Visible = startupManager.IsAvailable; + toolStripMenuItemStartupOnBoot.Checked = startupManager.Startup; + propertyGrid1.SelectedObject = fanControl; propertyGrid1.ExpandAllGridItems(); @@ -29,19 +38,33 @@ namespace FanControl fanModeSelectNotifyMenu.Items.Add(item); } - fanModeSelectMenu.SelectedIndex = 0; - fanModeSelectNotifyMenu.SelectedIndex = 0; + try + { + var fanMode = Enum.Parse(typeof(FanController.FanMode), Properties.Settings.Default.FanMode); + setFanMode((FanController.FanMode)fanMode); + } + catch(System.ArgumentException) + { + setFanMode(FanController.FanMode.Default); + } - notifyIcon.ShowBalloonTip(3000, "Steam Deck Fan Control", "Fan Control Started", ToolTipIcon.Info); + notifyIcon.ShowBalloonTip(3000, Text, "Fan Control Started", ToolTipIcon.Info); + } + + private void setFanMode(FanController.FanMode mode) + { + fanControl.SetMode(mode); + fanModeSelectMenu.SelectedItem = mode; + fanModeSelectNotifyMenu.SelectedItem = mode; + Properties.Settings.Default["FanMode"] = mode.ToString(); + Properties.Settings.Default.Save(); } private void fanModeSelect_SelectedValueChanged(object sender, EventArgs e) { var comboBox = (ToolStripComboBox)sender; var selectedMode = (FanController.FanMode)comboBox.SelectedItem; - fanControl.SetMode(selectedMode); - fanModeSelectMenu.SelectedItem = selectedMode; - fanModeSelectNotifyMenu.SelectedItem = selectedMode; + setFanMode(selectedMode); } private void FanControlForm_FormClosing(object sender, FormClosingEventArgs e) @@ -49,13 +72,13 @@ namespace FanControl if (e.CloseReason == CloseReason.UserClosing && Visible) { e.Cancel = true; - Hide(); + WindowState = FormWindowState.Minimized; } } private void formShow_Event(object sender, EventArgs e) { - Show(); + WindowState = FormWindowState.Normal; propertyGrid1.Refresh(); } @@ -87,5 +110,16 @@ namespace FanControl sensorWarningLabel.Visible = fanControl.IsAnyInvalid(); notifyIcon.Text = String.Format("Fan: {0} RPM Mode: {1}", fanControl.CurrentRPM, fanControl.Mode); } + + private void toolStripMenuItemStartupOnBoot_Click(object sender, EventArgs e) + { + startupManager.Startup = !startupManager.Startup; + toolStripMenuItemStartupOnBoot.Checked = startupManager.Startup; + } + + private void label1_DoubleClick(object sender, EventArgs e) + { + System.Diagnostics.Process.Start("http://github.com/ayufan-research/SteamDeckTools"); + } } } diff --git a/FanControl/FromLibreHardwareMonitor/StartupManager.cs b/FanControl/FromLibreHardwareMonitor/StartupManager.cs new file mode 100644 index 0000000..639d915 --- /dev/null +++ b/FanControl/FromLibreHardwareMonitor/StartupManager.cs @@ -0,0 +1,185 @@ +// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. +// Copyright (C) LibreHardwareMonitor and Contributors. +// Partial Copyright (C) Michael Möller and Contributors. +// All Rights Reserved. + +using System; +using System.IO; +using System.Linq; +using System.Security; +using System.Security.Principal; +using System.Windows.Forms; +using Microsoft.Win32; +using Microsoft.Win32.TaskScheduler; +using Action = Microsoft.Win32.TaskScheduler.Action; +using Task = Microsoft.Win32.TaskScheduler.Task; + +namespace FanControl.FromLibreHardwareMonitor +{ + public class StartupManager + { + private const string RegistryPath = @"Software\Microsoft\Windows\CurrentVersion\Run"; + private bool _startup; + + public const string Description = "Starts Steam Deck Fan Control on Windows startup."; + public const string NameOf = "Steam Deck Fan Control"; + + public StartupManager() + { + if (Environment.OSVersion.Platform >= PlatformID.Unix) + { + IsAvailable = false; + return; + } + + if (IsAdministrator() && TaskService.Instance.Connected) + { + IsAvailable = true; + + Task task = GetTask(); + if (task != null) + { + foreach (Action action in task.Definition.Actions) + { + if (action.ActionType == TaskActionType.Execute && action is ExecAction execAction) + { + if (execAction.Path.Equals(Application.ExecutablePath, StringComparison.OrdinalIgnoreCase)) + _startup = true; + } + } + } + } + else + { + try + { + using (RegistryKey registryKey = Registry.CurrentUser.OpenSubKey(RegistryPath)) + { + string value = (string)registryKey?.GetValue(NameOf); + + if (value != null) + _startup = value == Application.ExecutablePath; + } + + IsAvailable = true; + } + catch (SecurityException) + { + IsAvailable = false; + } + } + } + + public bool IsAvailable { get; } + + public bool Startup + { + get { return _startup; } + set + { + if (_startup != value) + { + if (IsAvailable) + { + if (TaskService.Instance.Connected) + { + if (value) + CreateTask(); + else + DeleteTask(); + + _startup = value; + } + else + { + try + { + if (value) + CreateRegistryKey(); + else + DeleteRegistryKey(); + + _startup = value; + } + catch (UnauthorizedAccessException) + { + throw new InvalidOperationException(); + } + } + } + else + { + throw new InvalidOperationException(); + } + } + } + } + + private static bool IsAdministrator() + { + try + { + WindowsIdentity identity = WindowsIdentity.GetCurrent(); + WindowsPrincipal principal = new WindowsPrincipal(identity); + + return principal.IsInRole(WindowsBuiltInRole.Administrator); + } + catch + { + return false; + } + } + + private static Task GetTask() + { + try + { + return TaskService.Instance.AllTasks.FirstOrDefault(x => x.Name.Equals(NameOf, StringComparison.OrdinalIgnoreCase)); + } + catch + { + return null; + } + } + + private void CreateTask() + { + TaskDefinition taskDefinition = TaskService.Instance.NewTask(); + taskDefinition.RegistrationInfo.Description = Description; + + taskDefinition.Triggers.Add(new LogonTrigger()); + + taskDefinition.Settings.StartWhenAvailable = true; + taskDefinition.Settings.DisallowStartIfOnBatteries = false; + taskDefinition.Settings.StopIfGoingOnBatteries = false; + taskDefinition.Settings.ExecutionTimeLimit = TimeSpan.Zero; + taskDefinition.Settings.AllowHardTerminate = false; + + taskDefinition.Principal.RunLevel = TaskRunLevel.Highest; + taskDefinition.Principal.LogonType = TaskLogonType.InteractiveToken; + + taskDefinition.Actions.Add(new ExecAction(Application.ExecutablePath, "", Path.GetDirectoryName(Application.ExecutablePath))); + + TaskService.Instance.RootFolder.RegisterTaskDefinition(NameOf, taskDefinition); + } + + private static void DeleteTask() + { + Task task = GetTask(); + task?.Folder.DeleteTask(task.Name, false); + } + + private static void CreateRegistryKey() + { + RegistryKey registryKey = Registry.CurrentUser.CreateSubKey(RegistryPath); + registryKey?.SetValue(NameOf, Application.ExecutablePath); + } + + private static void DeleteRegistryKey() + { + RegistryKey registryKey = Registry.CurrentUser.CreateSubKey(RegistryPath); + registryKey?.DeleteValue(NameOf); + } + } +} diff --git a/FanControl/Properties/Settings.Designer.cs b/FanControl/Properties/Settings.Designer.cs index 4bb435d..bc5d36a 100644 --- a/FanControl/Properties/Settings.Designer.cs +++ b/FanControl/Properties/Settings.Designer.cs @@ -22,5 +22,17 @@ namespace FanControl.Properties { return defaultInstance; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("Default")] + public string FanMode { + get { + return ((string)(this["FanMode"])); + } + set { + this["FanMode"] = value; + } + } } } diff --git a/FanControl/Properties/Settings.settings b/FanControl/Properties/Settings.settings index 049245f..fc44976 100644 --- a/FanControl/Properties/Settings.settings +++ b/FanControl/Properties/Settings.settings @@ -1,6 +1,9 @@  - - - - - + + + + + Default + + + \ No newline at end of file