Пример #1
0
 internal ControlCDelegateData(ConsoleSpecialKey controlKey, ConsoleCancelEventHandler cancelCallbacks)
 {
     this.ControlKey      = controlKey;
     this.CancelCallbacks = cancelCallbacks;
     this.CompletionEvent = new ManualResetEvent(false);
     // this.Cancel defaults to false
     // this.DelegateStarted defaults to false
 }
        public void InvalidEnumValue()
        {
            const ConsoleSpecialKey invalidValue = (ConsoleSpecialKey)15;

            Action act = () => invalidValue.MustBeValidEnumValue(nameof(invalidValue));

            act.ShouldThrow <EnumValueNotDefinedException>()
            .And.ParamName.Should().Be(nameof(invalidValue));
        }
        protected override bool OnCancelKeySignal(ConsoleSpecialKey consoleSpecialKey)
        {
            if (consoleSpecialKey == ConsoleSpecialKey.ControlC)
            {
                this.CancellationTokenSource.Cancel();
                return(true);
            }

            return(base.OnCancelKeySignal(consoleSpecialKey));
        }
    public static void InvalidEnumValue()
    {
        const ConsoleSpecialKey invalidValue = (ConsoleSpecialKey)15;

        Action act = () => invalidValue.MustBeValidEnumValue(nameof(invalidValue));

        var exceptionAssertion = act.Should().Throw <EnumValueNotDefinedException>().Which;

        exceptionAssertion.Message.Should().Contain($"{nameof(invalidValue)} \"{invalidValue}\" must be one of the defined constants of enum \"{invalidValue.GetType()}\", but it actually is not.");
        exceptionAssertion.ParamName.Should().Be(nameof(invalidValue));
    }
Пример #5
0
        internal static bool HandleBreakEvent(ConsoleSpecialKey controlKey)
        {
            ConsoleCancelEventHandler handler = s_cancelCallbacks;

            if (handler == null)
            {
                return(false);
            }

            var args = new ConsoleCancelEventArgs(controlKey);

            handler(null, args);
            return(args.Cancel);
        }
Пример #6
0
        private void CloseConsole(ConsoleSpecialKey closeKey, int forceCloseMillisecondsTimeout)
        {
            try
            {
                if (_process == null || _process.HasExited)
                {
                    return;
                }

                Trace.TraceInformation("Closing app input by sending Ctrl-Z signal");
                _process.StandardInput.Close();

                if (_process == null || _process.HasExited)
                {
                    return;
                }

                Trace.TraceInformation("Trying to close the app gracefully by sending " + closeKey);
                Win32.AttachConsole((uint)_process.Id);
                Win32.SetConsoleCtrlHandler(_consoleCtrlEventHandler, true);
                var ctrlType = closeKey == ConsoleSpecialKey.ControlC ? Win32.CtrlType.CtrlCEvent : Win32.CtrlType.CtrlBreakEvent;
                Win32.GenerateConsoleCtrlEvent(ctrlType, 0);

                if (_process == null || _process.HasExited)
                {
                    return;
                }

                // close console forcefully if not finished within allowed timeout
                Trace.TraceInformation("Waiting for voluntary app exit: Timeout={0}", forceCloseMillisecondsTimeout);
                var exited = _process.WaitForExit(forceCloseMillisecondsTimeout);
                if (!exited)
                {
                    Trace.TraceWarning("Closing the app forcefully");
                    _process.Kill();
                }
            }
            catch (Exception)
            {
                try
                { Process.GetProcessById(ProcessID).Kill(); }
                catch { }
            }
            finally
            {
                FreeProcessResources();
                GC.Collect();
                GC.SuppressFinalize(this);
            }
        }
Пример #7
0
        // Method that is called to handle "cancel" events.
        private static void HandleCancel(ConsoleSpecialKey specialKeys)
        {
            ConsoleCancelEventArgs args;

            args = new ConsoleCancelEventArgs(specialKeys);
            if (CancelKeyPress != null)
            {
                CancelKeyPress(null, args);
            }
            if (!(args.Cancel))
            {
                NormalMode();
                Environment.Exit(1);
            }
        }
        public static void InvalidEnumValueWithCustomParameterizedException()
        {
            const ConsoleSpecialKey invalidValue = (ConsoleSpecialKey)15;
            var observedValue = default(ConsoleSpecialKey);
            var exception     = new Exception();

            Action act = () => invalidValue.MustBeValidEnumValue(v =>
            {
                observedValue = v;
                return(exception);
            });

            act.Should().Throw <Exception>().Which.Should().BeSameAs(exception);
            observedValue.Should().Be(invalidValue);
        }
Пример #9
0
        // Returns true if we've "handled" the break request, false if
        // we want to terminate the process (or at least let the next
        // control handler function have a chance).
        private static bool BreakEvent(int controlType)
        {
            // The thread that this gets called back on has a very small stack on 64 bit systems. There is
            // not enough space to handle a managed exception being caught and thrown. So, queue up a work
            // item on another thread for the actual event callback.

            if (controlType == Win32Native.CTRL_C_EVENT ||
                controlType == Win32Native.CTRL_BREAK_EVENT)
            {
                // To avoid race between remove handler and raising the event
                ConsoleCancelEventHandler cancelCallbacks = Console._cancelCallbacks;
                if (cancelCallbacks == null)
                {
                    return(false);
                }

                // Create the delegate
                ConsoleSpecialKey    controlKey       = (controlType == 0) ? ConsoleSpecialKey.ControlC : ConsoleSpecialKey.ControlBreak;
                ControlCDelegateData delegateData     = new ControlCDelegateData(controlKey, cancelCallbacks);
                WaitCallback         controlCCallback = new WaitCallback(ControlCDelegate);

                // Queue the delegate
                if (!ThreadPool.QueueUserWorkItem(controlCCallback, delegateData))
                {
                    BCLDebug.Assert(false, "ThreadPool.QueueUserWorkItem returned false without throwing. Unable to execute ControlC handler");
                    return(false);
                }
                // Block until the delegate is done. We need to be robust in the face of the work item not executing
                // but we also want to get control back immediately after it is done and we don't want to give the
                // handler a fixed time limit in case it needs to display UI. Wait on the event twice, once with a
                // timout and a second time without if we are sure that the handler actually started.
                TimeSpan controlCWaitTime = new TimeSpan(0, 0, 30); // 30 seconds
                delegateData.CompletionEvent.WaitOne(controlCWaitTime, false);
                if (!delegateData.DelegateStarted)
                {
                    BCLDebug.Assert(false, "ThreadPool.QueueUserWorkItem did not execute the handler within 30 seconds.");
                    return(false);
                }
                delegateData.CompletionEvent.WaitOne();
                delegateData.CompletionEvent.Close();
                return(delegateData.Cancel);
            }
            return(false);
        }
Пример #10
0
        } // Real main()

        #region CtrlC-Handler
        // Now set the handler and do the processing
        //
        void CtrlCHandler(object sender, ConsoleCancelEventArgs args)
        {
            Sup.LogDebugMessage("SensorArray Gracefull exit... Begin");

            ConsoleSpecialKey Key = args.SpecialKey;

            //Sup.LogDebugMessage($"Key Pressed: {Key}");
            //Console.WriteLine($"Key Pressed: {Key}");

            switch (Key)
            {
            // Maybe some time I do a Signal base dynamic errorlevel setting
            // but ctrl-break does  not work on my machine
            case ConsoleSpecialKey.ControlBreak:
                // Look at the end of the file for what I thought to do here if the button worked.
                // For now, let go.
                // Do not immedialtely stop the process.
                args.Cancel = true;
                break;

            case ConsoleSpecialKey.ControlC:
                for (int i = 0; i < MaxNrI2cSensors; i++)
                {
                    thisI2C[i].Stop();
                }
                for (int i = 0; i < MaxNrSerialSensors; i++)
                {
                    thisSerial[i].Stop();
                }
                if (AirLinkEmulation)
                {
                    thisWebserver.Stop();
                }
                args.Cancel = true;       // Do not immedialtely stop the process, handle it by the Continue loop control boolean.
                Continue    = false;
                break;

            default:
                // Should be impossible
                break;
            }

            return;
        }
Пример #11
0
        internal static bool HandleBreakEvent(ConsoleSpecialKey controlKey)
        {
            // The thread that this gets called back on has a very small stack on some systems. There is
            // not enough space to handle a managed exception being caught and thrown. So, run a task
            // on the threadpool for the actual event callback.

            // To avoid the race condition between remove handler and raising the event
            ConsoleCancelEventHandler cancelCallbacks = Console._cancelCallbacks;

            if (cancelCallbacks == null)
            {
                return(false);
            }

            var  delegateData = new ControlCDelegateData(controlKey, cancelCallbacks);
            Task callBackTask = Task.Factory.StartNew(
                d => ((ControlCDelegateData)d).HandleBreakEvent(),
                delegateData,
                CancellationToken.None,
                TaskCreationOptions.DenyChildAttach,
                TaskScheduler.Default);

            // Block until the delegate is done. We need to be robust in the face of the task not executing
            // but we also want to get control back immediately after it is done and we don't want to give the
            // handler a fixed time limit in case it needs to display UI. Wait on the task twice, once with a
            // timeout and a second time without if we are sure that the handler actually started.
            TimeSpan controlCWaitTime = new TimeSpan(0, 0, 30); // 30 seconds

            callBackTask.Wait(controlCWaitTime);

            if (!delegateData.DelegateStarted)
            {
                Debug.Assert(false, "The task to execute the handler did not start within 30 seconds.");
                return(false);
            }

            callBackTask.Wait();
            return(delegateData.Cancel);
        }
Пример #12
0
        /// <summary>
        /// Stop the app.
        /// </summary>
        /// <param name="closeKey">Special key to send to close the app [default=Ctrl-C]</param>
        /// <param name="forceCloseMillisecondsTimeout">Timeout to wait before closing the app forcefully [default=infinite]</param>
        public void Stop(ConsoleSpecialKey closeKey = ConsoleSpecialKey.ControlC, int forceCloseMillisecondsTimeout = Timeout.Infinite)
        {
            ThrowIfDisposed();

            lock (_stateLock)
            {
                if (State == AppState.Undefined || State == AppState.Exited)
                {
                    throw new InvalidOperationException("App is not running.");
                }

                if (State == AppState.Exiting)
                {
                    throw new InvalidOperationException("App is already exiting.");
                }

                State = AppState.Exiting;

                Task.Factory.StartNew(() => CloseConsole(closeKey, forceCloseMillisecondsTimeout),
                                      TaskCreationOptions.LongRunning);
            }
        }
Пример #13
0
        private void CloseConsole(ConsoleSpecialKey closeKey, int forceCloseMillisecondsTimeout)
        {
            if (Process == null || Process.HasExited)
            {
                return;
            }

            Trace.TraceInformation("Closing app input by sending Ctrl-Z signal");
            Process.StandardInput.Close();

            if (Process == null || Process.HasExited)
            {
                return;
            }

            Trace.TraceInformation("Trying to close the app gracefully by sending " + closeKey);
            Win32.AttachConsole((uint)Process.Id);
            Win32.SetConsoleCtrlHandler(_consoleCtrlEventHandler, true);
            var ctrlType = closeKey == ConsoleSpecialKey.ControlC ? Win32.CtrlType.CtrlCEvent : Win32.CtrlType.CtrlBreakEvent;

            Win32.GenerateConsoleCtrlEvent(ctrlType, 0);

            if (Process == null || Process.HasExited)
            {
                return;
            }

            // close console forcefully if not finished within allowed timeout
            Trace.TraceInformation("Waiting for voluntary app exit: Timeout={0}", forceCloseMillisecondsTimeout);
            var exited = Process.WaitForExit(forceCloseMillisecondsTimeout);

            if (!exited)
            {
                Trace.TraceWarning("Closing the app forcefully");
                Process.Kill();
            }
        }
Пример #14
0
	// Method that is called to handle "cancel" events.
	private static void HandleCancel(ConsoleSpecialKey specialKeys)
			{
				ConsoleCancelEventArgs args;
				args = new ConsoleCancelEventArgs(specialKeys);
				if(CancelKeyPress != null)
				{
					CancelKeyPress(null, args);
				}
				if(!(args.Cancel))
				{
					NormalMode();
					Environment.Exit(1);
				}
			}
Пример #15
0
 internal ControlCDelegateData(ConsoleSpecialKey controlKey, ConsoleCancelEventHandler cancelCallbacks)
 {
     _controlKey      = controlKey;
     _cancelCallbacks = cancelCallbacks;
 }
Пример #16
0
        private bool _cancel;  // Whether to cancel the CancelKeyPress event

        internal ConsoleCancelEventArgs(ConsoleSpecialKey type)
        {
            _type   = type;
            _cancel = false;
        }
Пример #17
0
 internal ControlCDelegateData(ConsoleSpecialKey controlKey, ConsoleCancelEventHandler cancelCallbacks) {
     this.ControlKey = controlKey; 
     this.CancelCallbacks = cancelCallbacks; 
     this.CompletionEvent = new ManualResetEvent(false);
     // this.Cancel defaults to false 
     // this.DelegateStarted defaults to false
 }
Пример #18
0
        }                                              // 0x00000001802D2B60-0x00000001802D2B70

        // Constructors
        internal ConsoleCancelEventArgs(ConsoleSpecialKey type)
        {
        }                                                                  // 0x000000018080FAB0-0x000000018080FB20
Пример #19
0
 internal ConsoleCancelEventArgs(ConsoleSpecialKey type)
 {
     _type = type;
 }
	// Constructor.
	internal ConsoleCancelEventArgs(ConsoleSpecialKey specialKey)
			{
				this.cancel = false;
				this.specialKey = specialKey;
			}
 internal ConsoleCancelEventArgs(ConsoleSpecialKey type)
 {
     this._type = type;
     this._cancel = false;
 }
Пример #22
0
		internal ConsoleCancelEventArgs (ConsoleSpecialKey key)
		{
			specialKey = key;
		}
 internal ConsoleCancelEventArgs(ConsoleSpecialKey key)
 {
     specialKey = key;
 }
Пример #24
0
        /// <summary>
        /// Stop the app.
        /// </summary>
        /// <param name="closeKey">Special key to send to close the app [default=Ctrl-C]</param>
        /// <param name="forceCloseMillisecondsTimeout">Timeout to wait before closing the app forcefully [default=infinite]</param>
        public void Stop(ConsoleSpecialKey closeKey = ConsoleSpecialKey.ControlC, int forceCloseMillisecondsTimeout = Timeout.Infinite)
        {
            ThrowIfDisposed();

            lock (_stateLock)
            {
                if (State == AppState.Undefined || State == AppState.Exited)
                    throw new InvalidOperationException("App is not running.");

                if (State == AppState.Exiting)
                    throw new InvalidOperationException("App is already exiting.");

                State = AppState.Exiting;

                Task.Factory.StartNew(() => CloseConsole(closeKey, forceCloseMillisecondsTimeout),
                    TaskCreationOptions.LongRunning);
            }
        }
Пример #25
0
 // Constructor.
 internal ConsoleCancelEventArgs(ConsoleSpecialKey specialKey)
 {
     this.cancel     = false;
     this.specialKey = specialKey;
 }
Пример #26
0
        private void CloseConsole(ConsoleSpecialKey closeKey, int forceCloseMillisecondsTimeout)
        {
            if (_process == null || _process.HasExited)
                return;

            Trace.TraceInformation("Closing app input by sending Ctrl-Z signal");
            _process.StandardInput.Close();

            if (_process == null || _process.HasExited)
                return;

            Trace.TraceInformation("Trying to close the app gracefully by sending " + closeKey);
            Win32.AttachConsole((uint)_process.Id);
            Win32.SetConsoleCtrlHandler(_consoleCtrlEventHandler, true);
            var ctrlType = closeKey == ConsoleSpecialKey.ControlC ? Win32.CtrlType.CtrlCEvent : Win32.CtrlType.CtrlBreakEvent;
            Win32.GenerateConsoleCtrlEvent(ctrlType, 0);

            if (_process == null || _process.HasExited)
                return;

            // close console forcefully if not finished within allowed timeout
            Trace.TraceInformation("Waiting for voluntary app exit: Timeout={0}", forceCloseMillisecondsTimeout);
            var exited = _process.WaitForExit(forceCloseMillisecondsTimeout);
            if (!exited)
            {
                Trace.TraceWarning("Closing the app forcefully");
                _process.Kill();
            }
        }
Пример #27
0
 /// <summary>
 /// The event handler for this event is executed on a thread pool thread.
 /// </summary>
 /// <param name="consoleSpecialKey"> </param>
 /// <returns> </returns>
 protected virtual bool OnCancelKeySignal(ConsoleSpecialKey consoleSpecialKey)
 {
     return(false);
 }