From 3bcbf00a0ff529046027213944a6e094af68269c Mon Sep 17 00:00:00 2001 From: Inga Lovinde <52715130+inga-lovinde@users.noreply.github.com> Date: Sun, 1 Dec 2019 13:30:50 +0300 Subject: [PATCH] A bunch of more workarounds/hacks, install experience improved, FixMonitorTask implemented --- .../Devices/DeviceHelper.cs | 33 +- RadeonResetBugFixService/MainHandler.cs | 11 +- RadeonResetBugFixService/Program.cs | 18 +- RadeonResetBugFixService/ProjectInstaller.cs | 18 +- .../RadeonResetBugFixService.cs | 23 +- .../RadeonResetBugFixService.csproj | 2 + .../Tasks/AbstractDevicesTask.cs | 24 +- .../Tasks/FixMonitorTask.cs | 38 ++ .../ThirdParty/MonitorChanger.cs | 382 ++++++++++++++++++ .../ThirdParty/ServiceHelpers.cs | 4 +- 10 files changed, 537 insertions(+), 16 deletions(-) create mode 100644 RadeonResetBugFixService/Tasks/FixMonitorTask.cs create mode 100644 RadeonResetBugFixService/ThirdParty/MonitorChanger.cs diff --git a/RadeonResetBugFixService/Devices/DeviceHelper.cs b/RadeonResetBugFixService/Devices/DeviceHelper.cs index 73877b3..92ae405 100644 --- a/RadeonResetBugFixService/Devices/DeviceHelper.cs +++ b/RadeonResetBugFixService/Devices/DeviceHelper.cs @@ -3,6 +3,8 @@ using System; using System.Collections.Generic; using System.Management; + using System.Threading; + using System.Threading.Tasks; using Contracts; class DeviceHelper @@ -72,17 +74,44 @@ public static void DisableDevice(DeviceInfo deviceInfo) { - ThirdParty.DisableDevice.DeviceHelper.SetDeviceEnabled(deviceInfo.ClassGuid, deviceInfo.DeviceId, false); + RunWithTimeout( + () => ThirdParty.DisableDevice.DeviceHelper.SetDeviceEnabled(deviceInfo.ClassGuid, deviceInfo.DeviceId, false), + TimeSpan.FromSeconds(50)); } public static void EnableDevice(DeviceInfo deviceInfo) { - ThirdParty.DisableDevice.DeviceHelper.SetDeviceEnabled(deviceInfo.ClassGuid, deviceInfo.DeviceId, true); + RunWithTimeout( + () => ThirdParty.DisableDevice.DeviceHelper.SetDeviceEnabled(deviceInfo.ClassGuid, deviceInfo.DeviceId, true), + TimeSpan.FromSeconds(50)); } public static bool? IsDeviceCurrentlyDisabled(DeviceInfo deviceInfo) { return ThirdParty.DisableDevice.DeviceHelper.IsDeviceDisabled(deviceInfo.ClassGuid, deviceInfo.DeviceId); } + + private static void RunWithTimeout(Action action, TimeSpan timeout) + { + Exception localException = null; + Task.WaitAny( + Task.Run(() => + { + try + { + action(); + } + catch (Exception e) + { + localException = new Exception("Exception from action", e); + } + }), + Task.Delay(timeout)); + + if (localException != null) + { + throw localException; + } + } } } diff --git a/RadeonResetBugFixService/MainHandler.cs b/RadeonResetBugFixService/MainHandler.cs index 3c1cae7..6bbb473 100644 --- a/RadeonResetBugFixService/MainHandler.cs +++ b/RadeonResetBugFixService/MainHandler.cs @@ -26,12 +26,13 @@ $"radeonfix_{date:yyyyMMdd}_{date:HHmmss}.log"); } - public void HandleStartup() + public void HandleStartup(string reason) { using (var fileLogger = new FileLogger(this.LogFilename)) { using (ILogger logger = new TaskLoggerWrapper(fileLogger, "Startup")) { + logger.Log($"Reason: {reason}"); try { lock (this.Mutex) @@ -43,6 +44,10 @@ new SleepTask(TimeSpan.FromSeconds(20)), new DisableVirtualVideoTask(this.StartupDevicesStatus), new EnableAmdVideoTask(this.StartupDevicesStatus), + new SleepTask(TimeSpan.FromSeconds(40)), + new FixMonitorTask(), + new DisableVirtualVideoTask(this.StartupDevicesStatus), + new FixMonitorTask(), }); } } @@ -54,12 +59,13 @@ } } - public void HandleShutdown() + public void HandleShutdown(string reason) { using (var fileLogger = new FileLogger(this.LogFilename)) { using (ILogger logger = new TaskLoggerWrapper(fileLogger, "Shutdown")) { + logger.Log($"Reason: {reason}"); try { lock (this.Mutex) @@ -72,6 +78,7 @@ new DisableAmdVideoTask(this.ShutdownDevicesStatus), new EnableVirtualVideoTask(this.ShutdownDevicesStatus), new LastResortDevicesRestoreTask(this.StartupDevicesStatus), + new LastResortDevicesRestoreTask(this.StartupDevicesStatus), // just in case }); } } diff --git a/RadeonResetBugFixService/Program.cs b/RadeonResetBugFixService/Program.cs index 9a5516b..72175df 100644 --- a/RadeonResetBugFixService/Program.cs +++ b/RadeonResetBugFixService/Program.cs @@ -1,5 +1,6 @@ namespace RadeonResetBugFixService { + using Microsoft.Win32; using System; using System.Security.Principal; using System.ServiceProcess; @@ -87,24 +88,37 @@ private static void DoInstall() { + Console.WriteLine("Setting registry values..."); + // Prevent Windows from killing services that take up to 300 seconds to shutdown + Registry.SetValue(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control", "WaitToKillServiceTimeout", "300000", RegistryValueKind.String); + + // Disable fast restart + Registry.SetValue(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Power", "HiberbootEnabled", 0, RegistryValueKind.DWord); + + Console.WriteLine("Installing service..."); ServiceHelpers.InstallService(nameof(RadeonResetBugFixService), typeof(RadeonResetBugFixService)); + Console.WriteLine("Starting service..."); ServiceHelpers.StartService(nameof(RadeonResetBugFixService), typeof(RadeonResetBugFixService)); + Console.WriteLine("Started service"); } private static void DoUninstall() { + Console.WriteLine("Stopping service..."); ServiceHelpers.StopService(nameof(RadeonResetBugFixService), typeof(RadeonResetBugFixService)); + Console.WriteLine("Uninstalling service..."); ServiceHelpers.UninstallService(nameof(RadeonResetBugFixService), typeof(RadeonResetBugFixService)); + Console.WriteLine("Uninstalled"); } private static void DoStartup() { - new MainHandler().HandleStartup(); + new MainHandler().HandleStartup("Program.DoStartup"); } private static void DoShutdown() { - new MainHandler().HandleShutdown(); + new MainHandler().HandleShutdown("Program.DoShutdown"); } // Code taken from https://stackoverflow.com/a/2679654 diff --git a/RadeonResetBugFixService/ProjectInstaller.cs b/RadeonResetBugFixService/ProjectInstaller.cs index d48a816..8b72a72 100644 --- a/RadeonResetBugFixService/ProjectInstaller.cs +++ b/RadeonResetBugFixService/ProjectInstaller.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Configuration.Install; using System.Linq; +using System.Management; using System.Threading.Tasks; namespace RadeonResetBugFixService @@ -18,7 +19,22 @@ namespace RadeonResetBugFixService private void serviceInstaller1_AfterInstall(object sender, InstallEventArgs e) { - + ManagementObject wmiService = null; + ManagementBaseObject InParam = null; + try + { + wmiService = new ManagementObject($"Win32_Service.Name='{this.serviceInstaller1.ServiceName}'"); + InParam = wmiService.GetMethodParameters("Change"); + InParam["DesktopInteract"] = true; + wmiService.InvokeMethod("Change", InParam, null); + } + finally + { + if (InParam != null) + InParam.Dispose(); + if (wmiService != null) + wmiService.Dispose(); + } } private void serviceProcessInstaller1_AfterInstall(object sender, InstallEventArgs e) diff --git a/RadeonResetBugFixService/RadeonResetBugFixService.cs b/RadeonResetBugFixService/RadeonResetBugFixService.cs index 6740ba3..78b6d51 100644 --- a/RadeonResetBugFixService/RadeonResetBugFixService.cs +++ b/RadeonResetBugFixService/RadeonResetBugFixService.cs @@ -1,4 +1,5 @@ -using System; +using Microsoft.Win32; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; @@ -21,17 +22,31 @@ namespace RadeonResetBugFixService protected override void OnShutdown() { - this.Handler.HandleShutdown(); + SystemEvents.SessionEnding -= this.OnSessionEnding; + this.RequestAdditionalTime(300000); + this.Handler.HandleShutdown("ServiceBase.OnShutdown"); } protected override void OnStart(string[] args) { - this.Handler.HandleStartup(); + this.Handler.HandleStartup("ServiceBase.OnStart"); + this.RequestAdditionalTime(300000); + SystemEvents.SessionEnding += this.OnSessionEnding; } protected override void OnStop() { - this.Handler.HandleShutdown(); + SystemEvents.SessionEnding -= this.OnSessionEnding; + this.RequestAdditionalTime(300000); + this.Handler.HandleShutdown("ServiceBase.OnStop"); + } + + private void OnSessionEnding(object sender, SessionEndingEventArgs args) + { + if (args.Reason == SessionEndReasons.SystemShutdown) + { + this.Handler.HandleShutdown("SystemEvents.SessionEnding"); + } } } } diff --git a/RadeonResetBugFixService/RadeonResetBugFixService.csproj b/RadeonResetBugFixService/RadeonResetBugFixService.csproj index 467bfd0..2bb30f9 100644 --- a/RadeonResetBugFixService/RadeonResetBugFixService.csproj +++ b/RadeonResetBugFixService/RadeonResetBugFixService.csproj @@ -72,8 +72,10 @@ + + diff --git a/RadeonResetBugFixService/Tasks/AbstractDevicesTask.cs b/RadeonResetBugFixService/Tasks/AbstractDevicesTask.cs index c33d4af..230e86b 100644 --- a/RadeonResetBugFixService/Tasks/AbstractDevicesTask.cs +++ b/RadeonResetBugFixService/Tasks/AbstractDevicesTask.cs @@ -39,6 +39,11 @@ } else { + if (device.ErrorCode != 0) + { + logger.LogError($"Device is in error state: {device.ErrorCode}"); + } + logger.Log($"Disabling {device.Description}"); DeviceHelper.DisableDevice(device); logger.Log($"Disabled {device.Description}"); @@ -51,6 +56,11 @@ if (!device.IsDisabled) { logger.Log($"{device.Description} is already enabled"); + + if (device.ErrorCode != 0) + { + logger.LogError($"Device is in error state: {device.ErrorCode}"); + } } else { @@ -65,13 +75,17 @@ { if (this.ShouldDisable(device)) { - if (!device.IsDisabled) + if (device.IsDisabled) { - logger.LogError($"{device.Description} is enabled but should be disabled"); + logger.Log($"Successfully checked {device.Description} status"); + } + else if (device.ErrorCode != 0) + { + logger.LogError($"Device is in error state: {device.ErrorCode}"); } else { - logger.Log($"Successfully checked {device.Description} status"); + logger.LogError($"{device.Description} is enabled but should be disabled"); } } else if (this.ShouldEnable(device)) @@ -80,6 +94,10 @@ { logger.Log($"{device.Description} is disabled but should be enabled"); } + else if (device.ErrorCode != 0) + { + logger.LogError($"Device is in error state: {device.ErrorCode}"); + } else { logger.Log($"Successfully checked {device.Description} status"); diff --git a/RadeonResetBugFixService/Tasks/FixMonitorTask.cs b/RadeonResetBugFixService/Tasks/FixMonitorTask.cs new file mode 100644 index 0000000..01a6517 --- /dev/null +++ b/RadeonResetBugFixService/Tasks/FixMonitorTask.cs @@ -0,0 +1,38 @@ +namespace RadeonResetBugFixService.Tasks +{ + using System.Collections.Generic; + using System.Linq; + using Contracts; + using Devices; + + class FixMonitorTask : ITask + { + public string TaskName => "Fixing monitor"; + + public void Run(ILogger logger) + { + var hypervDisplays = new List(); + var realDisplays = new List(); + foreach (var display in ThirdParty.MonitorChanger.Display.GetDisplayList()) + { + logger.Log($"Found display(ID='{display.DeviceID}' Key='{display.DeviceKey}', Name='{display.DeviceName}', String='{display.DeviceString}')"); + if (display.DeviceID.ToLowerInvariant().StartsWith(@"monitor\mhs062e")) + { + hypervDisplays.Add(display); + } + else + { + realDisplays.Add(display); + } + } + + logger.Log($"Found {hypervDisplays.Count} virtual displays and {realDisplays.Count} real displays"); + if (hypervDisplays.Count > 0 && realDisplays.Count > 0) + { + var newPrimaryDisplay = realDisplays[0]; + logger.Log($"Setting default display to {newPrimaryDisplay.DeviceID}"); + ThirdParty.MonitorChanger.Display.SetAsPrimaryMonitor(newPrimaryDisplay); + } + } + } +} diff --git a/RadeonResetBugFixService/ThirdParty/MonitorChanger.cs b/RadeonResetBugFixService/ThirdParty/MonitorChanger.cs new file mode 100644 index 0000000..10d92ec --- /dev/null +++ b/RadeonResetBugFixService/ThirdParty/MonitorChanger.cs @@ -0,0 +1,382 @@ +namespace RadeonResetBugFixService.ThirdParty.MonitorChanger +{ + // Code taken from https://github.com/Grunge/setDisplayRes + using System; + using System.Collections.Generic; + using System.Runtime.InteropServices; + + // Encapsulates access to the PInvoke functions + public class Display + { + public static List GetDisplayList(bool RetrieveMonitorname = false) + { + //todo: EDD_GET_DEVICE_INTERFACE_NAME + //const int EDD_GET_DEVICE_INTERFACE_NAME = 0x1; + + List displays = new List(); + DISPLAY_DEVICE d = new DISPLAY_DEVICE(); + d.cb = Marshal.SizeOf(d); + try + { + for (uint id = 0; NativeMethods.EnumDisplayDevices(null, id, ref d, 0); id++) + { + if (d.StateFlags.HasFlag(DisplayDeviceStateFlags.AttachedToDesktop)) + { + //call again to get the monitor name (not only the graka name). + DISPLAY_DEVICE devWithName = new DISPLAY_DEVICE(); + devWithName.cb = Marshal.SizeOf(devWithName); + + NativeMethods.EnumDisplayDevices(d.DeviceName, 0, ref devWithName, 0); + //overwrite device string and id, keep the rest! + d.DeviceString = devWithName.DeviceString; + d.DeviceID = devWithName.DeviceID; + + displays.Add(d); + }//if is display + }//for + } + catch (Exception ex) + { + Console.WriteLine(String.Format("{0}", ex.ToString())); + } + + return displays; + } + + + + + + // Return a list of all possible display types for this computer + public static List GetDisplaySettings(string strDevName) + { + List modes = new List(); + DevMode devmode = DevMode; + + int counter = 0; + int returnValue = 1; + + // A return value of zero indicates that no more settings are available + while (returnValue != 0) + { + returnValue = GetSettings(strDevName, ref devmode, counter++); + + modes.Add(devmode); + } + + return modes; + } + + // Return the current display setting + public int GetCurrentSettings(string strDevName, ref DevMode devmode) + { + return GetSettings(strDevName, ref devmode, NativeMethods.ENUM_CURRENT_SETTINGS); + } + + + + //todo: CDS_UPDATEREGISTRY + + // Change the settings to the values of the DEVMODE passed + public static string ChangeSettings(DISPLAY_DEVICE a_dev, DevMode devmode, bool bSetPrimary) + { + string errorMessage = ""; + ChangeDisplaySettingsFlags flags = new ChangeDisplaySettingsFlags(); + flags = ChangeDisplaySettingsFlags.CDS_UPDATEREGISTRY | ChangeDisplaySettingsFlags.CDS_GLOBAL; + + ReturnCodes iRet = NativeMethods.ChangeDisplaySettingsEx(a_dev.DeviceName, ref devmode, IntPtr.Zero, flags, IntPtr.Zero); + + //same again, but with PRIMARY + if (bSetPrimary && iRet == ReturnCodes.DISP_CHANGE_SUCCESSFUL) + { + SetAsPrimaryMonitor(a_dev); + }//if primary + + switch (iRet) + { + case ReturnCodes.DISP_CHANGE_SUCCESSFUL: + break; + case ReturnCodes.DISP_CHANGE_RESTART: + errorMessage = "Please restart your system"; + break; + case ReturnCodes.DISP_CHANGE_FAILED: + errorMessage = "ChangeDisplaySettigns API failed"; + break; + case ReturnCodes.DISP_CHANGE_BADDUALVIEW: + errorMessage = "The settings change was unsuccessful because system is DualView capable."; + break; + case ReturnCodes.DISP_CHANGE_BADFLAGS: + errorMessage = "An invalid set of flags was passed in."; + break; + case ReturnCodes.DISP_CHANGE_BADPARAM: + errorMessage = "An invalid parameter was passed in. This can include an invalid flag or combination of flags."; + break; + case ReturnCodes.DISP_CHANGE_NOTUPDATED: + errorMessage = "Unable to write settings to the registry."; + break; + default: + errorMessage = "Unknown return value from ChangeDisplaySettings API"; + break; + } + return errorMessage; + } + + public static void SetAsPrimaryMonitor(DISPLAY_DEVICE a_dev) + { + var deviceMode = new DevMode(); + NativeMethods.EnumDisplaySettings(a_dev.DeviceName, -1, ref deviceMode); + var offsetx = deviceMode.dmPositionX; + var offsety = deviceMode.dmPositionY; + deviceMode.dmPositionX = 0; + deviceMode.dmPositionY = 0; + + NativeMethods.ChangeDisplaySettingsEx( + a_dev.DeviceName, + ref deviceMode, + (IntPtr)null, + (ChangeDisplaySettingsFlags.CDS_SET_PRIMARY | ChangeDisplaySettingsFlags.CDS_UPDATEREGISTRY | ChangeDisplaySettingsFlags.CDS_NORESET), + IntPtr.Zero); + + var device = new DISPLAY_DEVICE(); + device.cb = Marshal.SizeOf(device); + + // Update other devices + for (uint otherid = 0; NativeMethods.EnumDisplayDevices(null, otherid, ref device, 0); otherid++) + { + if (device.StateFlags.HasFlag(DisplayDeviceStateFlags.AttachedToDesktop) && device.DeviceID != a_dev.DeviceID) + { + device.cb = Marshal.SizeOf(device); + var otherDeviceMode = new DevMode(); + + NativeMethods.EnumDisplaySettings(device.DeviceName, -1, ref otherDeviceMode); + + otherDeviceMode.dmPositionX -= offsetx; + otherDeviceMode.dmPositionY -= offsety; + + NativeMethods.ChangeDisplaySettingsEx( + device.DeviceName, + ref otherDeviceMode, + (IntPtr)null, + (ChangeDisplaySettingsFlags.CDS_UPDATEREGISTRY | ChangeDisplaySettingsFlags.CDS_NORESET), + IntPtr.Zero); + + } + + device.cb = Marshal.SizeOf(device); + } + + // Apply settings + NativeMethods.ChangeDisplaySettingsEx(null, IntPtr.Zero, (IntPtr)null, ChangeDisplaySettingsFlags.CDS_NONE, (IntPtr)null); + }//set as primary() + + // Return a properly configured DEVMODE + public static DevMode DevMode + { + get + { + DevMode devmode = new DevMode(); + devmode.dmDeviceName = new String(new char[32]); + devmode.dmFormName = new String(new char[32]); + devmode.dmSize = (short)Marshal.SizeOf(devmode); + return devmode; + } + } + + // call the external function inthe Win32 API + private static int GetSettings(string strDevName, ref DevMode devmode, int iModeNum) + { + // helper to wrap EnumDisplaySettings Win32 API + return NativeMethods.EnumDisplaySettings(strDevName, iModeNum, ref devmode); + } + } + + + // Encapsulate the magic numbers for the return value in an enumeration + public enum ReturnCodes : int + { + DISP_CHANGE_SUCCESSFUL = 0, + DISP_CHANGE_BADDUALVIEW = -6, + DISP_CHANGE_BADFLAGS = -4, + DISP_CHANGE_BADMODE = -2, + DISP_CHANGE_BADPARAM = -5, + DISP_CHANGE_FAILED = -1, + DISP_CHANGE_NOTUPDATED = -3, + DISP_CHANGE_RESTART = 1 + } + + // To see how the DEVMODE struct was translated from the unmanaged to the managed see the Task 2 Declarations section + + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/prntspol_8nle.asp + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public struct DevMode + { + // The MarshallAs attribute is covered in the Background section of the article + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] + public string dmDeviceName; + + public short dmSpecVersion; + public short dmDriverVersion; + public short dmSize; + public short dmDriverExtra; + public int dmFields; + public int dmPositionX; + public int dmPositionY; + public int dmDisplayOrientation; + public int dmDisplayFixedOutput; + public short dmColor; + public short dmDuplex; + public short dmYResolution; + public short dmTTOption; + public short dmCollate; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] + public string dmFormName; + + public short dmLogPixels; + public short dmBitsPerPel; + public int dmPelsWidth; + public int dmPelsHeight; + public int dmDisplayFlags; + public int dmDisplayFrequency; + public int dmICMMethod; + public int dmICMIntent; + public int dmMediaType; + public int dmDitherType; + public int dmReserved1; + public int dmReserved2; + public int dmPanningWidth; + public int dmPanningHeight; + + public override string ToString() + { + return dmPelsWidth.ToString() + " x " + dmPelsHeight.ToString(); + } + + + public string[] GetInfoArray() + { + string[] items = new string[5]; + + items[0] = dmDeviceName; + items[1] = dmPelsWidth.ToString(); + items[2] = dmPelsHeight.ToString(); + items[3] = dmDisplayFrequency.ToString(); + items[4] = dmBitsPerPel.ToString(); + + return items; + } + } + + + //Display Listening + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public struct DISPLAY_DEVICE + { + [MarshalAs(UnmanagedType.U4)] + public int cb; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] + public string DeviceName; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string DeviceString; + [MarshalAs(UnmanagedType.U4)] + public DisplayDeviceStateFlags StateFlags; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string DeviceID; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string DeviceKey; + } + + [Flags()] + public enum DEVMODE_Flags : int + { + DM_BITSPERPEL = 0x40000, + DM_DISPLAYFLAGS = 0x200000, + DM_DISPLAYFREQUENCY = 0x400000, + DM_PELSHEIGHT = 0x100000, + DM_PELSWIDTH = 0x80000, + DM_POSITION = 0x20 + } + + [Flags()] + public enum DisplayDeviceStateFlags : int + { + /// The device is part of the desktop. + AttachedToDesktop = 0x1, + MultiDriver = 0x2, + /// The device is part of the desktop. + PrimaryDevice = 0x4, + /// Represents a pseudo device used to mirror application drawing for remoting or other purposes. + MirroringDriver = 0x8, + /// The device is VGA compatible. + VGACompatible = 0x10, + /// The device is removable; it cannot be the primary display. + Removable = 0x20, + /// The device has more display modes than its output devices support. + ModesPruned = 0x8000000, + Remote = 0x4000000, + Disconnect = 0x2000000 + } + + [Flags()] + public enum ChangeDisplaySettingsFlags : uint + { + CDS_NONE = 0, + CDS_UPDATEREGISTRY = 0x00000001, + CDS_TEST = 0x00000002, + CDS_FULLSCREEN = 0x00000004, + CDS_GLOBAL = 0x00000008, + CDS_SET_PRIMARY = 0x00000010, + CDS_VIDEOPARAMETERS = 0x00000020, + CDS_ENABLE_UNSAFE_MODES = 0x00000100, + CDS_DISABLE_UNSAFE_MODES = 0x00000200, + CDS_RESET = 0x40000000, + CDS_RESET_EX = 0x20000000, + CDS_NORESET = 0x10000000 + } + + [Flags()] + public enum ChangeDisplayConfigFlags : uint + { + SDC_TOPOLOGY_INTERNAL = 0x00000001, + SDC_TOPOLOGY_CLONE = 0x00000002, + SDC_TOPOLOGY_EXTEND = 0x00000004, + SDC_TOPOLOGY_EXTERNAL = 0x00000008, + SDC_APPLY = 0x00000080, + } + + class NativeMethods + { + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/devcons_84oj.asp + [DllImport("user32.dll", CharSet = CharSet.Ansi)] + public static extern int EnumDisplaySettings(string lpszDeviceName, int iModeNum, ref DevMode lpDevMode); + + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/devcons_7gz7.asp + [DllImport("user32.dll", CharSet = CharSet.Ansi)] //CallingConvention = CallingConvention.Cdecl + public static extern ReturnCodes ChangeDisplaySettingsEx(string lpszDeviceName, ref DevMode lpDevMode, IntPtr hwnd, ChangeDisplaySettingsFlags dwFlags, IntPtr lParam); + + [DllImport("user32.dll")] + public static extern int ChangeDisplaySettingsEx(int lpszDeviceName, int lpDevMode, int hwnd, int dwFlags, int lParam); + + + [DllImport("user32.dll")] + // A signature for ChangeDisplaySettingsEx with a DEVMODE struct as the second parameter won't allow you to pass in IntPtr.Zero, so create an overload + public static extern int ChangeDisplaySettingsEx(string lpszDeviceName, IntPtr lpDevMode, IntPtr hwnd, ChangeDisplaySettingsFlags dwflags, IntPtr lParam); + + + + + + [DllImport("user32.dll", CharSet = CharSet.Ansi)] + public static extern ReturnCodes ChangeDisplaySettings(ref DevMode lpDevMode, int dwFlags); + + [DllImport("user32.dll")] + public static extern bool EnumDisplayDevices(string lpDevice, uint iDevNum, ref DISPLAY_DEVICE lpDisplayDevice, uint dwFlags); + + + [DllImport("user32.dll", CharSet = CharSet.Unicode)] + public static extern long SetDisplayConfig(uint numPathArrayElements, IntPtr pathArray, uint numModeArrayElements, IntPtr modeArray, ChangeDisplayConfigFlags flags); + + + public const int ENUM_CURRENT_SETTINGS = -1; + } +} diff --git a/RadeonResetBugFixService/ThirdParty/ServiceHelpers.cs b/RadeonResetBugFixService/ThirdParty/ServiceHelpers.cs index 2997913..f9c78b7 100644 --- a/RadeonResetBugFixService/ThirdParty/ServiceHelpers.cs +++ b/RadeonResetBugFixService/ThirdParty/ServiceHelpers.cs @@ -101,7 +101,7 @@ if (controller.Status != ServiceControllerStatus.Running) { controller.Start(); - controller.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(10)); + controller.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromMinutes(6)); } } } @@ -114,7 +114,7 @@ if (controller.Status != ServiceControllerStatus.Stopped) { controller.Stop(); - controller.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(10)); + controller.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromMinutes(6)); } } }