From a8d41f67c95f9ddaffd2362c4d4587b43d516512 Mon Sep 17 00:00:00 2001 From: Vincent Maas Date: Sun, 11 Sep 2022 16:40:55 +0200 Subject: [PATCH] fix screensaver issue, add eye comfort mode, improve elevated process and add priority/affinity settings to game launcher --- ColorControl/ColorControl.csproj | 8 +- ColorControl/Common/Utils.cs | 182 +++++++++++------- ColorControl/Config.cs | 2 + ColorControl/Forms/ElevatedForm.Designer.cs | 46 +++++ ColorControl/Forms/ElevatedForm.cs | 93 +++++++++ ColorControl/Forms/ElevatedForm.resx | 60 ++++++ ColorControl/Forms/MessageForms.cs | 9 +- ColorControl/MainForm.Designer.cs | 93 +++++++-- ColorControl/MainForm.cs | 105 +++++++++- ColorControl/MainForm.resx | 5 +- ColorControl/Native/WinApi.cs | 135 +++++++++++++ ColorControl/Program.cs | 41 +++- .../Services/Common/GraphicsService.cs | 4 +- .../Services/GameLauncher/GamePreset.cs | 13 ++ .../Services/GameLauncher/GameService.cs | 2 +- ColorControl/Services/LG/LgDevice.cs | 1 + ColorControl/Services/LG/LgService.cs | 2 +- ColorControl/StartUpParams.cs | 48 +++++ 18 files changed, 743 insertions(+), 106 deletions(-) create mode 100644 ColorControl/Forms/ElevatedForm.Designer.cs create mode 100644 ColorControl/Forms/ElevatedForm.cs create mode 100644 ColorControl/Forms/ElevatedForm.resx create mode 100644 ColorControl/Native/WinApi.cs diff --git a/ColorControl/ColorControl.csproj b/ColorControl/ColorControl.csproj index 55e5363..7e3690c 100644 --- a/ColorControl/ColorControl.csproj +++ b/ColorControl/ColorControl.csproj @@ -18,8 +18,8 @@ Maassoft Maassoft 0 - 7.2.0.0 - 7.2.0.0 + 7.3.0.0 + 7.3.0.0 false true false @@ -89,8 +89,8 @@ - - + + diff --git a/ColorControl/Common/Utils.cs b/ColorControl/Common/Utils.cs index 4304034..f599500 100644 --- a/ColorControl/Common/Utils.cs +++ b/ColorControl/Common/Utils.cs @@ -1,10 +1,10 @@ using ColorControl.Forms; +using ColorControl.Native; using Microsoft.Win32; using Microsoft.Win32.TaskScheduler; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NWin32; -using NWin32.NativeTypes; using System; using System.Collections.Generic; using System.ComponentModel; @@ -36,52 +36,14 @@ namespace ColorControl.Common Win = 8 } - [StructLayout(LayoutKind.Sequential, Pack = 4)] - internal struct POWERBROADCAST_SETTING - { - public Guid PowerSetting; - public uint DataLength; - public byte Data; - } - public const int WM_BRINGTOFRONT = NativeConstants.WM_USER + 1; - public const int ENUM_CURRENT_SETTINGS = -1; - public const int ENUM_REGISTRY_SETTINGS = -2; - public static string PKEY_PNPX_IpAddress = "{656a3bb3-ecc0-43fd-8477-4ae0404a96cd} 12297"; public static string PKEY_PNPX_PhysicalAddress = "{656a3bb3-ecc0-43fd-8477-4ae0404a96cd} 12294"; public static Guid GUID_CONSOLE_DISPLAY_STATE = Guid.Parse("6FE69556-704A-47A0-8F24-C28D936FDA47"); - public static int PBT_POWERSETTINGCHANGE = 32787; - - public delegate void PCREATE_PROCESS_NOTIFY_ROUTINE(IntPtr ParentId, IntPtr ProcessId, bool Create); public static bool ConsoleOpened { get; private set; } - - [DllImport("user32.dll", SetLastError = true)] - public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc); - [DllImport("user32.dll")] - public static extern bool UnregisterHotKey(IntPtr hWnd, int id); - - [DllImport("user32.dll")] - public static extern bool EnumDisplaySettingsA(string deviceName, int modeNum, out DEVMODEA devMode); - - [DllImport("kernel32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool AllocConsole(); - - [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] - private static extern bool AttachConsole(int processId); - - [DllImport("kernel32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool FreeConsole(); - - [DllImport(@"User32", SetLastError = true)] - public static extern IntPtr RegisterPowerSettingNotification(IntPtr hRecipient, ref Guid PowerSettingGuid, Int32 Flags); - - [DllImport("User32.dll", SetLastError = true)] - public static extern bool UnregisterPowerSettingNotification(IntPtr hWnd); + public static bool UseDedicatedElevatedProcess = false; private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); private static bool WinKeyDown = false; @@ -208,8 +170,24 @@ namespace ColorControl.Common return keys; } - internal static bool ExecuteElevated(string args) + static bool IsAdministrator() { + var identity = WindowsIdentity.GetCurrent(); + var principal = new WindowsPrincipal(identity); + return principal.IsInRole(WindowsBuiltInRole.Administrator); + } + + internal static int ExecuteElevated(string args, bool wait = true, bool skipDedicated = false) + { + if (UseDedicatedElevatedProcess && !skipDedicated) + { + CheckElevatedProcess(); + + WinApi.CopyData.Send(ElevatedProcessWindowHandle, 1, args); + + return 0; + } + var info = new ProcessStartInfo(Process.GetCurrentProcess().MainModule.FileName, args) { Verb = "runas", // indicates to elevate privileges @@ -224,14 +202,35 @@ namespace ColorControl.Common try { process.Start(); - process.WaitForExit(); // sleep calling process thread until evoked process exit - return true; + + if (wait) + { + process.WaitForExit(); // sleep calling process thread until evoked process exit + } + + return process.Id; } catch (Exception e) { Logger.Error("ExecuteElevated: " + e.Message); } - return false; + return 0; + } + + private static IntPtr ElevatedProcessWindowHandle = IntPtr.Zero; + + internal static void CheckElevatedProcess() + { + ElevatedProcessWindowHandle = NativeMethods.FindWindowW(null, "ElevatedForm"); + + if (ElevatedProcessWindowHandle == IntPtr.Zero) + { + ExecuteElevated(StartUpParams.StartElevatedParam, false, true); + + Thread.Sleep(500); + + ElevatedProcessWindowHandle = NativeMethods.FindWindowW(null, "ElevatedForm"); + } } internal static bool IsChromeFixInstalled() @@ -273,21 +272,6 @@ namespace ColorControl.Common return key != null; } - internal static void GetRegistryKeyValue(string keyname, string valueName, bool deepSearch = false) - { - var key = Registry.LocalMachine.OpenSubKey(keyname); - - foreach (var subKeyName in key.GetSubKeyNames()) - { - var subKey = key.OpenSubKey(subKeyName); - if (subKey.GetValueNames().Contains(valueName)) - { - Thread.Sleep(0); - } - } - - } - internal static bool UpdateShortcut(string path, string arguments, bool removeArguments = false) { if (File.Exists(path)) @@ -468,6 +452,8 @@ namespace ColorControl.Common { return descriptionAttribute.Description; } + + return enumName; } return null; // could also return string.Empty @@ -510,6 +496,12 @@ namespace ColorControl.Common public static void RegisterTask(string taskName, bool enabled) { + if (!IsAdministrator()) + { + ExecuteElevated(enabled ? StartUpParams.EnableAutoStartParam : StartUpParams.DisableAutoStartParam); + return; + } + var file = Process.GetCurrentProcess().MainModule.FileName; var directory = Path.GetDirectoryName(file); @@ -569,13 +561,13 @@ namespace ColorControl.Common { if (clear) { - UnregisterHotKey(handle, id); + WinApi.UnregisterHotKey(handle, id); } if (!string.IsNullOrEmpty(shortcut)) { var (mods, key) = ParseShortcut(shortcut); - var result = RegisterHotKey(handle, id, mods, key); + var result = WinApi.RegisterHotKey(handle, id, mods, key); if (!result) { var errorMessage = new Win32Exception(Marshal.GetLastWin32Error()).Message; @@ -588,6 +580,13 @@ namespace ColorControl.Common return true; } + public static void CheckWin32Error(string message) + { + var errorMessage = new Win32Exception(Marshal.GetLastWin32Error()).Message; + + throw new Exception($"{message}: {errorMessage}"); + } + public static string FormatKeyboardShortcut(KeyEventArgs keyEvent) { var pressedModifiers = keyEvent.Modifiers; @@ -655,9 +654,9 @@ namespace ColorControl.Common return true; } - if (!AttachConsole(-1)) + if (!WinApi.AttachConsole(-1)) { - AllocConsole(); + WinApi.AllocConsole(); return true; } ConsoleOpened = true; @@ -673,7 +672,7 @@ namespace ColorControl.Common } SendKeys.SendWait("{ENTER}"); - var result = FreeConsole(); + var result = WinApi.FreeConsole(); return result; } @@ -692,7 +691,7 @@ namespace ColorControl.Common return null; } - public static void StartProcess(string fileName, string arguments = null, bool hidden = false, bool wait = false, bool setWorkingDir = false, bool elevate = false) + public static void StartProcess(string fileName, string arguments = null, bool hidden = false, bool wait = false, bool setWorkingDir = false, bool elevate = false, uint affinityMask = 0, uint priorityClass = 0) { var process = Process.Start(new ProcessStartInfo(fileName, arguments) { @@ -701,12 +700,65 @@ namespace ColorControl.Common WindowStyle = hidden ? ProcessWindowStyle.Hidden : ProcessWindowStyle.Normal, WorkingDirectory = setWorkingDir ? Path.GetDirectoryName(fileName) : null }); + + if (affinityMask > 0) + { + SetProcessAffinity(process.Id, affinityMask); + } + + if (priorityClass > 0 && priorityClass != NativeConstants.NORMAL_PRIORITY_CLASS) + { + SetProcessPriority(process.Id, priorityClass); + } + if (wait) { process.WaitForExit(); } } + internal static void SetProcessAffinity(int processId, uint affinityMask) + { + if (!IsAdministrator()) + { + ExecuteElevated($"{StartUpParams.SetProcessAffinityParam} {processId} {affinityMask}"); + + return; + } + + var hProcess = NativeMethods.OpenProcess(NativeConstants.PROCESS_ALL_ACCESS, false, (uint)processId); + + if (hProcess == IntPtr.Zero) + { + CheckWin32Error($"Unable to set processor affinity on process {processId}"); + } + + NativeMethods.SetProcessAffinityMask(hProcess, affinityMask); + + //var AffinityMask = (long)process.ProcessorAffinity; + //AffinityMask &= 0x000F; // use only any of the first 4 available processors + //process.ProcessorAffinity = (IntPtr)AffinityMask; + } + + internal static void SetProcessPriority(int processId, uint priorityClass) + { + if (!IsAdministrator()) + { + ExecuteElevated($"{StartUpParams.SetProcessPriorityParam} {processId} {priorityClass}"); + + return; + } + + var hProcess = NativeMethods.OpenProcess(NativeConstants.PROCESS_ALL_ACCESS, false, (uint)processId); + + if (hProcess == IntPtr.Zero) + { + CheckWin32Error($"Unable to set process priority on process {processId}"); + } + + NativeMethods.SetPriorityClass(hProcess, priorityClass); + } + public static string GetResourceFile(string resourceName) { resourceName = "ColorControl.Resources." + resourceName; diff --git a/ColorControl/Config.cs b/ColorControl/Config.cs index eab9607..6be9acf 100644 --- a/ColorControl/Config.cs +++ b/ColorControl/Config.cs @@ -30,6 +30,7 @@ namespace ColorControl public string AmdQuickAccessShortcut { get; set; } public string LgQuickAccessShortcut { get; set; } public string GameQuickAccessShortcut { get; set; } + public bool UseDedicatedElevatedProcess { get; set; } public Config() { @@ -41,6 +42,7 @@ namespace ColorControl CheckForUpdates = true; FixChromeFonts = false; UseGdiScaling = true; + UseDedicatedElevatedProcess = false; LgPresetsSortState = new ListViewSortState(); NvPresetsSortState = new ListViewSortState(); AmdPresetsSortState = new ListViewSortState(); diff --git a/ColorControl/Forms/ElevatedForm.Designer.cs b/ColorControl/Forms/ElevatedForm.Designer.cs new file mode 100644 index 0000000..fb7a647 --- /dev/null +++ b/ColorControl/Forms/ElevatedForm.Designer.cs @@ -0,0 +1,46 @@ +namespace ColorControl.Forms +{ + partial class ElevatedForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // ElevatedForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(251, 124); + this.Name = "ElevatedForm"; + this.Text = "ElevatedForm"; + this.ResumeLayout(false); + + } + + #endregion + } +} \ No newline at end of file diff --git a/ColorControl/Forms/ElevatedForm.cs b/ColorControl/Forms/ElevatedForm.cs new file mode 100644 index 0000000..044b3f6 --- /dev/null +++ b/ColorControl/Forms/ElevatedForm.cs @@ -0,0 +1,93 @@ +using ColorControl.Native; +using NWin32; +using System; +using System.Drawing; +using System.IO; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace ColorControl.Forms +{ + public partial class ElevatedForm : Form + { + public ElevatedForm() + { + File.Delete("d:\\Msg.txt"); + InitializeComponent(); + + FormBorderStyle = FormBorderStyle.None; + ShowInTaskbar = false; + Load += ElevatedForm_Load; + Shown += ElevatedForm_Shown; + + var filterStatus = new WinApi.CHANGEFILTERSTRUCT(); + filterStatus.size = (uint)Marshal.SizeOf(filterStatus); + filterStatus.info = 0; + + var result = WinApi.ChangeWindowMessageFilterEx(Handle, NativeConstants.WM_COPYDATA, WinApi.ChangeWindowMessageFilterExAction.Allow, ref filterStatus); + //File.AppendAllLines("d:\\Msg.txt", new[] { "ChangeWindowMessageFilterEx result: " + result }); + + Task.Run(() => CheckMutexAsync()); + } + + private void ElevatedForm_Shown(object sender, EventArgs e) + { + Hide(); + } + + protected void ElevatedForm_Load(object sender, EventArgs e) + { + Size = new Size(0, 0); + } + + protected override void WndProc(ref Message m) + { + if (m.Msg == NativeConstants.WM_COPYDATA) + { + var container = (WinApi.COPYDATASTRUCT)m.GetLParam(typeof(WinApi.COPYDATASTRUCT)); + var message = Marshal.PtrToStringAnsi(container.lpData); + + File.AppendAllLines("d:\\Msg.txt", new[] { "Message received: " + message }); + + HandleMessage(message); + + //Utils.StartProcess("notepad.exe"); + + //BackColor = Color.Red; + //Text = "AHA!"; + //MessageForms.WarningOk("Received!"); + } + + base.WndProc(ref m); + } + + private void HandleMessage(string message) + { + var args = message.Split(' '); + + var startUpParams = StartUpParams.Parse(args); + + Program.HandleStartupParams(startUpParams, null); + } + + private void CheckMutexAsync() + { + var mutex = new Mutex(false, Program.MutexId, out var created); + + File.AppendAllLines("d:\\Msg.txt", new[] { "Mutex created: " + created }); + + try + { + mutex.WaitOne(); + File.AppendAllLines("d:\\Msg.txt", new[] { "Mutex released?" }); + } + catch (AbandonedMutexException) + { + File.AppendAllLines("d:\\Msg.txt", new[] { "Mutex abandoned" }); + } + BeginInvoke(() => Application.Exit()); + } + } +} diff --git a/ColorControl/Forms/ElevatedForm.resx b/ColorControl/Forms/ElevatedForm.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/ColorControl/Forms/ElevatedForm.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ColorControl/Forms/MessageForms.cs b/ColorControl/Forms/MessageForms.cs index a8f3f89..f4dc00a 100644 --- a/ColorControl/Forms/MessageForms.cs +++ b/ColorControl/Forms/MessageForms.cs @@ -177,7 +177,7 @@ namespace ColorControl.Forms if (field.Values != null && field.Values.Any()) { comboBox.Items.AddRange(field.Values.ToArray()); - comboBox.SelectedIndex = 0; + comboBox.SelectedIndex = field.Value is string strValue ? comboBox.Items.IndexOf(strValue) : 0; } control = comboBox; @@ -188,8 +188,9 @@ namespace ColorControl.Forms { Left = 40, Top = top, - Width = 200, - Height = 100 + Width = 400, + Height = 100, + MultiColumn = true }; top += 80; @@ -197,7 +198,7 @@ namespace ColorControl.Forms if (field.Values != null && field.Values.Any()) { - var compoundValue = (int)field.Value; + var compoundValue = field.Value is int ? (int)field.Value : (int)((uint)field.Value); var enumValue = 1; foreach (var value in field.Values) { diff --git a/ColorControl/MainForm.Designer.cs b/ColorControl/MainForm.Designer.cs index 7efa371..fa80a6f 100644 --- a/ColorControl/MainForm.Designer.cs +++ b/ColorControl/MainForm.Designer.cs @@ -79,6 +79,7 @@ this.btnApply = new System.Windows.Forms.Button(); this.lvNvPresets = new System.Windows.Forms.ListView(); this.tabAMD = new System.Windows.Forms.TabPage(); + this.btnAmdSettings = new System.Windows.Forms.Button(); this.chkAmdQuickAccess = new System.Windows.Forms.CheckBox(); this.lblAmdPresetName = new System.Windows.Forms.Label(); this.edtAmdPresetName = new System.Windows.Forms.TextBox(); @@ -170,6 +171,10 @@ this.clbLgPower = new System.Windows.Forms.CheckedListBox(); this.lblLgError = new System.Windows.Forms.Label(); this.tabGameLauncher = new System.Windows.Forms.TabPage(); + this.btnGameOptions = new System.Windows.Forms.Button(); + this.mnuGameOptions = new System.Windows.Forms.ContextMenuStrip(this.components); + this.miGameProcessorAffinity = new System.Windows.Forms.ToolStripMenuItem(); + this.miGameProcessPriority = new System.Windows.Forms.ToolStripMenuItem(); this.chkGameQuickAccess = new System.Windows.Forms.CheckBox(); this.btnGameSettings = new System.Windows.Forms.Button(); this.mnuGameActions = new System.Windows.Forms.ContextMenuStrip(this.components); @@ -246,7 +251,7 @@ this.mnuNvSettings = new System.Windows.Forms.ContextMenuStrip(this.components); this.miNvProfileInspector = new System.Windows.Forms.ToolStripMenuItem(); this.miNvSettings = new System.Windows.Forms.ToolStripMenuItem(); - this.btnAmdSettings = new System.Windows.Forms.Button(); + this.chkOptionsDedicatedElevatedProcess = new System.Windows.Forms.CheckBox(); this.tcMain.SuspendLayout(); this.tabNVIDIA.SuspendLayout(); this.mnuNvPresets.SuspendLayout(); @@ -259,6 +264,7 @@ this.mnuLgExpert.SuspendLayout(); this.mnuLgButtons.SuspendLayout(); this.tabGameLauncher.SuspendLayout(); + this.mnuGameOptions.SuspendLayout(); this.mnuGameActions.SuspendLayout(); this.mnuGameAddStep.SuspendLayout(); this.tabOptions.SuspendLayout(); @@ -794,6 +800,18 @@ this.tabAMD.Text = "AMD controller"; this.tabAMD.UseVisualStyleBackColor = true; // + // btnAmdSettings + // + this.btnAmdSettings.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnAmdSettings.Location = new System.Drawing.Point(1017, 429); + this.btnAmdSettings.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.btnAmdSettings.Name = "btnAmdSettings"; + this.btnAmdSettings.Size = new System.Drawing.Size(88, 27); + this.btnAmdSettings.TabIndex = 60; + this.btnAmdSettings.Text = "Settings..."; + this.btnAmdSettings.UseVisualStyleBackColor = true; + this.btnAmdSettings.Click += new System.EventHandler(this.btnAmdSettings_Click); + // // chkAmdQuickAccess // this.chkAmdQuickAccess.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); @@ -1827,6 +1845,7 @@ // // tabGameLauncher // + this.tabGameLauncher.Controls.Add(this.btnGameOptions); this.tabGameLauncher.Controls.Add(this.chkGameQuickAccess); this.tabGameLauncher.Controls.Add(this.btnGameSettings); this.tabGameLauncher.Controls.Add(this.chkGameRunAsAdmin); @@ -1854,6 +1873,43 @@ this.tabGameLauncher.Text = "Game Launcher"; this.tabGameLauncher.UseVisualStyleBackColor = true; // + // btnGameOptions + // + this.btnGameOptions.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.btnGameOptions.ContextMenuStrip = this.mnuGameOptions; + this.btnGameOptions.Enabled = false; + this.btnGameOptions.Location = new System.Drawing.Point(785, 439); + this.btnGameOptions.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.btnGameOptions.Name = "btnGameOptions"; + this.btnGameOptions.Size = new System.Drawing.Size(88, 27); + this.btnGameOptions.TabIndex = 45; + this.btnGameOptions.Text = "Options..."; + this.btnGameOptions.UseVisualStyleBackColor = true; + this.btnGameOptions.Click += new System.EventHandler(this.btnGameOptions_Click); + // + // mnuGameOptions + // + this.mnuGameOptions.ImageScalingSize = new System.Drawing.Size(20, 20); + this.mnuGameOptions.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.miGameProcessorAffinity, + this.miGameProcessPriority}); + this.mnuGameOptions.Name = "mnuLgButtons"; + this.mnuGameOptions.Size = new System.Drawing.Size(166, 48); + // + // miGameProcessorAffinity + // + this.miGameProcessorAffinity.Name = "miGameProcessorAffinity"; + this.miGameProcessorAffinity.Size = new System.Drawing.Size(165, 22); + this.miGameProcessorAffinity.Text = "Processor affinity"; + this.miGameProcessorAffinity.Click += new System.EventHandler(this.btnGameProcessAffinity_Click); + // + // miGameProcessPriority + // + this.miGameProcessPriority.Name = "miGameProcessPriority"; + this.miGameProcessPriority.Size = new System.Drawing.Size(165, 22); + this.miGameProcessPriority.Text = "Process priority"; + this.miGameProcessPriority.Click += new System.EventHandler(this.miGameProcessPriority_Click); + // // chkGameQuickAccess // this.chkGameQuickAccess.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); @@ -2522,6 +2578,7 @@ // // grpGeneralOptions // + this.grpGeneralOptions.Controls.Add(this.chkOptionsDedicatedElevatedProcess); this.grpGeneralOptions.Controls.Add(this.chkGdiScaling); this.grpGeneralOptions.Controls.Add(this.chkCheckForUpdates); this.grpGeneralOptions.Controls.Add(this.chkMinimizeToSystemTray); @@ -2540,7 +2597,7 @@ // chkGdiScaling // this.chkGdiScaling.AutoSize = true; - this.chkGdiScaling.Location = new System.Drawing.Point(238, 75); + this.chkGdiScaling.Location = new System.Drawing.Point(238, 72); this.chkGdiScaling.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.chkGdiScaling.Name = "chkGdiScaling"; this.chkGdiScaling.Size = new System.Drawing.Size(197, 19); @@ -2552,7 +2609,7 @@ // chkCheckForUpdates // this.chkCheckForUpdates.AutoSize = true; - this.chkCheckForUpdates.Location = new System.Drawing.Point(238, 48); + this.chkCheckForUpdates.Location = new System.Drawing.Point(238, 47); this.chkCheckForUpdates.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.chkCheckForUpdates.Name = "chkCheckForUpdates"; this.chkCheckForUpdates.Size = new System.Drawing.Size(197, 19); @@ -2576,7 +2633,7 @@ // chkMinimizeOnClose // this.chkMinimizeOnClose.AutoSize = true; - this.chkMinimizeOnClose.Location = new System.Drawing.Point(7, 75); + this.chkMinimizeOnClose.Location = new System.Drawing.Point(7, 72); this.chkMinimizeOnClose.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.chkMinimizeOnClose.Name = "chkMinimizeOnClose"; this.chkMinimizeOnClose.Size = new System.Drawing.Size(122, 19); @@ -2588,7 +2645,7 @@ // chkStartMinimized // this.chkStartMinimized.AutoSize = true; - this.chkStartMinimized.Location = new System.Drawing.Point(7, 48); + this.chkStartMinimized.Location = new System.Drawing.Point(7, 47); this.chkStartMinimized.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.chkStartMinimized.Name = "chkStartMinimized"; this.chkStartMinimized.Size = new System.Drawing.Size(109, 19); @@ -2767,17 +2824,17 @@ this.miNvSettings.Text = "Settings"; this.miNvSettings.Click += new System.EventHandler(this.miNvSettings_Click); // - // btnAmdSettings + // chkOptionsDedicatedElevatedProcess // - this.btnAmdSettings.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.btnAmdSettings.Location = new System.Drawing.Point(1017, 429); - this.btnAmdSettings.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); - this.btnAmdSettings.Name = "btnAmdSettings"; - this.btnAmdSettings.Size = new System.Drawing.Size(88, 27); - this.btnAmdSettings.TabIndex = 60; - this.btnAmdSettings.Text = "Settings..."; - this.btnAmdSettings.UseVisualStyleBackColor = true; - this.btnAmdSettings.Click += new System.EventHandler(this.btnAmdSettings_Click); + this.chkOptionsDedicatedElevatedProcess.AutoSize = true; + this.chkOptionsDedicatedElevatedProcess.Location = new System.Drawing.Point(7, 97); + this.chkOptionsDedicatedElevatedProcess.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.chkOptionsDedicatedElevatedProcess.Name = "chkOptionsDedicatedElevatedProcess"; + this.chkOptionsDedicatedElevatedProcess.Size = new System.Drawing.Size(190, 19); + this.chkOptionsDedicatedElevatedProcess.TabIndex = 8; + this.chkOptionsDedicatedElevatedProcess.Text = "Use dedicated elevated process"; + this.chkOptionsDedicatedElevatedProcess.UseVisualStyleBackColor = true; + this.chkOptionsDedicatedElevatedProcess.CheckedChanged += new System.EventHandler(this.chkOptionsDedicatedElevatedProcess_CheckedChanged); // // MainForm // @@ -2815,6 +2872,7 @@ this.mnuLgButtons.ResumeLayout(false); this.tabGameLauncher.ResumeLayout(false); this.tabGameLauncher.PerformLayout(); + this.mnuGameOptions.ResumeLayout(false); this.mnuGameActions.ResumeLayout(false); this.mnuGameAddStep.ResumeLayout(false); this.tabOptions.ResumeLayout(false); @@ -3062,6 +3120,11 @@ private System.Windows.Forms.ToolStripMenuItem miNvSettings; private System.Windows.Forms.CheckBox chkAmdQuickAccess; private System.Windows.Forms.Button btnAmdSettings; + private System.Windows.Forms.Button btnGameOptions; + private System.Windows.Forms.ContextMenuStrip mnuGameOptions; + private System.Windows.Forms.ToolStripMenuItem miGameProcessorAffinity; + private System.Windows.Forms.ToolStripMenuItem miGameProcessPriority; + private System.Windows.Forms.CheckBox chkOptionsDedicatedElevatedProcess; } } diff --git a/ColorControl/MainForm.cs b/ColorControl/MainForm.cs index 3191c22..645a6f6 100644 --- a/ColorControl/MainForm.cs +++ b/ColorControl/MainForm.cs @@ -1,6 +1,7 @@ using ATI.ADL; using ColorControl.Common; using ColorControl.Forms; +using ColorControl.Native; using ColorControl.Services.AMD; using ColorControl.Services.Common; using ColorControl.Services.GameLauncher; @@ -147,7 +148,7 @@ namespace ColorControl InitInfo(); UserSessionInfo.Install(); - _screenStateNotify = Utils.RegisterPowerSettingNotification(Handle, ref Utils.GUID_CONSOLE_DISPLAY_STATE, 0); + _screenStateNotify = WinApi.RegisterPowerSettingNotification(Handle, ref Utils.GUID_CONSOLE_DISPLAY_STATE, 0); //Scale(new SizeF(1.25F, 1.25F)); @@ -716,9 +717,9 @@ namespace ColorControl } else if (m.Msg == NativeConstants.WM_POWERBROADCAST) { - if (m.WParam.ToInt32() == Utils.PBT_POWERSETTINGCHANGE) + if (m.WParam.ToInt32() == WinApi.PBT_POWERSETTINGCHANGE) { - var ps = Marshal.PtrToStructure(m.LParam); + var ps = Marshal.PtrToStructure(m.LParam); Logger.Debug($"PBT_POWERSETTINGCHANGE: {ps.Data}"); @@ -783,7 +784,7 @@ namespace ColorControl if (_screenStateNotify != IntPtr.Zero) { - Utils.UnregisterPowerSettingNotification(_screenStateNotify); + WinApi.UnregisterPowerSettingNotification(_screenStateNotify); _screenStateNotify = IntPtr.Zero; } } @@ -816,7 +817,7 @@ namespace ColorControl return; } var enabled = chkStartAfterLogin.Checked; - Utils.ExecuteElevated(enabled ? StartUpParams.EnableAutoStartParam : StartUpParams.DisableAutoStartParam); + Utils.RegisterTask(Program.TS_TASKNAME, enabled); } private void LoadConfig() @@ -828,6 +829,7 @@ namespace ColorControl edtDelayDisplaySettings.Value = _config.DisplaySettingsDelay; edtBlankScreenSaverShortcut.Text = _config.ScreenSaverShortcut; chkGdiScaling.Checked = _config.UseGdiScaling; + chkOptionsDedicatedElevatedProcess.Checked = _config.UseDedicatedElevatedProcess; if (!string.IsNullOrEmpty(_config.ScreenSaverShortcut)) { @@ -1589,7 +1591,7 @@ namespace ColorControl if (!string.IsNullOrEmpty(preset.shortcut)) { - Utils.UnregisterHotKey(Handle, preset.id); + WinApi.UnregisterHotKey(Handle, preset.id); } _nvService.GetPresets().Remove(preset); @@ -1944,7 +1946,7 @@ namespace ColorControl if (!string.IsNullOrEmpty(preset.shortcut)) { - Utils.UnregisterHotKey(Handle, preset.id); + WinApi.UnregisterHotKey(Handle, preset.id); } _lgService.GetPresets().Remove(preset); @@ -2729,7 +2731,7 @@ Do you want to continue?"; if (!string.IsNullOrEmpty(preset.shortcut)) { - Utils.UnregisterHotKey(Handle, preset.id); + WinApi.UnregisterHotKey(Handle, preset.id); } _amdService.GetPresets().Remove(preset); @@ -3408,7 +3410,7 @@ The InStart and Software Update items are now visible under the Expert-button." if (string.IsNullOrEmpty(text)) { - Utils.UnregisterHotKey(Handle, SHORTCUTID_GAMEBAR); + WinApi.UnregisterHotKey(Handle, SHORTCUTID_GAMEBAR); } else { @@ -3737,7 +3739,7 @@ The InStart and Software Update items are now visible under the Expert-button." if (!string.IsNullOrEmpty(preset.shortcut)) { - Utils.UnregisterHotKey(Handle, preset.id); + WinApi.UnregisterHotKey(Handle, preset.id); } _gameService.GetPresets().Remove(preset); @@ -3989,5 +3991,88 @@ The InStart and Software Update items are now visible under the Expert-button." Utils.RegisterShortcut(Handle, SHORTCUTID_AMDQA, _config.AmdQuickAccessShortcut, clear); } + + private void btnGameProcessAffinity_Click(object sender, EventArgs e) + { + var preset = GetSelectedGamePreset(); + + if (preset == null) + { + return; + } + + var numberOfProcessors = Environment.ProcessorCount; + + var options = Enumerable.Range(0, numberOfProcessors).Select(i => $"CPU #{i}"); + + var values = MessageForms.ShowDialog("Set processor affinity", new[] { + new MessageForms.FieldDefinition + { + Label = "Set desired processors which are allowed to run program", + FieldType = MessageForms.FieldType.Flags, + Values = options, + Value = preset.ProcessAffinityMask + } + }); + + if (!values.Any()) + { + return; + } + + var value = values.First().Value; + + preset.ProcessAffinityMask = (uint)(int)value; + } + + private void btnGameOptions_Click(object sender, EventArgs e) + { + mnuGameOptions.Show(btnGameOptions, btnGameOptions.PointToClient(Cursor.Position)); + } + + private void miGameProcessPriority_Click(object sender, EventArgs e) + { + var preset = GetSelectedGamePreset(); + + if (preset == null) + { + return; + } + + var dropDownValues = Utils.GetDescriptions(); + + var values = MessageForms.ShowDialog("Set process priority", new[] { + new MessageForms.FieldDefinition + { + Label = "Set desired process priority", + FieldType = MessageForms.FieldType.DropDown, + Values = dropDownValues, + Value = preset.ProcessPriorityClass > 0 ? ((GamePriorityClass)preset.ProcessPriorityClass).GetDescription() : GamePriorityClass.Normal.GetDescription() + } + }); + + if (!values.Any()) + { + return; + } + + var value = values.First().Value.ToString(); + var enumName = Utils.GetEnumNameByDescription(typeof(GamePriorityClass), value); + if (enumName != null) + { + value = enumName; + } + + var enumValue = Enum.Parse(typeof(GamePriorityClass), value); + + preset.ProcessPriorityClass = (uint)(int)enumValue; + + } + + private void chkOptionsDedicatedElevatedProcess_CheckedChanged(object sender, EventArgs e) + { + _config.UseDedicatedElevatedProcess = chkOptionsDedicatedElevatedProcess.Checked; + Utils.UseDedicatedElevatedProcess = _config.UseDedicatedElevatedProcess; + } } } \ No newline at end of file diff --git a/ColorControl/MainForm.resx b/ColorControl/MainForm.resx index 8f3dfb9..86759e2 100644 --- a/ColorControl/MainForm.resx +++ b/ColorControl/MainForm.resx @@ -69,8 +69,11 @@ 147, 17 + + 705, 16 + - 418, 15 + 414, 15 416, 50 diff --git a/ColorControl/Native/WinApi.cs b/ColorControl/Native/WinApi.cs new file mode 100644 index 0000000..dd27396 --- /dev/null +++ b/ColorControl/Native/WinApi.cs @@ -0,0 +1,135 @@ +using NWin32.NativeTypes; +using System; +using System.Runtime.InteropServices; + +namespace ColorControl.Native +{ + public static class WinApi + { + [StructLayout(LayoutKind.Sequential, Pack = 4)] + internal struct POWERBROADCAST_SETTING + { + public Guid PowerSetting; + public uint DataLength; + public byte Data; + } + + [StructLayout(LayoutKind.Sequential)] + public struct COPYDATASTRUCT + { + public IntPtr dwData; // in C/C++ this is an UINT_PTR, not an UINT + public int cbData; + public IntPtr lpData; + } + + [StructLayout(LayoutKind.Sequential)] + public struct CopyData : IDisposable + { + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] + static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg, IntPtr wParam, ref CopyData target, + SendMessageTimeoutFlags fuFlags, uint uTimeout, out UIntPtr lpdwResult); + + [Flags] + enum SendMessageTimeoutFlags : uint + { + SMTO_NORMAL = 0x0, + SMTO_BLOCK = 0x1, + SMTO_ABORTIFHUNG = 0x2, + SMTO_NOTIMEOUTIFNOTHUNG = 0x8 + } + const uint WM_COPYDATA = 0x4A; + + public IntPtr dwData; + public int cbData; + public IntPtr lpData; + + public void Dispose() + { + if (lpData != IntPtr.Zero) + { + Marshal.FreeCoTaskMem(lpData); + lpData = IntPtr.Zero; + cbData = 0; + } + } + public string AsAnsiString + { + get { return Marshal.PtrToStringAnsi(lpData, cbData); } + } + public string AsUnicodeString + { + get { return Marshal.PtrToStringUni(lpData); } + } + public static CopyData CreateForString(int dwData, string value, bool Unicode = false) + { + var result = new CopyData(); + result.dwData = (IntPtr)dwData; + result.lpData = Unicode ? Marshal.StringToCoTaskMemUni(value) : Marshal.StringToCoTaskMemAnsi(value); + result.cbData = value.Length + 2; + return result; + } + + public static UIntPtr Send(IntPtr targetHandle, int dwData, string value, uint timeoutMs = 1000, bool Unicode = false) + { + var cds = CreateForString(dwData, value, Unicode); + UIntPtr result; + SendMessageTimeout(targetHandle, WM_COPYDATA, IntPtr.Zero, ref cds, SendMessageTimeoutFlags.SMTO_NORMAL, timeoutMs, out result); + cds.Dispose(); + return result; + } + } + + public enum MessageFilterInfo : uint + { + None = 0, AlreadyAllowed = 1, AlreadyDisAllowed = 2, AllowedHigher = 3 + }; + + public enum ChangeWindowMessageFilterExAction : uint + { + Reset = 0, Allow = 1, DisAllow = 2 + }; + + [StructLayout(LayoutKind.Sequential)] + public struct CHANGEFILTERSTRUCT + { + public uint size; + public MessageFilterInfo info; + } + + public const int ENUM_CURRENT_SETTINGS = -1; + public const int ENUM_REGISTRY_SETTINGS = -2; + + public static int PBT_POWERSETTINGCHANGE = 32787; + + public delegate void PCREATE_PROCESS_NOTIFY_ROUTINE(IntPtr ParentId, IntPtr ProcessId, bool Create); + + [DllImport("user32.dll", SetLastError = true)] + public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc); + + [DllImport("user32.dll")] + public static extern bool UnregisterHotKey(IntPtr hWnd, int id); + + [DllImport("user32.dll")] + public static extern bool EnumDisplaySettingsA(string deviceName, int modeNum, out DEVMODEA devMode); + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AllocConsole(); + + [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] + public static extern bool AttachConsole(int processId); + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool FreeConsole(); + + [DllImport(@"User32", SetLastError = true)] + public static extern IntPtr RegisterPowerSettingNotification(IntPtr hRecipient, ref Guid PowerSettingGuid, Int32 Flags); + + [DllImport("User32.dll", SetLastError = true)] + public static extern bool UnregisterPowerSettingNotification(IntPtr hWnd); + + [DllImport("user32.dll", SetLastError = true)] + public static extern bool ChangeWindowMessageFilterEx(IntPtr hWnd, uint msg, ChangeWindowMessageFilterExAction action, ref CHANGEFILTERSTRUCT changeInfo); + } +} diff --git a/ColorControl/Program.cs b/ColorControl/Program.cs index f9be8de..10701d4 100644 --- a/ColorControl/Program.cs +++ b/ColorControl/Program.cs @@ -1,4 +1,5 @@ using ColorControl.Common; +using ColorControl.Forms; using ColorControl.Services.AMD; using ColorControl.Services.LG; using ColorControl.Services.NVIDIA; @@ -21,6 +22,8 @@ namespace ColorControl public static Config Config { get; private set; } public static AppContext AppContext { get; private set; } + public static string MutexId { get; private set; } + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); /// @@ -29,6 +32,8 @@ namespace ColorControl [STAThread] static void Main(string[] args) { + MutexId = $"Global\\{typeof(MainForm).GUID}"; + var currentDomain = AppDomain.CurrentDomain; // Handler for unhandled exceptions. currentDomain.UnhandledException += GlobalUnhandledExceptionHandler; @@ -63,8 +68,7 @@ namespace ColorControl Utils.CloseConsole(); } - string mutexId = $"Global\\{typeof(MainForm).GUID}"; - var mutex = new Mutex(true, mutexId, out var mutexCreated); + var mutex = new Mutex(true, MutexId, out var mutexCreated); try { if (!mutexCreated) @@ -81,11 +85,13 @@ namespace ColorControl } else { + mutex.WaitOne(); try { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm(AppContext)); + } catch (Exception ex) { @@ -135,9 +141,11 @@ namespace ColorControl Logger.Error($"LoadConfig: {ex.Message}"); } Config ??= new Config(); + + Utils.UseDedicatedElevatedProcess = Config.UseDedicatedElevatedProcess; } - private static bool HandleStartupParams(StartUpParams startUpParams, Process existingProcess) + public static bool HandleStartupParams(StartUpParams startUpParams, Process existingProcess) { if (startUpParams.ActivateChromeFontFix || startUpParams.DeactivateChromeFontFix) { @@ -149,6 +157,21 @@ namespace ColorControl Utils.RegisterTask(TS_TASKNAME, startUpParams.EnableAutoStart); return true; } + if (startUpParams.SetProcessAffinity) + { + Utils.SetProcessAffinity(startUpParams.ProcessId, startUpParams.AffinityMask); + return true; + } + if (startUpParams.SetProcessPriority) + { + Utils.SetProcessPriority(startUpParams.ProcessId, startUpParams.PriorityClass); + return true; + } + if (startUpParams.StartElevated) + { + StartElevated(); + return true; + } var useConsole = startUpParams.NoGui || existingProcess != null; @@ -228,6 +251,18 @@ namespace ColorControl return result; } + private static void StartElevated() + { + try + { + Application.Run(new ElevatedForm()); + } + catch (Exception ex) + { + MessageBox.Show("Error while initializing elevated application: " + ex.ToLogString(Environment.StackTrace), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + public static int EnumThreadWindows(IntPtr handle, IntPtr param) { NativeMethods.SendMessageW(handle, Utils.WM_BRINGTOFRONT, UIntPtr.Zero, IntPtr.Zero); diff --git a/ColorControl/Services/Common/GraphicsService.cs b/ColorControl/Services/Common/GraphicsService.cs index 6e1ca62..5381efd 100644 --- a/ColorControl/Services/Common/GraphicsService.cs +++ b/ColorControl/Services/Common/GraphicsService.cs @@ -1,4 +1,4 @@ -using ColorControl.Common; +using ColorControl.Native; using NWin32; using NWin32.NativeTypes; using System; @@ -101,7 +101,7 @@ namespace ColorControl.Services.Common { DEVMODEA devMode; // NativeMethods defines modeNum as an 'uint' but we need to pass '-1' - if (Utils.EnumDisplaySettingsA(displayName, Utils.ENUM_CURRENT_SETTINGS, out devMode)) + if (WinApi.EnumDisplaySettingsA(displayName, WinApi.ENUM_CURRENT_SETTINGS, out devMode)) { return devMode.dmDisplayFrequency; } diff --git a/ColorControl/Services/GameLauncher/GamePreset.cs b/ColorControl/Services/GameLauncher/GamePreset.cs index 82ea364..bf9e66f 100644 --- a/ColorControl/Services/GameLauncher/GamePreset.cs +++ b/ColorControl/Services/GameLauncher/GamePreset.cs @@ -1,8 +1,19 @@ using ColorControl.Services.Common; +using NWin32; using System.Collections.Generic; namespace ColorControl.Services.GameLauncher { + public enum GamePriorityClass + { + Idle = NativeConstants.IDLE_PRIORITY_CLASS, + BelowNormal = NativeConstants.BELOW_NORMAL_PRIORITY_CLASS, + Normal = NativeConstants.NORMAL_PRIORITY_CLASS, + AboveNormal = NativeConstants.ABOVE_NORMAL_PRIORITY_CLASS, + High = NativeConstants.HIGH_PRIORITY_CLASS, + RealTime = NativeConstants.REALTIME_PRIORITY_CLASS + } + class GamePreset : PresetBase { public string Path { get; set; } @@ -10,6 +21,8 @@ namespace ColorControl.Services.GameLauncher public bool RunAsAdministrator { get; set; } public List PreLaunchSteps { get; set; } public List PostLaunchSteps { get; set; } + public uint ProcessAffinityMask { get; set; } + public uint ProcessPriorityClass { get; set; } public GamePreset() : base() { diff --git a/ColorControl/Services/GameLauncher/GameService.cs b/ColorControl/Services/GameLauncher/GameService.cs index 79bb1a6..1041e41 100644 --- a/ColorControl/Services/GameLauncher/GameService.cs +++ b/ColorControl/Services/GameLauncher/GameService.cs @@ -133,7 +133,7 @@ namespace ColorControl.Services.GameLauncher if (!string.IsNullOrEmpty(preset.Path)) { - Utils.StartProcess(preset.Path, preset.Parameters, setWorkingDir: true, elevate: preset.RunAsAdministrator); + Utils.StartProcess(preset.Path, preset.Parameters, setWorkingDir: true, elevate: preset.RunAsAdministrator, affinityMask: preset.ProcessAffinityMask, priorityClass: preset.ProcessPriorityClass); } _lastAppliedPreset = preset; diff --git a/ColorControl/Services/LG/LgDevice.cs b/ColorControl/Services/LG/LgDevice.cs index 54d1ee2..83fba78 100644 --- a/ColorControl/Services/LG/LgDevice.cs +++ b/ColorControl/Services/LG/LgDevice.cs @@ -150,6 +150,7 @@ namespace ColorControl.Services.LG AddGenericPictureAction("gamma", typeof(GammaExp)); AddGenericPictureAction("colorTemperature", minValue: 0, maxValue: 50, title: "Color Temperature"); AddGenericPictureAction("whiteBalanceColorTemperature", typeof(WhiteBalanceColorTemperature), title: "White Balance Color Temperature"); + AddGenericPictureAction("eyeComfortMode", typeof(OffToOn), title: "Eye Comfort Mode"); //AddGenericPictureAction("dynamicColor", typeof(OffToAuto)); //AddGenericPictureAction("superResolution", typeof(OffToAuto)); AddGenericPictureAction("peakBrightness", typeof(OffToHigh), title: "Peak Brightness"); diff --git a/ColorControl/Services/LG/LgService.cs b/ColorControl/Services/LG/LgService.cs index 594bb0f..b012f31 100644 --- a/ColorControl/Services/LG/LgService.cs +++ b/ColorControl/Services/LG/LgService.cs @@ -654,7 +654,7 @@ namespace ColorControl.Services.LG Logger.Debug($"Screensaver check: powering off tv {device.Name} because of screensaver"); try { - _poweredOffByScreenSaver = await device.PowerOff().WaitAsync(TimeSpan.FromSeconds(5)); + _poweredOffByScreenSaver = await device.PowerOff(true).WaitAsync(TimeSpan.FromSeconds(5)); } catch (TimeoutException) { diff --git a/ColorControl/StartUpParams.cs b/ColorControl/StartUpParams.cs index b953fe1..5bc7f0a 100644 --- a/ColorControl/StartUpParams.cs +++ b/ColorControl/StartUpParams.cs @@ -14,6 +14,9 @@ namespace ColorControl public const string NoGuiParam = "--nogui"; public const string EnableAutoStartParam = "--enable-auto-start"; public const string DisableAutoStartParam = "--disable-auto-start"; + public const string SetProcessAffinityParam = "--set-process-affinity"; + public const string SetProcessPriorityParam = "--set-process-priority"; + public const string StartElevatedParam = "--elevated"; public bool RunningFromScheduledTask { get; private set; } public bool ActivateChromeFontFix { get; private set; } @@ -28,6 +31,12 @@ namespace ColorControl public bool NoGui { get; set; } public bool EnableAutoStart { get; private set; } public bool DisableAutoStart { get; private set; } + public bool SetProcessAffinity { get; private set; } + public int ProcessId { get; private set; } + public uint AffinityMask { get; private set; } + public bool SetProcessPriority { get; private set; } + public uint PriorityClass { get; private set; } + public bool StartElevated { get; private set; } public static StartUpParams Parse(IEnumerable args) { @@ -54,6 +63,28 @@ namespace ColorControl settings.LgPresetName = arg; break; } + case SetProcessAffinityParam: + { + if (settings.ProcessId == 0) + { + settings.ProcessId = int.Parse(arg); + continue; + } + + settings.AffinityMask = uint.Parse(arg); + break; + } + case SetProcessPriorityParam: + { + if (settings.ProcessId == 0) + { + settings.ProcessId = int.Parse(arg); + continue; + } + + settings.PriorityClass = uint.Parse(arg); + break; + } } parseNameParam = string.Empty; @@ -116,6 +147,23 @@ namespace ColorControl settings.DisableAutoStart = true; break; } + case SetProcessAffinityParam: + { + settings.SetProcessAffinity = true; + parseNameParam = SetProcessAffinityParam; + break; + } + case SetProcessPriorityParam: + { + settings.SetProcessPriority = true; + parseNameParam = SetProcessPriorityParam; + break; + } + case StartElevatedParam: + { + settings.StartElevated = true; + break; + } } } return settings;