fix WOL issues, add Windows Service

This commit is contained in:
Vincent Maas committed 2022-10-28 14:25:14 +02:00
1 parent a8d41f67c9
commit 452206729b
20 files changed
+1517 -266

No files matched your search

+1 -1
View File
@@ -5,7 +5,7 @@ VisualStudioVersion = 17.0.32014.148
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ColorControl", "ColorControl\ColorControl.csproj", "{A6005D08-70F0-44CB-A384-9219EBA84F21}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nspector", "Nspector\Nspector.csproj", "{76797290-48F5-4A82-86C3-FAD25DAE4500}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nspector", "Nspector\Nspector.csproj", "{76797290-48F5-4A82-86C3-FAD25DAE4500}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
+72 -69
View File
@@ -1,32 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0-windows10.0.20348.0</TargetFramework>
<OutputType>WinExe</OutputType>
<IsWebBootstrapper>false</IsWebBootstrapper>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>false</MapFileExtensions>
<UpdateUrl>https://www.maassoft.com/downloads/ColorControl/</UpdateUrl>
<ProductName>ColorControl</ProductName>
<PublisherName>Maassoft</PublisherName>
<LangVersion>10.0</LangVersion>
<TargetFramework>net6.0-windows10.0.20348.0</TargetFramework>
<OutputType>WinExe</OutputType>
<IsWebBootstrapper>false</IsWebBootstrapper>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>false</MapFileExtensions>
<UpdateUrl>https://www.maassoft.com/downloads/ColorControl/</UpdateUrl>
<ProductName>ColorControl</ProductName>
<PublisherName>Maassoft</PublisherName>
<Company>Maassoft</Company>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>7.3.0.0</ApplicationVersion>
<Version>7.3.0.0</Version>
<ApplicationVersion>8.0.0.0</ApplicationVersion>
<Version>8.0.0.0</Version>
<UseApplicationTrust>false</UseApplicationTrust>
<PublishWizardCompleted>true</PublishWizardCompleted>
<BootstrapperEnabled>false</BootstrapperEnabled>
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
<UseWindowsForms>true</UseWindowsForms>
<UseWPF>false</UseWPF>
<ImportWindowsDesktopTargets>true</ImportWindowsDesktopTargets>
<PublishWizardCompleted>true</PublishWizardCompleted>
<BootstrapperEnabled>false</BootstrapperEnabled>
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
<UseWindowsForms>true</UseWindowsForms>
<UseWPF>false</UseWPF>
<ImportWindowsDesktopTargets>true</ImportWindowsDesktopTargets>
<ApplicationIcon>pngbarn.ico</ApplicationIcon>
<SupportedOSPlatformVersion>10.0.20348.0</SupportedOSPlatformVersion>
<Copyright>2020-2022 Maassoft</Copyright>
@@ -40,68 +41,70 @@
<AssemblyOriginatorKeyFile>ColorControl_TemporaryKey.pfx</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<OutputPath>bin\x64\Debug\</OutputPath>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<OutputPath>bin\x64\Debug\</OutputPath>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<OutputPath>bin\x64\Release\</OutputPath>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Compile Update="Properties\Settings.Designer.cs">
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
</Compile>
<Compile Update="Services\Common\QuickAccessForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Update="services\lg\RemoteControlPanel.cs">
<SubType>UserControl</SubType>
</Compile>
<EmbeddedResource Include="Resources\LG_register.json" />
<EmbeddedResource Include="Resources\RC_coords.txt" />
<EmbeddedResource Include="Resources\LG_remote.jpg" />
<Content Include="LgPresets.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Compile Update="Properties\Settings.Designer.cs">
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
</Compile>
<Compile Update="Services\Common\QuickAccessForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Update="services\lg\RemoteControlPanel.cs">
<SubType>UserControl</SubType>
</Compile>
<EmbeddedResource Include="Resources\LG_register.json" />
<EmbeddedResource Include="Resources\RC_coords.txt" />
<EmbeddedResource Include="Resources\LG_remote.jpg" />
<Content Include="LgPresets.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="pngbarn.ico" />
<Content Include="pngbarn.ico" />
</ItemGroup>
<ItemGroup>
<Folder Include="bin\x64\Debug\" />
<Folder Include="bin\x64\Debug\" />
</ItemGroup>
<ItemGroup>
<COMReference Include="IWshRuntimeLibrary">
<Guid>{F935DC20-1CF0-11D0-ADB9-00C04FD58A0B}</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
<COMReference Include="IWshRuntimeLibrary">
<Guid>{F935DC20-1CF0-11D0-ADB9-00C04FD58A0B}</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.1" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="NLog" Version="5.0.2" />
<PackageReference Include="NStandard" Version="0.10.0.1" />
<PackageReference Include="NvAPIWrapper.Net" Version="0.8.1.101" />
<PackageReference Include="NWin32" Version="1.2.3" />
<PackageReference Include="TaskScheduler" Version="2.10.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="NLog" Version="5.0.4" />
<PackageReference Include="NStandard" Version="0.15.2" />
<PackageReference Include="NvAPIWrapper.Net" Version="0.8.1.101" />
<PackageReference Include="NWin32" Version="1.2.3" />
<PackageReference Include="TaskScheduler" Version="2.10.1" />
<PackageReference Include="Vanara.PInvoke.IpHlpApi" Version="3.4.9" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Nspector\Nspector.csproj" />
<ProjectReference Include="..\Nspector\Nspector.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<None Update="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
</Project>
+83
View File
@@ -0,0 +1,83 @@
using ColorControl.Svc;
using Newtonsoft.Json;
using System;
using System.IO.Pipes;
using System.Security.Principal;
namespace ColorControl.Common
{
public static class PipeUtils
{
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
public static string SendMessage(string message)
{
var pipeClient = new NamedPipeClientStream(".", "testpipe", PipeDirection.InOut, PipeOptions.None, TokenImpersonationLevel.None);
try
{
pipeClient.Connect(500);
try
{
var ss = new StreamString(pipeClient);
ss.WriteString(message);
var result = ss.ReadString();
return result;
}
finally
{
pipeClient.Close();
}
}
catch (Exception ex)
{
Logger.Error(ex, "PipeUtils.SendMessage");
return null;
}
}
public static SvcResultMessage SendMessage(SvcMessage message)
{
var messageJson = JsonConvert.SerializeObject(message);
var resultJson = SendMessage(messageJson);
if (resultJson == null)
{
return null;
}
var resultMessage = JsonConvert.DeserializeObject<SvcResultMessage>(resultJson);
return resultMessage;
}
public static SvcResultMessage SendMessage(SvcMessageType messageType)
{
var message = new SvcMessage { MessageType = messageType };
return SendMessage(message);
}
public static bool? SendRpcMessage(string command)
{
var message = new SvcMessage { MessageType = SvcMessageType.ExecuteRpc, Data = command };
var messageJson = JsonConvert.SerializeObject(message);
var resultJson = SendMessage(messageJson);
if (resultJson == null)
{
return null;
}
var resultMessage = JsonConvert.DeserializeObject<SvcResultMessage>(resultJson);
return resultMessage.Result;
}
}
}
+51
View File
@@ -0,0 +1,51 @@
using System;
using System.IO;
using System.Text;
namespace ColorControl.Common
{
public class StreamString
{
private Stream ioStream;
private UnicodeEncoding streamEncoding;
public StreamString(Stream ioStream)
{
this.ioStream = ioStream;
streamEncoding = new UnicodeEncoding();
}
public string ReadString()
{
var lenBytes = new byte[4];
var read = ioStream.Read(lenBytes, 0, lenBytes.Length);
if (read < lenBytes.Length)
{
return null;
}
var len = BitConverter.ToInt32(lenBytes);
var inBuffer = new byte[len];
ioStream.Read(inBuffer, 0, len);
return streamEncoding.GetString(inBuffer);
}
public int WriteString(string outString)
{
var outBuffer = streamEncoding.GetBytes(outString);
var len = outBuffer.Length;
var lenBytes = BitConverter.GetBytes(len);
ioStream.Write(lenBytes, 0, lenBytes.Length);
ioStream.Write(outBuffer, 0, len);
ioStream.Flush();
return outBuffer.Length + lenBytes.Length;
}
}
}
+280 -27
View File
@@ -14,9 +14,12 @@ using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.NetworkInformation;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
@@ -49,6 +52,23 @@ namespace ColorControl.Common
private static bool WinKeyDown = false;
private static Keys[] KeysWithoutModifiers = new[] { Keys.F13, Keys.F14, Keys.F15, Keys.F16, Keys.F17, Keys.F18, Keys.F19, Keys.F20, Keys.F21, Keys.F22, Keys.F23, Keys.F24 };
private static string SERVICE_NAME = "Color Control Service";
public static string ELEVATION_MSG = @"Elevation is needed in some cases where ColorControl needs administrator rights.
Some operations like installing a service, changing the priority of a process or creating a temporary IP-route for improved WOL-functionality will not work without those rights.
These methods are available:
- None: no administrator operations can be executed (unless program already manually is started as admin)
- Run as admin: only available when starting automatically after login (configures scheduled task with highest privileges)
- Use Windows Service: this will install a Windows Service that handles the operations which need admin rights. This is the preferred method.
- Use dedicated elevated process: a second ColorControl-process will be spawned that is run as administrator.
The best and suggested method to provide this is via a Windows Service. Only when installing the service a User Account Control window may popup.";
public static Bitmap SubPixelShift(Bitmap bitmap)
{
Bitmap bitmap2 = (Bitmap)bitmap.Clone();
@@ -170,15 +190,34 @@ namespace ColorControl.Common
return keys;
}
static bool IsAdministrator()
private static bool? _IsAdministrator;
public static bool IsAdministrator()
{
if (_IsAdministrator.HasValue)
{
return _IsAdministrator.Value;
}
var identity = WindowsIdentity.GetCurrent();
var principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
_IsAdministrator = principal.IsInRole(WindowsBuiltInRole.Administrator);
return _IsAdministrator.Value;
}
internal static int ExecuteElevated(string args, bool wait = true, bool skipDedicated = false)
internal static int ExecuteElevated(string args, bool wait = true, bool skipDedicated = false, bool skipService = false)
{
if (!skipService && IsServiceRunning())
{
var result = PipeUtils.SendRpcMessage(args);
if (result.HasValue)
{
return 0;
}
}
if (UseDedicatedElevatedProcess && !skipDedicated)
{
CheckElevatedProcess();
@@ -188,7 +227,9 @@ namespace ColorControl.Common
return 0;
}
var info = new ProcessStartInfo(Process.GetCurrentProcess().MainModule.FileName, args)
var fileName = Process.GetCurrentProcess().MainModule.FileName;
var info = new ProcessStartInfo(fileName, args)
{
Verb = "runas", // indicates to elevate privileges
UseShellExecute = true,
@@ -225,11 +266,24 @@ namespace ColorControl.Common
if (ElevatedProcessWindowHandle == IntPtr.Zero)
{
ExecuteElevated(StartUpParams.StartElevatedParam, false, true);
ExecuteElevated(StartUpParams.StartElevatedParam, false, true, true);
Thread.Sleep(500);
var delay = 1000;
ElevatedProcessWindowHandle = NativeMethods.FindWindowW(null, "ElevatedForm");
while (delay >= 0)
{
Thread.Sleep(100);
ElevatedProcessWindowHandle = NativeMethods.FindWindowW(null, "ElevatedForm");
if (ElevatedProcessWindowHandle != IntPtr.Zero)
{
Thread.Sleep(100);
break;
}
delay -= 100;
}
}
}
@@ -494,11 +548,11 @@ namespace ColorControl.Common
return list;
}
public static void RegisterTask(string taskName, bool enabled)
public static void RegisterTask(string taskName, bool enabled, TaskRunLevel runLevel = TaskRunLevel.LUA)
{
if (!IsAdministrator())
{
ExecuteElevated(enabled ? StartUpParams.EnableAutoStartParam : StartUpParams.DisableAutoStartParam);
ExecuteElevated(enabled ? $"{StartUpParams.EnableAutoStartParam} {(int)runLevel}" : StartUpParams.DisableAutoStartParam, skipService: true);
return;
}
@@ -511,8 +565,10 @@ namespace ColorControl.Common
{
if (enabled)
{
TaskDefinition td = ts.NewTask();
var td = ts.NewTask();
td.RegistrationInfo.Description = "Start ColorControl";
td.Principal.RunLevel = runLevel;
td.Triggers.Add(new LogonTrigger { UserId = WindowsIdentity.GetCurrent().Name });
@@ -528,32 +584,18 @@ namespace ColorControl.Common
}
catch (Exception e)
{
//MessageForms.ErrorOk("Could not create/delete task: " + e.Message);
Logger.Error($"Could not create/delete task: {e.Message}");
}
}
public static bool TaskExists(string taskName, bool update)
public static bool TaskExists(string taskName)
{
var file = Assembly.GetExecutingAssembly().Location;
using (TaskService ts = new TaskService())
{
var task = ts.RootFolder.Tasks.FirstOrDefault(x => x.Name.Equals(taskName));
if (task != null)
{
//var action = task.Definition.Actions.FirstOrDefault(x => x.ActionType == TaskActionType.Execute);
//if (action != null)
//{
// var execAction = action as ExecAction;
// if (!execAction.Path.Equals(file))
// {
// RegisterTask(taskName, false);
// RegisterTask(taskName, true);
// }
//}
return true;
}
return false;
return task != null;
}
}
@@ -871,5 +913,216 @@ namespace ColorControl.Common
{
return str1.Trim().Replace(" ", string.Empty).Equals(str2.Trim().Replace(" ", string.Empty), StringComparison.OrdinalIgnoreCase);
}
public static void StartService()
{
if (!IsAdministrator())
{
ExecuteElevated(StartUpParams.StartServiceParam);
return;
}
var controller = new ServiceController(SERVICE_NAME);
if (controller.Status == ServiceControllerStatus.Stopped)
{
controller.Start();
}
}
public static void StopService()
{
if (!IsAdministrator())
{
ExecuteElevated(StartUpParams.StopServiceParam);
return;
}
var controller = new ServiceController(SERVICE_NAME);
if (controller.Status == ServiceControllerStatus.Running)
{
controller.Stop();
}
}
public static bool IsServiceInstalled()
{
return GetServiceStatus() != 0;
}
public static bool IsServiceRunning()
{
return GetServiceStatus() == ServiceControllerStatus.Running;
}
public static ServiceControllerStatus GetServiceStatus()
{
var controller = new ServiceController(SERVICE_NAME);
try
{
return controller.Status;
}
catch (Exception)
{
return 0;
}
}
internal static void InstallService()
{
if (!IsAdministrator())
{
ExecuteElevated(StartUpParams.InstallServiceParam, skipService: true);
return;
}
if (!IsServiceInstalled())
{
StartProcess("sc.exe", @$"create ""{SERVICE_NAME}"" binpath=""{Process.GetCurrentProcess().MainModule.FileName}"" start=auto", wait: true);
StartProcess("sc.exe", @$"description ""{SERVICE_NAME}"" ""Executes tasks for Color Control that require elevation. If this service is stopped, functions like WOL might be impacted.""", wait: true);
}
StartService();
}
internal static void UninstallService()
{
if (!IsAdministrator())
{
ExecuteElevated(StartUpParams.UninstallServiceParam, skipService: true);
return;
}
if (!IsServiceInstalled())
{
return;
}
StopService();
StartProcess("sc.exe", @$"delete ""{SERVICE_NAME}""", wait: true);
}
public static bool PingHost(string nameOrAddress)
{
try
{
using var pinger = new Ping();
var reply = pinger.Send(nameOrAddress);
return reply.Status == IPStatus.Success;
}
catch (PingException)
{
// Discard PingExceptions and return false;
return false;
}
}
public static bool WriteText(string fileName, string data)
{
var doWrite = !File.Exists(fileName);
if (!doWrite)
{
var writtenData = File.ReadAllText(fileName);
doWrite = !writtenData.Equals(data);
}
if (doWrite)
{
try
{
File.WriteAllText(fileName, data);
}
catch (Exception e)
{
Logger.Error(e.ToLogString());
}
}
return doWrite;
}
public static string ReadText(string fileName, bool reverse = false)
{
var exists = File.Exists(fileName);
if (!exists)
{
return null;
}
try
{
var lines = new StringBuilder();
using var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using var reader = new StreamReader(fs);
string line;
while ((line = reader.ReadLine()) != null)
{
if (reverse)
{
lines.Insert(0, line + "\r\n");
continue;
}
lines.AppendLine(line);
}
return lines.ToString();
}
catch (Exception e)
{
Logger.Error(e.ToLogString());
}
return null;
}
public static bool WriteObject(string fileName, object value)
{
var data = JsonConvert.SerializeObject(value);
return WriteText(fileName, data);
}
public static T DeserializeJson<T>(string fileName)
{
try
{
var json = File.ReadAllText(fileName);
var data = JsonConvert.DeserializeObject<T>(json);
return data;
}
catch (Exception e)
{
Logger.Error(e.ToLogString());
return default;
}
}
public static string Base64Encode(string plainText)
{
var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
return Convert.ToBase64String(plainTextBytes);
}
public static string Base64Decode(string base64EncodedData)
{
var base64EncodedBytes = Convert.FromBase64String(base64EncodedData);
return Encoding.UTF8.GetString(base64EncodedBytes);
}
}
}
+169 -27
View File
@@ -1,67 +1,97 @@
using NLog;
using System;
using System.Net.NetworkInformation;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using Vanara.PInvoke;
using static Vanara.PInvoke.IpHlpApi;
namespace ColorControl.Common
{
class WOL
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private const string ArgumentExceptionInvalidMacAddressLength = "Invalid MAC address length.";
private const string ArgumentExceptionInvalidPasswordLength = "Invalid password length.";
private const int DefaultWolPort = 9;
public static bool WakeFunction(string macAddress)
public static bool WakeFunction(string macAddress, string ipAddress = null)
{
return WakeFunctionToAllNics(macAddress);
return WakeFunctionToAllNics(macAddress, ipAddress);
}
public static bool WakeFunctionToAllNics(string macAddress)
public static bool WakeFunctionCheckAdmin(string macAddress, string ipAddress = null)
{
if (Utils.IsAdministrator())
{
return WakeFunction(macAddress, ipAddress);
}
var result = PipeUtils.SendRpcMessage($"{StartUpParams.SendWakeOnLanParam} {macAddress} {ipAddress}");
// Execute local WOL anyway because pipe failed
if (!result.HasValue)
{
result = WakeFunction(macAddress, ipAddress);
}
return result.Value;
}
public static bool WakeFunctionToAllNics(string macAddress, string ipAddressString)
{
var result = false;
Logger.Debug($"Sending WOL packet to MAC-address {macAddress}");
try
{
var address = PhysicalAddress.Parse(macAddress);
var addressBytes = address.GetAddressBytes();
var physicalAddress = PhysicalAddress.Parse(macAddress);
var addressBytes = physicalAddress.GetAddressBytes();
var data = GetWolPacket(addressBytes);
var ipAddress = ipAddressString != null ? IPAddress.Parse(ipAddressString) : null;
var interfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (var ni in interfaces)
{
if (ni.NetworkInterfaceType == NetworkInterfaceType.Loopback || ni.Name.Contains("VirtualBox"))
if (ni.NetworkInterfaceType == NetworkInterfaceType.Loopback || ni.Name.Contains("VirtualBox") || ni.Name.Contains("vEthernet") || ni.Description.Contains("Virtual"))
{
continue;
}
Logger.Debug($"Found network: {ni.Name} ({ni.Description}), type: {ni.NetworkInterfaceType}");
try
{
if (/*ni.OperationalStatus == OperationalStatus.Up &&*/ ni.SupportsMulticast && ni.GetIPProperties().GetIPv4Properties() != null)
if (ni.SupportsMulticast && ni.GetIPProperties().GetIPv4Properties() == null)
{
foreach (var uip in ni.GetIPProperties().UnicastAddresses)
{
if (uip.Address.ToString().StartsWith("169.254"))
{
continue;
}
if (uip.Address.AddressFamily == AddressFamily.InterNetwork)
{
Logger.Debug($"Broadcast WOL in network: {ni.Name} ({ni.Description}), local address: {uip.Address}");
var local = new IPEndPoint(uip.Address, 0);
var udpc = new UdpClient(local);
udpc.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
udpc.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontRoute, 1);
var target = new IPEndPoint(IPAddress.Broadcast, DefaultWolPort);
udpc.Send(data, data.Length, target);
continue;
}
result = true;
}
foreach (var uip in ni.GetIPProperties().UnicastAddresses)
{
if (uip.Address.ToString().StartsWith("169.254") || uip.Address.AddressFamily != AddressFamily.InterNetwork)
{
continue;
}
Logger.Debug($"Broadcast WOL in network: {ni.Name} ({ni.Description}), local address: {uip.Address}, destination IP-address: {ipAddressString ?? "broadcast"}");
if (ipAddress != null)
{
var localEP = new IPEndPoint(uip.Address, 0);
SendWolToIpAddress(uip.Address, ipAddress, data, physicalAddress);
}
BroadcastWol(uip.Address, IPAddress.Broadcast, data);
var parts = uip.Address.ToString().Split(".").ToList();
parts[3] = "0";
var broadcastAddress = IPAddress.Parse(string.Join(".", parts));
BroadcastWol(uip.Address, broadcastAddress, data);
result = true;
}
}
catch (Exception ex)
@@ -110,5 +140,117 @@ namespace ColorControl.Common
}
return packet;
}
}
private static void BroadcastWol(IPAddress localAddress, IPAddress broadCastAddress, byte[] data)
{
//var localEP = new IPEndPoint(localAddress, 0);
var udpc = new UdpClient();
udpc.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
//udpc.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontRoute, 1);
var target = new IPEndPoint(broadCastAddress, DefaultWolPort);
udpc.Send(data, data.Length, target);
}
private static void SendWolToIpAddress(IPAddress localAddress, IPAddress remoteAddress, byte[] data, PhysicalAddress physicalAddress)
{
//var localEP = new IPEndPoint(localAddress, 0);
var netLuid = CreateTransientLocalNetEntry(remoteAddress, physicalAddress);
try
{
var udpc = new UdpClient();
udpc.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
var target = new IPEndPoint(remoteAddress, DefaultWolPort);
udpc.Send(data, data.Length, target);
}
finally
{
DeleteNetEntry(netLuid, remoteAddress);
}
}
private static NET_LUID CreateTransientLocalNetEntry(IPAddress ipAddress, PhysicalAddress macAddress)
{
var ipBytes = ipAddress.GetAddressBytes();
var address = new Ws2_32.SOCKADDR_INET
{
si_family = Ws2_32.ADDRESS_FAMILY.AF_INET,
Ipv4 = new Ws2_32.SOCKADDR_IN(new Ws2_32.IN_ADDR(ipBytes), DefaultWolPort),
};
var net = new NET_LUID();
var addr = new Ws2_32.SOCKADDR_INET();
MIB_IPFORWARD_ROW2 forwardRow;
var result = GetBestRoute2(net, 0, addr, address, 0, out forwardRow, out _);
if (result != Win32Error.ERROR_SUCCESS)
{
Logger.Debug($"Cannot find best route: {result}");
var luidDummy = new NET_LUID();
return luidDummy;
}
var luid = forwardRow.InterfaceLuid;
var macAddressBytes = macAddress.GetAddressBytes();
var bytes = new byte[32];
macAddressBytes.CopyTo(bytes, 0);
var row = new MIB_IPNET_ROW2
{
Address = address,
InterfaceLuid = luid,
PhysicalAddress = bytes,
PhysicalAddressLength = 6
};
result = CreateIpNetEntry2(ref row);
if (result != Win32Error.ERROR_SUCCESS)
{
Logger.Debug($"Cannot create ip net entry: {result}");
}
return luid;
}
private static void DeleteNetEntry(NET_LUID luid, IPAddress ipAddress)
{
if (luid.Value == 0)
{
return;
}
var ipBytes = ipAddress.GetAddressBytes();
var address = new Ws2_32.SOCKADDR_INET
{
si_family = Ws2_32.ADDRESS_FAMILY.AF_INET,
Ipv4 = new Ws2_32.SOCKADDR_IN(new Ws2_32.IN_ADDR(ipBytes), DefaultWolPort)
};
var row = new MIB_IPNET_ROW2
{
Address = address,
InterfaceLuid = luid,
};
var result = DeleteIpNetEntry2(ref row);
if (result != Win32Error.ERROR_SUCCESS)
{
Logger.Debug($"Cannot delete ip net entry: {result}");
}
}
}
}
+12
View File
@@ -2,6 +2,14 @@
namespace ColorControl
{
public enum ElevationMethod
{
None = 0,
RunAsAdmin = 1,
UseService = 2,
UseElevatedProcess = 3
}
public class ListViewSortState
{
public SortOrder SortOrder { get; set; }
@@ -31,6 +39,8 @@ namespace ColorControl
public string LgQuickAccessShortcut { get; set; }
public string GameQuickAccessShortcut { get; set; }
public bool UseDedicatedElevatedProcess { get; set; }
public ElevationMethod ElevationMethod { get; set; }
public bool ElevationMethodAsked { get; set; }
public Config()
{
@@ -43,6 +53,8 @@ namespace ColorControl
FixChromeFonts = false;
UseGdiScaling = true;
UseDedicatedElevatedProcess = false;
ElevationMethod = ElevationMethod.None;
ElevationMethodAsked = false;
LgPresetsSortState = new ListViewSortState();
NvPresetsSortState = new ListViewSortState();
AmdPresetsSortState = new ListViewSortState();
+9 -2
View File
@@ -49,7 +49,7 @@ namespace ColorControl.Forms
var container = (WinApi.COPYDATASTRUCT)m.GetLParam(typeof(WinApi.COPYDATASTRUCT));
var message = Marshal.PtrToStringAnsi(container.lpData);
File.AppendAllLines("d:\\Msg.txt", new[] { "Message received: " + message });
//File.AppendAllLines("d:\\Msg.txt", new[] { "Message received: " + message });
HandleMessage(message);
@@ -69,7 +69,14 @@ namespace ColorControl.Forms
var startUpParams = StartUpParams.Parse(args);
Program.HandleStartupParams(startUpParams, null);
try
{
Program.HandleStartupParams(startUpParams, null);
}
catch (Exception)
{
}
}
private void CheckMutexAsync()
+155 -33
View File
@@ -231,6 +231,13 @@
this.edtDelayDisplaySettings = new System.Windows.Forms.NumericUpDown();
this.label6 = new System.Windows.Forms.Label();
this.grpGeneralOptions = new System.Windows.Forms.GroupBox();
this.btnStartStopService = new System.Windows.Forms.Button();
this.btnElevationInfo = new System.Windows.Forms.Button();
this.rbElevationService = new System.Windows.Forms.RadioButton();
this.rbElevationProcess = new System.Windows.Forms.RadioButton();
this.rbElevationAdmin = new System.Windows.Forms.RadioButton();
this.label8 = new System.Windows.Forms.Label();
this.rbElevationNone = new System.Windows.Forms.RadioButton();
this.chkGdiScaling = new System.Windows.Forms.CheckBox();
this.chkCheckForUpdates = new System.Windows.Forms.CheckBox();
this.chkMinimizeToSystemTray = new System.Windows.Forms.CheckBox();
@@ -238,6 +245,8 @@
this.chkStartMinimized = new System.Windows.Forms.CheckBox();
this.chkStartAfterLogin = new System.Windows.Forms.CheckBox();
this.tabLog = new System.Windows.Forms.TabPage();
this.lblShowLog = new System.Windows.Forms.Label();
this.cbxLogType = new System.Windows.Forms.ComboBox();
this.btnClearLog = new System.Windows.Forms.Button();
this.edtLog = new System.Windows.Forms.TextBox();
this.tabInfo = new System.Windows.Forms.TabPage();
@@ -251,7 +260,6 @@
this.mnuNvSettings = new System.Windows.Forms.ContextMenuStrip(this.components);
this.miNvProfileInspector = new System.Windows.Forms.ToolStripMenuItem();
this.miNvSettings = new System.Windows.Forms.ToolStripMenuItem();
this.chkOptionsDedicatedElevatedProcess = new System.Windows.Forms.CheckBox();
this.tcMain.SuspendLayout();
this.tabNVIDIA.SuspendLayout();
this.mnuNvPresets.SuspendLayout();
@@ -2237,11 +2245,11 @@
this.grpNvidiaOptions.Controls.Add(this.cbxDitheringBitDepth);
this.grpNvidiaOptions.Controls.Add(this.chkDitheringEnabled);
this.grpNvidiaOptions.Controls.Add(this.pbGradient);
this.grpNvidiaOptions.Location = new System.Drawing.Point(481, 7);
this.grpNvidiaOptions.Location = new System.Drawing.Point(537, 7);
this.grpNvidiaOptions.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.grpNvidiaOptions.Name = "grpNvidiaOptions";
this.grpNvidiaOptions.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.grpNvidiaOptions.Size = new System.Drawing.Size(625, 351);
this.grpNvidiaOptions.Size = new System.Drawing.Size(569, 351);
this.grpNvidiaOptions.TabIndex = 6;
this.grpNvidiaOptions.TabStop = false;
this.grpNvidiaOptions.Text = "NVIDIA options - test dithering";
@@ -2312,7 +2320,7 @@
this.pbGradient.Location = new System.Drawing.Point(7, 106);
this.pbGradient.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.pbGradient.Name = "pbGradient";
this.pbGradient.Size = new System.Drawing.Size(611, 236);
this.pbGradient.Size = new System.Drawing.Size(555, 236);
this.pbGradient.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.pbGradient.TabIndex = 0;
this.pbGradient.TabStop = false;
@@ -2324,11 +2332,11 @@
this.grpMiscellaneousOptions.Controls.Add(this.edtBlankScreenSaverShortcut);
this.grpMiscellaneousOptions.Controls.Add(this.lblFixChromeFontsDescription);
this.grpMiscellaneousOptions.Controls.Add(this.chkFixChromeFonts);
this.grpMiscellaneousOptions.Location = new System.Drawing.Point(7, 332);
this.grpMiscellaneousOptions.Location = new System.Drawing.Point(7, 365);
this.grpMiscellaneousOptions.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.grpMiscellaneousOptions.Name = "grpMiscellaneousOptions";
this.grpMiscellaneousOptions.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.grpMiscellaneousOptions.Size = new System.Drawing.Size(467, 150);
this.grpMiscellaneousOptions.Size = new System.Drawing.Size(522, 150);
this.grpMiscellaneousOptions.TabIndex = 5;
this.grpMiscellaneousOptions.TabStop = false;
this.grpMiscellaneousOptions.Text = "Miscellaneous";
@@ -2399,11 +2407,11 @@
this.grpLGOptions.Controls.Add(this.lblLgMaxPowerOnRetriesDescription);
this.grpLGOptions.Controls.Add(this.edtLgMaxPowerOnRetries);
this.grpLGOptions.Controls.Add(this.lblLgMaxPowerOnRetries);
this.grpLGOptions.Location = new System.Drawing.Point(7, 136);
this.grpLGOptions.Location = new System.Drawing.Point(7, 169);
this.grpLGOptions.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.grpLGOptions.Name = "grpLGOptions";
this.grpLGOptions.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.grpLGOptions.Size = new System.Drawing.Size(470, 190);
this.grpLGOptions.Size = new System.Drawing.Size(522, 190);
this.grpLGOptions.TabIndex = 4;
this.grpLGOptions.TabStop = false;
this.grpLGOptions.Text = "LG controller";
@@ -2411,7 +2419,7 @@
// lblGameBarShortcut
//
this.lblGameBarShortcut.AutoSize = true;
this.lblGameBarShortcut.Location = new System.Drawing.Point(201, 127);
this.lblGameBarShortcut.Location = new System.Drawing.Point(266, 127);
this.lblGameBarShortcut.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.lblGameBarShortcut.Name = "lblGameBarShortcut";
this.lblGameBarShortcut.Size = new System.Drawing.Size(108, 15);
@@ -2420,7 +2428,7 @@
//
// edtLgGameBarShortcut
//
this.edtLgGameBarShortcut.Location = new System.Drawing.Point(307, 121);
this.edtLgGameBarShortcut.Location = new System.Drawing.Point(386, 121);
this.edtLgGameBarShortcut.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.edtLgGameBarShortcut.Name = "edtLgGameBarShortcut";
this.edtLgGameBarShortcut.ReadOnly = true;
@@ -2447,7 +2455,7 @@
0,
0,
0});
this.edtLgOptionShutdownDelay.Location = new System.Drawing.Point(349, 68);
this.edtLgOptionShutdownDelay.Location = new System.Drawing.Point(428, 68);
this.edtLgOptionShutdownDelay.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.edtLgOptionShutdownDelay.Maximum = new decimal(new int[] {
5000,
@@ -2507,7 +2515,7 @@
//
// edtLgMaxPowerOnRetries
//
this.edtLgMaxPowerOnRetries.Location = new System.Drawing.Point(349, 20);
this.edtLgMaxPowerOnRetries.Location = new System.Drawing.Point(428, 20);
this.edtLgMaxPowerOnRetries.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.edtLgMaxPowerOnRetries.Maximum = new decimal(new int[] {
25,
@@ -2535,11 +2543,11 @@
//
this.grpHDROptions.Controls.Add(this.edtDelayDisplaySettings);
this.grpHDROptions.Controls.Add(this.label6);
this.grpHDROptions.Location = new System.Drawing.Point(481, 365);
this.grpHDROptions.Location = new System.Drawing.Point(537, 365);
this.grpHDROptions.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.grpHDROptions.Name = "grpHDROptions";
this.grpHDROptions.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.grpHDROptions.Size = new System.Drawing.Size(467, 83);
this.grpHDROptions.Size = new System.Drawing.Size(569, 83);
this.grpHDROptions.TabIndex = 3;
this.grpHDROptions.TabStop = false;
this.grpHDROptions.Text = "HDR";
@@ -2578,7 +2586,13 @@
//
// grpGeneralOptions
//
this.grpGeneralOptions.Controls.Add(this.chkOptionsDedicatedElevatedProcess);
this.grpGeneralOptions.Controls.Add(this.btnStartStopService);
this.grpGeneralOptions.Controls.Add(this.btnElevationInfo);
this.grpGeneralOptions.Controls.Add(this.rbElevationService);
this.grpGeneralOptions.Controls.Add(this.rbElevationProcess);
this.grpGeneralOptions.Controls.Add(this.rbElevationAdmin);
this.grpGeneralOptions.Controls.Add(this.label8);
this.grpGeneralOptions.Controls.Add(this.rbElevationNone);
this.grpGeneralOptions.Controls.Add(this.chkGdiScaling);
this.grpGeneralOptions.Controls.Add(this.chkCheckForUpdates);
this.grpGeneralOptions.Controls.Add(this.chkMinimizeToSystemTray);
@@ -2589,15 +2603,101 @@
this.grpGeneralOptions.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.grpGeneralOptions.Name = "grpGeneralOptions";
this.grpGeneralOptions.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.grpGeneralOptions.Size = new System.Drawing.Size(467, 122);
this.grpGeneralOptions.Size = new System.Drawing.Size(522, 156);
this.grpGeneralOptions.TabIndex = 2;
this.grpGeneralOptions.TabStop = false;
this.grpGeneralOptions.Text = "General";
//
// btnStartStopService
//
this.btnStartStopService.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnStartStopService.Location = new System.Drawing.Point(474, 103);
this.btnStartStopService.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.btnStartStopService.Name = "btnStartStopService";
this.btnStartStopService.Size = new System.Drawing.Size(40, 27);
this.btnStartStopService.TabIndex = 65;
this.btnStartStopService.Text = "Start";
this.btnStartStopService.UseVisualStyleBackColor = true;
this.btnStartStopService.Click += new System.EventHandler(this.btnStartStopService_Click);
//
// btnElevationInfo
//
this.btnElevationInfo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnElevationInfo.Location = new System.Drawing.Point(329, 41);
this.btnElevationInfo.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.btnElevationInfo.Name = "btnElevationInfo";
this.btnElevationInfo.Size = new System.Drawing.Size(22, 27);
this.btnElevationInfo.TabIndex = 64;
this.btnElevationInfo.Text = "?";
this.btnElevationInfo.UseVisualStyleBackColor = true;
this.btnElevationInfo.Click += new System.EventHandler(this.btnElevationInfo_Click);
//
// rbElevationService
//
this.rbElevationService.AutoSize = true;
this.rbElevationService.Location = new System.Drawing.Point(216, 107);
this.rbElevationService.Name = "rbElevationService";
this.rbElevationService.Size = new System.Drawing.Size(136, 19);
this.rbElevationService.TabIndex = 63;
this.rbElevationService.TabStop = true;
this.rbElevationService.Tag = "2";
this.rbElevationService.Text = "Use Windows Service";
this.rbElevationService.UseVisualStyleBackColor = true;
this.rbElevationService.CheckedChanged += new System.EventHandler(this.rbElevationNone_CheckedChanged);
//
// rbElevationProcess
//
this.rbElevationProcess.AutoSize = true;
this.rbElevationProcess.Location = new System.Drawing.Point(216, 128);
this.rbElevationProcess.Name = "rbElevationProcess";
this.rbElevationProcess.Size = new System.Drawing.Size(189, 19);
this.rbElevationProcess.TabIndex = 62;
this.rbElevationProcess.TabStop = true;
this.rbElevationProcess.Tag = "3";
this.rbElevationProcess.Text = "Use dedicated elevated process";
this.rbElevationProcess.UseVisualStyleBackColor = true;
this.rbElevationProcess.CheckedChanged += new System.EventHandler(this.rbElevationNone_CheckedChanged);
//
// rbElevationAdmin
//
this.rbElevationAdmin.AutoSize = true;
this.rbElevationAdmin.Location = new System.Drawing.Point(216, 86);
this.rbElevationAdmin.Name = "rbElevationAdmin";
this.rbElevationAdmin.Size = new System.Drawing.Size(97, 19);
this.rbElevationAdmin.TabIndex = 61;
this.rbElevationAdmin.TabStop = true;
this.rbElevationAdmin.Tag = "1";
this.rbElevationAdmin.Text = "Run as admin";
this.rbElevationAdmin.UseVisualStyleBackColor = true;
this.rbElevationAdmin.CheckedChanged += new System.EventHandler(this.rbElevationNone_CheckedChanged);
//
// label8
//
this.label8.AutoSize = true;
this.label8.Location = new System.Drawing.Point(216, 47);
this.label8.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.label8.Name = "label8";
this.label8.Size = new System.Drawing.Size(105, 15);
this.label8.TabIndex = 60;
this.label8.Text = "Elevation-method:";
//
// rbElevationNone
//
this.rbElevationNone.AutoSize = true;
this.rbElevationNone.Location = new System.Drawing.Point(216, 65);
this.rbElevationNone.Name = "rbElevationNone";
this.rbElevationNone.Size = new System.Drawing.Size(54, 19);
this.rbElevationNone.TabIndex = 10;
this.rbElevationNone.TabStop = true;
this.rbElevationNone.Tag = "0";
this.rbElevationNone.Text = "None";
this.rbElevationNone.UseVisualStyleBackColor = true;
this.rbElevationNone.CheckedChanged += new System.EventHandler(this.rbElevationNone_CheckedChanged);
//
// chkGdiScaling
//
this.chkGdiScaling.AutoSize = true;
this.chkGdiScaling.Location = new System.Drawing.Point(238, 72);
this.chkGdiScaling.Location = new System.Drawing.Point(216, 22);
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);
@@ -2609,7 +2709,7 @@
// chkCheckForUpdates
//
this.chkCheckForUpdates.AutoSize = true;
this.chkCheckForUpdates.Location = new System.Drawing.Point(238, 47);
this.chkCheckForUpdates.Location = new System.Drawing.Point(7, 122);
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);
@@ -2621,7 +2721,7 @@
// chkMinimizeToSystemTray
//
this.chkMinimizeToSystemTray.AutoSize = true;
this.chkMinimizeToSystemTray.Location = new System.Drawing.Point(238, 22);
this.chkMinimizeToSystemTray.Location = new System.Drawing.Point(7, 97);
this.chkMinimizeToSystemTray.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.chkMinimizeToSystemTray.Name = "chkMinimizeToSystemTray";
this.chkMinimizeToSystemTray.Size = new System.Drawing.Size(152, 19);
@@ -2667,6 +2767,8 @@
//
// tabLog
//
this.tabLog.Controls.Add(this.lblShowLog);
this.tabLog.Controls.Add(this.cbxLogType);
this.tabLog.Controls.Add(this.btnClearLog);
this.tabLog.Controls.Add(this.edtLog);
this.tabLog.Location = new System.Drawing.Point(4, 24);
@@ -2678,9 +2780,33 @@
this.tabLog.Text = "Log";
this.tabLog.UseVisualStyleBackColor = true;
//
// lblShowLog
//
this.lblShowLog.AutoSize = true;
this.lblShowLog.Location = new System.Drawing.Point(8, 14);
this.lblShowLog.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.lblShowLog.Name = "lblShowLog";
this.lblShowLog.Size = new System.Drawing.Size(88, 15);
this.lblShowLog.TabIndex = 33;
this.lblShowLog.Text = "Show log from:";
//
// cbxLogType
//
this.cbxLogType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cbxLogType.FormattingEnabled = true;
this.cbxLogType.Items.AddRange(new object[] {
"Main application",
"Service"});
this.cbxLogType.Location = new System.Drawing.Point(102, 9);
this.cbxLogType.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.cbxLogType.Name = "cbxLogType";
this.cbxLogType.Size = new System.Drawing.Size(189, 23);
this.cbxLogType.TabIndex = 32;
this.cbxLogType.SelectedIndexChanged += new System.EventHandler(this.cbxLogType_SelectedIndexChanged);
//
// btnClearLog
//
this.btnClearLog.Location = new System.Drawing.Point(7, 7);
this.btnClearLog.Location = new System.Drawing.Point(299, 6);
this.btnClearLog.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.btnClearLog.Name = "btnClearLog";
this.btnClearLog.Size = new System.Drawing.Size(88, 27);
@@ -2824,18 +2950,6 @@
this.miNvSettings.Text = "Settings";
this.miNvSettings.Click += new System.EventHandler(this.miNvSettings_Click);
//
// chkOptionsDedicatedElevatedProcess
//
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
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
@@ -3124,7 +3238,15 @@
private System.Windows.Forms.ContextMenuStrip mnuGameOptions;
private System.Windows.Forms.ToolStripMenuItem miGameProcessorAffinity;
private System.Windows.Forms.ToolStripMenuItem miGameProcessPriority;
private System.Windows.Forms.CheckBox chkOptionsDedicatedElevatedProcess;
private System.Windows.Forms.RadioButton rbElevationService;
private System.Windows.Forms.RadioButton rbElevationProcess;
private System.Windows.Forms.RadioButton rbElevationAdmin;
private System.Windows.Forms.Label label8;
private System.Windows.Forms.RadioButton rbElevationNone;
private System.Windows.Forms.Button btnElevationInfo;
private System.Windows.Forms.Button btnStartStopService;
private System.Windows.Forms.Label lblShowLog;
private System.Windows.Forms.ComboBox cbxLogType;
}
}
+293 -47
View File
@@ -7,8 +7,8 @@ using ColorControl.Services.Common;
using ColorControl.Services.GameLauncher;
using ColorControl.Services.LG;
using ColorControl.Services.NVIDIA;
using ColorControl.Svc;
using LgTv;
using Newtonsoft.Json;
using NLog;
using nspector;
using nspector.Common;
@@ -28,7 +28,6 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
@@ -77,7 +76,6 @@ namespace ColorControl
private bool _updatingDitherSettings;
private LgGameBar _gameBarForm;
private QuickAccessForm<GamePreset> _gameQuickAccessForm;
private GameService _gameService;
@@ -125,7 +123,7 @@ namespace ColorControl
_trayIcon.ContextMenuStrip.Opened += trayIconContextMenu_Popup;
_trayIcon.BalloonTipClicked += trayIconBalloonTip_Clicked;
chkStartAfterLogin.Checked = Utils.TaskExists(Program.TS_TASKNAME, true);
chkStartAfterLogin.Checked = Utils.TaskExists(Program.TS_TASKNAME);
chkFixChromeFonts.Enabled = Utils.IsChromeInstalled();
if (chkFixChromeFonts.Enabled)
@@ -140,12 +138,15 @@ namespace ColorControl
_shortcuts.Add(SHORTCUTID_SCREENSAVER, StartScreenSaver);
//Utils.StartService();
InitLgService();
InitNvService();
InitAmdService();
InitGameService();
InitInfo();
UpdateServiceInfo();
UserSessionInfo.Install();
_screenStateNotify = WinApi.RegisterPowerSettingNotification(Handle, ref Utils.GUID_CONSOLE_DISPLAY_STATE, 0);
@@ -154,9 +155,36 @@ namespace ColorControl
_initialized = true;
//Task.Run(() => Utils.StartPipeAsync());
AfterInitialized();
}
private void UpdateServiceInfo()
{
var text = "Use Windows Service";
btnStartStopService.Enabled = true;
if (Utils.IsServiceRunning())
{
text += " (running)";
btnStartStopService.Text = "Stop";
}
else if (Utils.IsServiceInstalled())
{
text += " (installed, not running)";
btnStartStopService.Text = "Start";
}
else
{
text += " (not installed)";
btnStartStopService.Text = "Start";
btnStartStopService.Enabled = false;
}
rbElevationService.Text = text;
}
private void InitNvService()
{
try
@@ -361,6 +389,11 @@ namespace ColorControl
Text = Application.ProductName + " " + Application.ProductVersion;
//}
if (Utils.IsAdministrator())
{
Text += " (administrator)";
}
lblInfo.Text = Text + " - " + _currentVersionInfo.LegalCopyright;
lbPlugins.Items.Add("lgtv.net by gr4b4z");
@@ -817,7 +850,13 @@ namespace ColorControl
return;
}
var enabled = chkStartAfterLogin.Checked;
Utils.RegisterTask(Program.TS_TASKNAME, enabled);
RegisterScheduledTask(enabled);
rbElevationAdmin.Enabled = enabled;
if (!enabled && rbElevationAdmin.Checked)
{
rbElevationNone.Checked = true;
}
}
private void LoadConfig()
@@ -829,7 +868,6 @@ namespace ColorControl
edtDelayDisplaySettings.Value = _config.DisplaySettingsDelay;
edtBlankScreenSaverShortcut.Text = _config.ScreenSaverShortcut;
chkGdiScaling.Checked = _config.UseGdiScaling;
chkOptionsDedicatedElevatedProcess.Checked = _config.UseDedicatedElevatedProcess;
if (!string.IsNullOrEmpty(_config.ScreenSaverShortcut))
{
@@ -857,15 +895,7 @@ namespace ColorControl
_config.FormHeight = Height;
}
try
{
var data = JsonConvert.SerializeObject(_config);
File.WriteAllText(Program.ConfigFilename, data);
}
catch (Exception e)
{
Logger.Error(e.ToLogString());
}
Utils.WriteObject(Program.ConfigFilename, _config);
}
private void ShowControls(Control parent, bool show = true, Control exclude = null)
@@ -907,6 +937,44 @@ namespace ColorControl
InitSelectedTab();
CheckForUpdates();
CheckElevationMethod();
}
private void CheckElevationMethod()
{
if (Utils.IsAdministrator())
{
return;
}
if (_config.ElevationMethodAsked)
{
if (_config.ElevationMethod == ElevationMethod.UseService && !Utils.IsServiceInstalled() &&
(MessageForms.QuestionYesNo("The elevation method is set to Windows Service but it is not installed. Do you want to install it now?") == DialogResult.Yes))
{
Utils.InstallService();
}
else if (_config.ElevationMethod == ElevationMethod.UseService && !Utils.IsServiceRunning() &&
(MessageForms.QuestionYesNo("The elevation method is set to Windows Service but it is not running. Do you want to start it now?") == DialogResult.Yes))
{
Utils.StartService();
}
return;
}
var result = MessageForms.QuestionYesNo(Utils.ELEVATION_MSG + @"
Do you want to install and start the Windows Service now? You can always change this on the Options-tab page.
NOTE: installing the service may cause a User Account Control popup.");
if (result == DialogResult.Yes)
{
SetElevationMethod(ElevationMethod.UseService);
}
_config.ElevationMethodAsked = true;
}
protected override void SetVisibleCore(bool value)
@@ -1692,6 +1760,24 @@ namespace ColorControl
UpdateDitherSettings();
}
_initialized = false;
try
{
var _ = _config.ElevationMethod switch
{
ElevationMethod.None => rbElevationNone.Checked = true,
ElevationMethod.RunAsAdmin => rbElevationAdmin.Checked = true,
ElevationMethod.UseService => rbElevationService.Checked = true,
ElevationMethod.UseElevatedProcess => rbElevationProcess.Checked = true
};
}
finally
{
_initialized = true;
}
UpdateServiceInfo();
}
private void UpdateDitherSettings()
@@ -2059,36 +2145,44 @@ namespace ColorControl
private void LoadLog()
{
var filename = Path.Combine(_dataDir, "LogFile.txt");
var logType = cbxLogType.SelectedIndex;
var lines = new List<string> { "No log file found" };
try
if (logType == -1)
{
if (File.Exists(filename))
cbxLogType.SelectedIndex = 0;
return;
}
string text;
if (logType == 0)
{
var filename = Path.Combine(_dataDir, "LogFile.txt");
text = Utils.ReadText(filename);
text ??= "No log file found";
}
else
{
if (Utils.IsServiceRunning())
{
using var fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
var message = new SvcMessage { MessageType = SvcMessageType.GetLog };
using var reader = new StreamReader(fs);
var result = PipeUtils.SendMessage(message);
String line;
while ((line = reader.ReadLine()) != null)
{
lines.Add(line);
}
//lines = File.ReadAllLines(filename);
text = result?.Data ?? "Cannot get log from service";
}
else
{
text = "The service is not installed or not running";
}
}
catch (Exception ex)
{
lines = new List<string> { $"Cannot load log file: {ex.Message}" };
}
var reversedLines = lines.ToList();
var builder = new StringBuilder();
reversedLines.ForEach(line => builder.AppendLine(line));
edtLog.Text = builder.ToString();
edtLog.Text = text;
edtLog.SelectionStart = text.Length;
edtLog.ScrollToCaret();
}
private void LoadInfo()
@@ -2401,12 +2495,26 @@ Do you want to continue?";
private void btnClearLog_Click(object sender, EventArgs e)
{
var filename = Path.Combine(_dataDir, "LogFile.txt");
if (File.Exists(filename))
var logType = cbxLogType.SelectedIndex;
if (logType == -1)
{
File.Delete(filename);
edtLog.Clear();
return;
}
if (logType == 0)
{
var filename = Program.LogFilename;
if (File.Exists(filename))
{
File.Delete(filename);
}
}
else
{
PipeUtils.SendMessage(SvcMessageType.ClearLog);
}
edtLog.Clear();
}
private void edtLgDeviceFilter_TextChanged(object sender, EventArgs e)
@@ -3652,7 +3760,8 @@ The InStart and Software Update items are now visible under the Expert-button."
var fileName = Path.GetFileNameWithoutExtension(preset.Path);
preset.name = versionInfo.FileDescription ?? versionInfo.ProductName ?? fileName;
preset.name = !string.IsNullOrEmpty(versionInfo.FileDescription) ? versionInfo.FileDescription :
!string.IsNullOrEmpty(versionInfo.ProductName) ? versionInfo.ProductName : fileName;
}
AddOrUpdateItemGame(preset);
@@ -4066,13 +4175,150 @@ The InStart and Software Update items are now visible under the Expert-button."
var enumValue = Enum.Parse(typeof(GamePriorityClass), value);
preset.ProcessPriorityClass = (uint)(int)enumValue;
}
private void chkOptionsDedicatedElevatedProcess_CheckedChanged(object sender, EventArgs e)
private void rbElevationNone_CheckedChanged(object sender, EventArgs e)
{
_config.UseDedicatedElevatedProcess = chkOptionsDedicatedElevatedProcess.Checked;
Utils.UseDedicatedElevatedProcess = _config.UseDedicatedElevatedProcess;
if (!_initialized)
{
return;
}
if (sender is not RadioButton button || !button.Checked)
{
return;
}
SetElevationMethod((ElevationMethod)Utils.ParseInt((string)button.Tag));
}
private void SetElevationMethod(ElevationMethod elevationMethod)
{
_config.ElevationMethod = elevationMethod;
Utils.UseDedicatedElevatedProcess = _config.ElevationMethod == ElevationMethod.UseElevatedProcess;
var _ = _config.ElevationMethod switch
{
ElevationMethod.None => SetElevationMethodNone(),
ElevationMethod.RunAsAdmin => SetElevationMethodRunAsAdmin(),
ElevationMethod.UseService => SetElevationMethodUseService(),
ElevationMethod.UseElevatedProcess => SetElevationMethodUseElevatedProcess(),
_ => true
};
UpdateServiceInfo();
}
private bool SetElevationMethodNone()
{
if (chkStartAfterLogin.Enabled)
{
RegisterScheduledTask();
}
Utils.UninstallService();
return true;
}
private bool SetElevationMethodRunAsAdmin()
{
if (chkStartAfterLogin.Enabled)
{
RegisterScheduledTask(false);
RegisterScheduledTask();
}
Utils.UninstallService();
return true;
}
private bool SetElevationMethodUseService()
{
Utils.InstallService();
if (Utils.IsServiceInstalled())
{
MessageForms.InfoOk("Service installed successfully.");
return true;
}
MessageForms.ErrorOk("Service could not be installed. Check the logs.");
return false;
}
private bool SetElevationMethodUseElevatedProcess()
{
if (chkStartAfterLogin.Enabled)
{
RegisterScheduledTask();
}
Utils.UninstallService();
return true;
}
private void RegisterScheduledTask(bool enabled = true)
{
Utils.RegisterTask(Program.TS_TASKNAME, enabled, _config.ElevationMethod == ElevationMethod.RunAsAdmin ? Microsoft.Win32.TaskScheduler.TaskRunLevel.Highest : Microsoft.Win32.TaskScheduler.TaskRunLevel.LUA);
}
private void btnElevationInfo_Click(object sender, EventArgs e)
{
MessageForms.InfoOk(Utils.ELEVATION_MSG + @$"
NOTE: if ColorControl itself already runs as administrator this is indicated in the title: ColorControl {Application.ProductVersion} (administrator).
Currently ColorControl is {(Utils.IsAdministrator() ? "" : "not ")}running as administrator.
");
}
private void btnStartStopService_Click(object sender, EventArgs e)
{
btnStartStopService.Enabled = false;
try
{
var start = btnStartStopService.Text == "Start";
if (start)
{
Utils.StartService();
}
else
{
Utils.StopService();
}
var wait = 1000;
while (wait > 0)
{
Utils.WaitForTask(Task.Delay(100));
if (start == Utils.IsServiceRunning())
{
break;
}
wait -= 100;
}
}
finally
{
btnStartStopService.Enabled = true;
}
UpdateServiceInfo();
}
private void cbxLogType_SelectedIndexChanged(object sender, EventArgs e)
{
LoadLog();
}
}
}
+79 -6
View File
@@ -3,13 +3,18 @@ using ColorControl.Forms;
using ColorControl.Services.AMD;
using ColorControl.Services.LG;
using ColorControl.Services.NVIDIA;
using ColorControl.Svc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using NLog;
using NWin32;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ColorControl
@@ -19,6 +24,7 @@ namespace ColorControl
public const string TS_TASKNAME = "ColorControl";
public static string DataDir { get; private set; }
public static string ConfigFilename { get; private set; }
public static string LogFilename { get; private set; }
public static Config Config { get; private set; }
public static AppContext AppContext { get; private set; }
@@ -32,6 +38,20 @@ namespace ColorControl
[STAThread]
static void Main(string[] args)
{
DataDir = Utils.GetDataPath();
var runAsService = args.Contains("--service") || Process.GetCurrentProcess().Parent()?.ProcessName?.Equals("services", StringComparison.InvariantCultureIgnoreCase) == true;
InitLogger(runAsService);
Logger.Debug("Parent process: " + Process.GetCurrentProcess().Parent()?.ProcessName);
if (runAsService)
{
Utils.WaitForTask(RunService(args));
return;
}
MutexId = $"Global\\{typeof(MainForm).GUID}";
var currentDomain = AppDomain.CurrentDomain;
@@ -40,9 +60,6 @@ namespace ColorControl
// Handler for exceptions in threads behind forms.
Application.ThreadException += GlobalThreadExceptionHandler;
DataDir = Utils.GetDataPath();
InitLogger();
LoadConfig();
if (Config.UseGdiScaling)
@@ -88,10 +105,19 @@ namespace ColorControl
mutex.WaitOne();
try
{
if (Debugger.IsAttached)
{
Utils.StartService();
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm(AppContext));
if (Debugger.IsAttached)
{
Utils.StopService();
}
}
catch (Exception ex)
{
@@ -108,12 +134,17 @@ namespace ColorControl
}
}
private static void InitLogger()
private static void InitLogger(bool runAsService)
{
var config = new NLog.Config.LoggingConfiguration();
// Targets where to log to: File and Console
var logfile = new NLog.Targets.FileTarget("logfile") { FileName = Path.Combine(DataDir, "LogFile.txt") };
var logFileAppendix = runAsService ? "_svc" : "";
LogFilename = Path.Combine(DataDir, $"LogFile{logFileAppendix}.txt");
var logfile = new NLog.Targets.FileTarget("logfile") { FileName = LogFilename };
//var logconsole = new NLog.Targets.ConsoleTarget("logconsole");
// Rules for mapping loggers to targets
@@ -154,7 +185,7 @@ namespace ColorControl
}
if (startUpParams.EnableAutoStart || startUpParams.DisableAutoStart)
{
Utils.RegisterTask(TS_TASKNAME, startUpParams.EnableAutoStart);
Utils.RegisterTask(TS_TASKNAME, startUpParams.EnableAutoStart, startUpParams.AutoStartRunLevel);
return true;
}
if (startUpParams.SetProcessAffinity)
@@ -172,6 +203,30 @@ namespace ColorControl
StartElevated();
return true;
}
if (startUpParams.SendWol)
{
return WOL.WakeFunction(startUpParams.WolMacAddress, startUpParams.WolIpAddress);
}
if (startUpParams.InstallService)
{
Utils.InstallService();
return true;
}
if (startUpParams.UninstallService)
{
Utils.UninstallService();
return true;
}
if (startUpParams.StartService)
{
Utils.StartService();
return true;
}
if (startUpParams.StopService)
{
Utils.StopService();
return true;
}
var useConsole = startUpParams.NoGui || existingProcess != null;
@@ -263,6 +318,24 @@ namespace ColorControl
}
}
private static async Task RunService(string[] args)
{
Logger.Debug("RUNNING SERVICE");
using IHost host = Host.CreateDefaultBuilder(args)
.UseWindowsService(options =>
{
options.ServiceName = "ColorControl Service";
})
.ConfigureServices(services =>
{
services.AddHostedService<ColorControlBackgroundService>();
})
.Build();
await host.RunAsync();
}
public static int EnumThreadWindows(IntPtr handle, IntPtr param)
{
NativeMethods.SendMessageW(handle, Utils.WM_BRINGTOFRONT, UIntPtr.Zero, IntPtr.Zero);
+1 -11
View File
@@ -1,10 +1,8 @@
using ATI.ADL;
using ColorControl.Common;
using ColorControl.Services.Common;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;
@@ -52,15 +50,7 @@ namespace ColorControl.Services.AMD
private void SavePresets()
{
try
{
var json = JsonConvert.SerializeObject(_presets);
File.WriteAllText(_presetsFilename, json);
}
catch (Exception e)
{
Logger.Error(e.ToLogString());
}
Utils.WriteObject(_presetsFilename, _presets);
}
public void GlobalSave()
@@ -1,9 +1,7 @@
using ColorControl.Common;
using ColorControl.Services.Common;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
namespace ColorControl.Services.GameLauncher
@@ -51,15 +49,7 @@ namespace ColorControl.Services.GameLauncher
private void SavePresets()
{
try
{
var json = JsonConvert.SerializeObject(_presets);
File.WriteAllText(_presetsFilename, json);
}
catch (Exception e)
{
Logger.Error(e.ToLogString());
}
Utils.WriteObject(_presetsFilename, _presets);
}
public void GlobalSave()
+1 -1
View File
@@ -759,7 +759,7 @@ namespace ColorControl.Services.LG
if (MacAddress != null)
{
result = WOL.WakeFunction(MacAddress);
result = WOL.WakeFunctionCheckAdmin(MacAddress, IpAddress);
_justWokeUp = true;
}
else
+24 -13
View File
@@ -1,6 +1,7 @@
using ColorControl.Common;
using ColorControl.Forms;
using ColorControl.Services.Common;
using ColorControl.Svc;
using LgTv;
using Microsoft.Win32;
using Newtonsoft.Json;
@@ -127,6 +128,8 @@ namespace ColorControl.Services.LG
SaveConfig();
SavePresets();
SaveRemoteControlButtons();
SendConfigToService();
}
protected override List<LgPreset> GetDefaultPresets()
@@ -257,29 +260,19 @@ namespace ColorControl.Services.LG
private void SavePresets()
{
try
{
var json = JsonConvert.SerializeObject(_presets);
File.WriteAllText(_presetsFilename, json);
}
catch (Exception e)
{
Logger.Error(e.ToLogString());
}
Utils.WriteObject(_presetsFilename, _presets);
}
private void SaveConfig()
{
Config.PowerOnAfterStartup = Devices?.Any(d => d.PowerOnAfterStartup) ?? false;
var json = JsonConvert.SerializeObject(Config);
File.WriteAllText(_configFilename, json);
Utils.WriteObject(_configFilename, Config);
}
private void SaveRemoteControlButtons()
{
var json = JsonConvert.SerializeObject(_remoteControlButtons);
File.WriteAllText(_rcButtonsFilename, json);
Utils.WriteObject(_rcButtonsFilename, _remoteControlButtons);
}
public async Task RefreshDevices(bool connect = true, bool afterStartUp = false)
@@ -937,5 +930,23 @@ namespace ColorControl.Services.LG
Utils.StartProcess(resumeScript, hidden: true);
}
}
private void SendConfigToService()
{
if (!Utils.IsServiceRunning())
{
return;
}
var json = JsonConvert.SerializeObject(Config);
var message = new SvcMessage
{
MessageType = SvcMessageType.SetLgConfig,
Data = json
};
PipeUtils.SendMessage(message);
}
}
}
+2 -17
View File
@@ -1,6 +1,5 @@
using ColorControl.Common;
using ColorControl.Services.Common;
using Newtonsoft.Json;
using nspector.Common;
using nspector.Common.Meta;
using NvAPIWrapper.Display;
@@ -10,7 +9,6 @@ using NWin32.NativeTypes;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
@@ -187,15 +185,7 @@ namespace ColorControl.Services.NVIDIA
private void SavePresets()
{
try
{
var json = JsonConvert.SerializeObject(_presets);
File.WriteAllText(_presetsFilename, json);
}
catch (Exception e)
{
Logger.Error(e.ToLogString());
}
Utils.WriteObject(_presetsFilename, _presets);
}
private void SetCurrentDisplay(NvPreset preset)
@@ -509,11 +499,11 @@ namespace ColorControl.Services.NVIDIA
return false;
}
var timing = display.DisplayDevice.CurrentTiming;
var desktopRect = display.DisplayDevice.ScanOutInformation.SourceDesktopRectangle;
if (refreshRate == 0)
{
var timing = display.DisplayDevice.CurrentTiming;
refreshRate = (uint)timing.Extra.RefreshRate;
}
@@ -523,11 +513,6 @@ namespace ColorControl.Services.NVIDIA
resolutionHeight = (uint)desktopRect.Height;
}
if (timing.Extra.RefreshRate == refreshRate && desktopRect.Width == resolutionWidth && desktopRect.Height == resolutionHeight)
{
return true;
}
var portrait = new[] { Rotate.Degree90, Rotate.Degree270 }.Contains(display.DisplayDevice.ScanOutInformation.SourceToTargetRotation);
return SetRefreshRateInternal(display.Name, (int)refreshRate, portrait, (int)resolutionWidth, (int)resolutionHeight, updateRegistry);
+59 -1
View File
@@ -1,4 +1,6 @@
using System.Collections.Generic;
using ColorControl.Common;
using Microsoft.Win32.TaskScheduler;
using System.Collections.Generic;
namespace ColorControl
{
@@ -17,6 +19,11 @@ namespace ColorControl
public const string SetProcessAffinityParam = "--set-process-affinity";
public const string SetProcessPriorityParam = "--set-process-priority";
public const string StartElevatedParam = "--elevated";
public const string SendWakeOnLanParam = "--send-wol";
public const string InstallServiceParam = "--install-service";
public const string UninstallServiceParam = "--uninstall-service";
public const string StartServiceParam = "--start-service";
public const string StopServiceParam = "--stop-service";
public bool RunningFromScheduledTask { get; private set; }
public bool ActivateChromeFontFix { get; private set; }
@@ -30,6 +37,7 @@ namespace ColorControl
public string LgPresetName { get; private set; }
public bool NoGui { get; set; }
public bool EnableAutoStart { get; private set; }
public TaskRunLevel AutoStartRunLevel { get; private set; } = TaskRunLevel.LUA;
public bool DisableAutoStart { get; private set; }
public bool SetProcessAffinity { get; private set; }
public int ProcessId { get; private set; }
@@ -37,6 +45,13 @@ namespace ColorControl
public bool SetProcessPriority { get; private set; }
public uint PriorityClass { get; private set; }
public bool StartElevated { get; private set; }
public bool SendWol { get; private set; }
public string WolMacAddress { get; private set; }
public string WolIpAddress { get; private set; }
public bool InstallService { get; private set; }
public bool UninstallService { get; private set; }
public bool StartService { get; private set; }
public bool StopService { get; private set; }
public static StartUpParams Parse(IEnumerable<string> args)
{
@@ -85,6 +100,22 @@ namespace ColorControl
settings.PriorityClass = uint.Parse(arg);
break;
}
case SendWakeOnLanParam:
{
if (settings.WolMacAddress == null)
{
settings.WolMacAddress = arg;
continue;
}
settings.WolIpAddress = arg;
break;
}
case EnableAutoStartParam:
{
settings.AutoStartRunLevel = (TaskRunLevel)Utils.ParseInt(arg, 0);
break;
}
}
parseNameParam = string.Empty;
@@ -140,6 +171,7 @@ namespace ColorControl
case EnableAutoStartParam:
{
settings.EnableAutoStart = true;
parseNameParam = EnableAutoStartParam;
break;
}
case DisableAutoStartParam:
@@ -164,6 +196,32 @@ namespace ColorControl
settings.StartElevated = true;
break;
}
case SendWakeOnLanParam:
{
settings.SendWol = true;
parseNameParam = SendWakeOnLanParam;
break;
}
case InstallServiceParam:
{
settings.InstallService = true;
break;
}
case UninstallServiceParam:
{
settings.UninstallService = true;
break;
}
case StartServiceParam:
{
settings.StartService = true;
break;
}
case StopServiceParam:
{
settings.StopService = true;
break;
}
}
}
return settings;
@@ -0,0 +1,193 @@
using ColorControl.Common;
using ColorControl.Services.LG;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using NLog;
using System;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Threading;
using System.Threading.Tasks;
namespace ColorControl.Svc
{
public sealed class ColorControlBackgroundService : BackgroundService
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private static string LgConfigFile = "LgConfig.json";
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
try
{
LgConfigFile = Path.Combine(Program.DataDir, LgConfigFile);
//var lgService = new LgService(Program.DataDir, true);
//lgService.InstallEventHandlers(true);
await WakeDevicesAsync();
var securityIdentifier = new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null);
var ps = new PipeSecurity();
ps.AddAccessRule(new PipeAccessRule(securityIdentifier, PipeAccessRights.ReadWrite, AccessControlType.Allow));
Logger.Debug("EXECUTING BACKGROUND");
while (!stoppingToken.IsCancellationRequested)
{
Logger.Debug("WAITING FOR MESSAGE...");
var pipeServer = NamedPipeServerStreamAcl.Create("testpipe", PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous, 1024, 1024, ps);
await pipeServer.WaitForConnectionAsync(stoppingToken);
var ss = new StreamString(pipeServer);
var message = ss.ReadString();
//Logger.Debug("MESSAGE RECEIVED: " + message);
try
{
var result = HandleMessage(message);
var resultJson = JsonConvert.SerializeObject(result);
//Logger.Debug("SENDING RESULT: " + resultJson);
ss.WriteString(resultJson);
}
catch (Exception ex)
{
Logger.Error($"While handling message: {message}");
var result = SvcResultMessage.FromResult(false, ex.Message);
var resultJson = JsonConvert.SerializeObject(result);
ss.WriteString(resultJson);
}
pipeServer.Close();
//pipeServer.Disconnect();
}
Logger.Debug("STOPPING...");
}
catch (OperationCanceledException)
{
Logger.Debug("Service stopping");
}
catch (Exception ex)
{
Logger.Error(ex, "{Message}", ex.Message);
// Terminates this process and returns an exit code to the operating system.
// This is required to avoid the 'BackgroundServiceExceptionBehavior', which
// performs one of two scenarios:
// 1. When set to "Ignore": will do nothing at all, errors cause zombie services.
// 2. When set to "StopHost": will cleanly stop the host, and log errors.
//
// In order for the Windows Service Management system to leverage configured
// recovery options, we need to terminate the process with a non-zero exit code.
//Environment.Exit(1);
}
}
private SvcResultMessage HandleMessage(string json)
{
var message = JsonConvert.DeserializeObject<SvcMessage>(json);
var result = message.MessageType switch
{
SvcMessageType.SetLgConfig => HandleSetLgConfigMessage(message),
SvcMessageType.GetLog => HandleGetLogMessage(message),
SvcMessageType.ClearLog => HandleClearLogMessage(message),
SvcMessageType.ExecuteRpc => HandleExecuteRpcCommand(message)
};
return result;
}
private SvcResultMessage HandleExecuteRpcCommand(SvcMessage message)
{
var args = message.Data.Split(' ');
var startUpParams = StartUpParams.Parse(args);
return SvcResultMessage.FromResult(Program.HandleStartupParams(startUpParams, null));
}
private SvcResultMessage HandleSetLgConfigMessage(SvcMessage message)
{
var data = message.Data;
Utils.WriteText(LgConfigFile, data);
return SvcResultMessage.FromResult(true);
}
private SvcResultMessage HandleGetLogMessage(SvcMessage _)
{
var logFile = Program.LogFilename;
var data = Utils.ReadText(logFile);
return SvcResultMessage.FromResult(data);
}
private SvcResultMessage HandleClearLogMessage(SvcMessage _)
{
var logFile = Program.LogFilename;
if (File.Exists(logFile))
{
File.Delete(logFile);
}
return SvcResultMessage.FromResult(true);
}
private async Task WakeDevicesAsync()
{
if (!UserSessionInfo.UserLocalSession)
{
return;
}
if (!File.Exists(LgConfigFile))
{
return;
}
var config = Utils.DeserializeJson<LgServiceConfig>(LgConfigFile);
if (config == null)
{
return;
}
var wakeDevices = config.Devices.Where(d => d.PowerOnAfterStartup).ToList();
foreach (var wakeDevice in wakeDevices)
{
for (var i = 0; i < config.PowerOnRetries; i++)
{
WOL.WakeFunction(wakeDevice.MacAddress, wakeDevice.IpAddress);
await Task.Delay(1000);
var result = Utils.PingHost(wakeDevice.IpAddress);
if (result)
{
Logger.Debug($"Device {wakeDevice.Name} is pingable, stopping WOL");
break;
}
}
}
}
}
}
+17
View File
@@ -0,0 +1,17 @@
namespace ColorControl.Svc
{
public enum SvcMessageType
{
SetLgConfig = 1,
GetLog = 2,
ClearLog = 3,
ExecuteRpc = 10,
}
public class SvcMessage
{
public SvcMessageType MessageType { get; set; }
public string Data { get; set; }
}
}
+15
View File
@@ -0,0 +1,15 @@
namespace ColorControl.Svc
{
public class SvcResultMessage
{
public bool Result { get; set; }
public string Data { get; set; }
public string ErrorMessage { get; set; }
public static SvcResultMessage FromResult(bool result, string errorMessage = null) => new SvcResultMessage { Result = result, ErrorMessage = errorMessage };
public static SvcResultMessage FromResult(string data) => new SvcResultMessage { Result = true, Data = data };
}
}