/* This is a signal handler for console signals. * It is called by the system in a separate thread so we have to be careful here. * "When the signal is received, the system creates a new thread in the process to execute * the function." * https://docs.microsoft.com/en-us/windows/console/handlerroutine * Note .NET can handle CTRL_C and CTRL_BREAK events via Console.CancelKeyPress but it can't * handle CTRL_CLOSE which is why I used this handler routine and the Win32 API instead. */ private static bool ConsoleCtrlHandlerRoutine(CtrlTypes ctrlType) { switch (ctrlType) { case CtrlTypes.CTRL_C_EVENT: case CtrlTypes.CTRL_BREAK_EVENT: /* We handle these for consistency. Application.Exit() causes Application.Run() * in the main thread to return followed by a graceful cleanup. If we didn't * handle these signals then ExitProcess may or may not be called, depending on * whether or not any other handlers handle these signals. */ Application.Exit(); return(true); case CtrlTypes.CTRL_CLOSE_EVENT: /* For this event it appears ExitProcess is imminent even if the event is * handled. Instead we just won't handle it and we'll assume an impending exit. * The system will wait several seconds for this handler before terminating the * process (observed in Windows 8.1). There's basically nothing guaranteed to * finish at this point but we make an attempt at disposing of the tray icon so * it doesn't linger. */ UISyncContext.Send(delegate { if (Tray != null) { Tray.Dispose(); } }, null); return(false); } return(false); }
public void Quit() { _quitting = true; MainWindow?.Close(); Tray?.Dispose(); Tray = null; Discord?.Quit(); Current?.Shutdown(); }
protected override void Dispose(bool disposing) { if (disposing) { _tray?.Dispose(); _container?.Dispose(); _coreInvoker?.Dispose(); } base.Dispose(disposing); }
bool Start() { bool success = false; // Delegate for the control handler to handle console break and close events ConsoleCtrlDelegate console_ctrl_delegate = null; // Event window to handle console-minimize events ConsoleEventWindow console_event_window = null; // Event watcher to handle WMI brightness events ManagementEventWatcher watcher = null; /* If it was requested to hide the console do that first, since doing anything else * first would mean the console is more likely to be seen (ie flicker) even if it should * be hidden. */ if (we_own_the_console) { if (opt_hide_on_start || (opt_hide_on_minimize && IsIconic(GetConsoleWindow()))) { MinimizeAndHideWindow(GetConsoleWindow()); } Console.BufferHeight = 10000; } else { if (opt_hide_on_start || opt_hide_on_minimize) { Console.WriteLine( "WARNING: " + ProgName + " isn't running in its own console window, so " + "the options that were specified to hide the console are being ignored.\n" ); } } string title = ProgName + ": Sync AC & DC brightness"; Console.Title = title; Console.WriteLine(title); Console.WriteLine(""); Console.WriteLine("Use option /? for usage information."); Console.WriteLine(""); // Synchronization used by other threads to run code in this main UI thread UISyncContext = new WindowsFormsSynchronizationContext(); SynchronizationContext.SetSynchronizationContext(UISyncContext); // Pop our console to the front when we're signaled by a secondary instance ThreadPool.RegisterWaitForSingleObject(RestoreConsoleEvent, delegate { IntPtr console = GetConsoleWindow(); ShowWindow(console, SW_MINIMIZE); ShowWindow(console, SW_RESTORE); }, null, -1, false); if (we_own_the_console) { Tray_Create(); console_ctrl_delegate = new ConsoleCtrlDelegate(ConsoleCtrlHandlerRoutine); SetConsoleCtrlHandler(console_ctrl_delegate, true); if (opt_hide_on_minimize) { console_event_window = new ConsoleEventWindow(GetConsoleWindow()); Console.Title += " (minimize-to-tray enabled)"; /* If the console window is already minimized then emulate the notification to * the event window. It's important to send this so that the event window is * hidden in a way that the window manager unhides it when the console window is * restored. * * It's possible to have a race condition here, for example the console window * is minimized during or after the event window is created but before this * code, so the event window may receive the message twice. That is fine, the * window manager tracks the event window status properly and it will still * unhide the event window properly when the console window is restored. */ if (IsIconic(GetConsoleWindow())) { //Console.Beep(300, 250); SendMessage(console_event_window.Handle, WM_SHOWWINDOW, NULL, (IntPtr)SW_PARENTCLOSING); } } } // Global mutex to handle multiple sessions running this program at the same time if (SyncBrightnessMutex == null) { SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null); MutexAccessRule rule = new MutexAccessRule(sid, MutexRights.FullControl, AccessControlType.Allow); MutexSecurity sec = new MutexSecurity(); sec.AddAccessRule(rule); bool created_new = false; SyncBrightnessMutex = new Mutex(false, SyncBrightnessMutexName, out created_new, sec); } //todo:Is there a way to get brightness changed event using Win32 API without WMI? string scope = @"\\localhost\root\WMI"; string query = "SELECT * FROM WmiMonitorBrightnessEvent"; watcher = new ManagementEventWatcher(scope, query); watcher.EventArrived += new EventArrivedEventHandler(OnBrightnessChanged); Console.WriteLine("Monitoring brightness change..."); SyncBrightness(); // Start monitoring brightness events. The watcher calls SyncBrightness when necessary. try { watcher.Start(); } // Check for access denied, for example a Guest account can't monitor brightness events. catch (UnauthorizedAccessException) { Console.Error.WriteLine("\nError: Can't monitor brightness events, access denied."); goto Cleanup; } #if DEBUG // Force GC to help coax out any bugs that otherwise wouldn't be apparent. GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); #endif // Start the message loop to handle synchronization events and window messsages. Application.Run(); // Application.Run() returns due to Application.Exit(). // Currently that only happens at the user's request. success = true; Cleanup: /* Do a graceful cleanup. * Note since this is a console application if the user closes the console window then * this code is never reached. Refer to ConsoleCtrlHandlerRoutine. */ if (console_ctrl_delegate != null) { SetConsoleCtrlHandler(console_ctrl_delegate, false); } if (Tray != null) { Tray.Dispose(); } if (watcher != null) { watcher.Stop(); } GC.KeepAlive(console_event_window); return(success ? true : false); }
private void ApplicationOnExit(object sender, ExitEventArgs exitEventArgs) { StopAllServices(); _tray.Dispose(); }