Exemple #1
0
        /* 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);
        }
Exemple #2
0
 public void Quit()
 {
     _quitting = true;
     MainWindow?.Close();
     Tray?.Dispose();
     Tray = null;
     Discord?.Quit();
     Current?.Shutdown();
 }
Exemple #3
0
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _tray?.Dispose();
                _container?.Dispose();
                _coreInvoker?.Dispose();
            }

            base.Dispose(disposing);
        }
Exemple #4
0
        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();
 }