Refactoring; improved Win7 and Win10 compatibility

master
Inga 🏳‍🌈 4 years ago
parent 20d7d33023
commit 5787a023eb
  1. 23
      RadeonResetBugFixService/ConsoleHelper.cs
  2. 39
      RadeonResetBugFixService/EnvironmentHelper.cs
  3. 26
      RadeonResetBugFixService/Program.cs
  4. 47
      RadeonResetBugFixService/Properties/app.manifest
  5. 7
      RadeonResetBugFixService/RadeonResetBugFixService.cs
  6. 6
      RadeonResetBugFixService/RadeonResetBugFixService.csproj
  7. 16
      RadeonResetBugFixService/RegistryHelper.cs

@ -1,23 +0,0 @@
namespace RadeonResetBugFixService
{
using System;
using System.Runtime.InteropServices;
static class ConsoleHelper
{
private static class NativeMethods
{
[DllImport("kernel32.dll")]
public static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
public static extern bool IsWindowVisible(IntPtr hWnd);
}
// Code taken from https://stackoverflow.com/a/53716169
public static bool HaveVisibleConsole()
{
return NativeMethods.IsWindowVisible(NativeMethods.GetConsoleWindow());
}
}
}

@ -0,0 +1,39 @@
namespace RadeonResetBugFixService
{
using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
static class EnvironmentHelper
{
private static class NativeMethods
{
[DllImport("kernel32.dll")]
public static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
public static extern bool IsWindowVisible(IntPtr hWnd);
}
private static Version VistaVersion { get; } = new Version(6, 0);
private static Version Windows8Version { get; } = new Version(6, 2);
// Code taken from https://stackoverflow.com/a/53716169
public static bool IsConsoleVisibleOnWindows() => NativeMethods.IsWindowVisible(NativeMethods.GetConsoleWindow());
private static bool IsWindows() => RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
// Code taken from https://stackoverflow.com/a/2679654
public static bool HasAdministratorPrivileges()
{
WindowsIdentity id = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(id);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
public static bool IsWindows8OrNewer() => IsWindows() && Environment.OSVersion.Version >= Windows8Version;
public static bool IsVistaOrNewer() => IsWindows() && Environment.OSVersion.Version >= VistaVersion;
}
}

@ -1,8 +1,6 @@
namespace RadeonResetBugFixService namespace RadeonResetBugFixService
{ {
using System; using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.ServiceProcess; using System.ServiceProcess;
using ThirdParty.ServiceHelpers; using ThirdParty.ServiceHelpers;
@ -18,15 +16,15 @@
throw new ArgumentNullException(nameof(args)); throw new ArgumentNullException(nameof(args));
} }
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) if (!EnvironmentHelper.IsVistaOrNewer())
{ {
Console.Error.WriteLine("This program only runs on Windows"); Console.Error.WriteLine("This program only runs on Windows Vista or newer");
return -1; return -1;
} }
if (ConsoleHelper.HaveVisibleConsole()) if (EnvironmentHelper.IsConsoleVisibleOnWindows())
{ {
if (!HasAdministratorPrivileges()) if (!EnvironmentHelper.HasAdministratorPrivileges())
{ {
Console.Error.WriteLine("Access Denied."); Console.Error.WriteLine("Access Denied.");
Console.Error.WriteLine("Administrator permissions are needed to use this tool."); Console.Error.WriteLine("Administrator permissions are needed to use this tool.");
@ -43,14 +41,10 @@
} }
} }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "Windows service initialization")]
private static int MainService() private static int MainService()
{ {
ServiceBase[] ServicesToRun; ServiceBase.Run(new RadeonResetBugFixService());
ServicesToRun = new ServiceBase[]
{
new RadeonResetBugFixService()
};
ServiceBase.Run(ServicesToRun);
return 0; return 0;
} }
@ -142,13 +136,5 @@
{ {
new MainHandler().HandleShutdown("Program.DoShutdown"); new MainHandler().HandleShutdown("Program.DoShutdown");
} }
// Code taken from https://stackoverflow.com/a/2679654
private static bool HasAdministratorPrivileges()
{
WindowsIdentity id = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(id);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
} }
} }

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="RadeonResetBugFixService"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC Manifest Options
If you want to change the Windows User Account Control level replace the
requestedExecutionLevel node with one of the following.
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
Specifying requestedExecutionLevel element will disable file and registry virtualization.
Remove this element if your application requires this virtualization for backwards
compatibility.
-->
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on
and is designed to work with. Uncomment the appropriate elements
and Windows will automatically select the most compatible environment. -->
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
</assembly>

@ -92,12 +92,15 @@
"ServiceBase.OnCustomCommand", "ServiceBase.OnCustomCommand",
(string reason) => (string reason) =>
{ {
this.Handler.HandleLog($"Custom command: {command}");
if (command == SERVICE_CONTROL_PRESHUTDOWN) if (command == SERVICE_CONTROL_PRESHUTDOWN)
{ {
this.Handler.HandleLog($"Custom command: preshutdown");
this.CallStop(); this.CallStop();
} }
else
{
this.Handler.HandleLog($"Unknown custom command: {command}");
}
}); });
} }

@ -44,6 +44,9 @@
<PropertyGroup> <PropertyGroup>
<StartupObject /> <StartupObject />
</PropertyGroup> </PropertyGroup>
<PropertyGroup>
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Configuration.Install" /> <Reference Include="System.Configuration.Install" />
@ -58,7 +61,7 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="ConsoleHelper.cs" /> <Compile Include="EnvironmentHelper.cs" />
<Compile Include="Constants.cs" /> <Compile Include="Constants.cs" />
<Compile Include="Contracts\DeviceInfo.cs" /> <Compile Include="Contracts\DeviceInfo.cs" />
<Compile Include="Contracts\DevicesStatus.cs" /> <Compile Include="Contracts\DevicesStatus.cs" />
@ -106,6 +109,7 @@
<None Include=".editorconfig" /> <None Include=".editorconfig" />
<None Include="App.config" /> <None Include="App.config" />
<None Include="packages.config" /> <None Include="packages.config" />
<None Include="Properties\app.manifest" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="ProjectInstaller.resx"> <EmbeddedResource Include="ProjectInstaller.resx">

@ -19,15 +19,21 @@
} }
} }
private static RegistryValuePath PreshutdownOrderPath = new RegistryValuePath(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control", "PreshutdownOrder"); private static string BasicDisplayServiceName { get; } = (
EnvironmentHelper.IsWindows8OrNewer()
? "BasicDisplay"
: "vga"
);
private static RegistryValuePath WaitToKillServiceTimeoutPath = new RegistryValuePath(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control", "WaitToKillServiceTimeout"); private static RegistryValuePath PreshutdownOrderPath { get; } = new RegistryValuePath(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control", "PreshutdownOrder");
private static RegistryValuePath FastRebootPath = new RegistryValuePath(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Power", "HiberbootEnabled"); private static RegistryValuePath WaitToKillServiceTimeoutPath { get; } = new RegistryValuePath(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control", "WaitToKillServiceTimeout");
private static RegistryValuePath NoInteractiveServicesPath = new RegistryValuePath(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Windows", "NoInteractiveServices"); private static RegistryValuePath FastRebootPath { get; } = new RegistryValuePath(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Power", "HiberbootEnabled");
private static RegistryValuePath BasicDisplayStartTypePath = new RegistryValuePath(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\BasicDisplay", "Start"); private static RegistryValuePath NoInteractiveServicesPath { get; } = new RegistryValuePath(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Windows", "NoInteractiveServices");
private static RegistryValuePath BasicDisplayStartTypePath { get; } = new RegistryValuePath(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\" + BasicDisplayServiceName, "Start");
private static T GetValue<T>(RegistryValuePath path, T defaultValue = default) => (T)Registry.GetValue(path.KeyName, path.ValueName, defaultValue); private static T GetValue<T>(RegistryValuePath path, T defaultValue = default) => (T)Registry.GetValue(path.KeyName, path.ValueName, defaultValue);

Loading…
Cancel
Save