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;