private OutputParams ProcessWindow(InputParams inputs, ref bool SkillIsPausable)
        {
            //This is the implementation of the "first" Method provided to the Skills (the "process method")

            //Remark : this method is quite complicated because it has to deal with windows and HMI, so it requires access to the UI thread.

            //Skill is currently not pausable
            SkillIsPausable = false;
            InputsForFakeWindow value;

            //First cast the inputs
            try
            {
                value = (InputsForFakeWindow)inputs.Values;
            }
            catch (System.InvalidCastException ex)
            {
                //If you can't cast the inputs, then there is a special error code for this
                return(new OutputParams(Skill.ERROR_VALUES_PROCESS_INVALID, null));
            }

            //Then execute the code

            try
            {
                //Lets say skill is productive (even if it is not that true)
                inputs.IsProductive = true;

                //Update remaining time
                value.RemainingTimeMs = value.ExecutionTimeMs;

                inputs.RemainingDuration = (UInt32)value.RemainingTimeMs;

                //First Ask (the UI thread) to pop a new window
                InputsForFakeWindow argsFirst = new InputsForFakeWindow()
                {
                    StartANewWindow = true,
                    RemainingTimeMs = value.RemainingTimeMs,
                    CloseTheWindow  = false,
                    ExecutionTimeMs = value.ExecutionTimeMs,
                    NameOfSkill     = value.NameOfSkill,
                    Status          = "EXECUTING"
                };

                OnDisplayOnSkillWindow(argsFirst);


                //Then perform a loop, each second, after each second
                int subdivision = value.ExecutionTimeMs / 1000;

                //You can subscribe to the "Pausing" event, if you want to have notification of the Pausing.
                //The SEE mother class also subscribed to that event, to notify the OPC-UA about the state change
                inputs.Pausing += inputs_Pausing;

                if (subdivision >= 1)
                {
                    //SKill is now pausable => turn SkillIsPausable to true
                    SkillIsPausable = true;

                    //there are more than 1 second of execution time
                    for (int i = 0; i < subdivision; i++)
                    {
                        double remainingTime = (((double)value.ExecutionTimeMs) - i * 1000.0);

                        inputs.StopOrPauseIfRequired(); //You can use this line of code to block or stop the execution, if a Stop or pause was required

                        InputsForFakeWindow argsLoop = new InputsForFakeWindow()
                        {
                            StartANewWindow = false,
                            RemainingTimeMs = (int)remainingTime,
                            CloseTheWindow  = false,
                            ExecutionTimeMs = value.ExecutionTimeMs,
                            NameOfSkill     = value.NameOfSkill,
                            Status          = "EXECUTING"
                        };

                        OnDisplayOnSkillWindow(argsLoop);

                        //Update remaining time before sleeping
                        inputs.RemainingDuration = (UInt32)remainingTime;

                        //Sleep 1s
                        System.Threading.Thread.Sleep(1000);

                        inputs.StopOrPauseIfRequired(); //You can use this line of code to block or stop the execution, if a Stop or pause was required
                    }

                    double LastValue = (((double)value.ExecutionTimeMs) - subdivision * 1000.0);

                    inputs.StopOrPauseIfRequired(); //You can use this line of code to block or stop the execution, if a Stop or pause was required

                    InputsForFakeWindow argsLastLoop = new InputsForFakeWindow()
                    {
                        StartANewWindow = false,
                        RemainingTimeMs = (int)LastValue,
                        CloseTheWindow  = false,
                        ExecutionTimeMs = value.ExecutionTimeMs,
                        NameOfSkill     = value.NameOfSkill,
                        Status          = "EXECUTING"
                    };

                    OnDisplayOnSkillWindow(argsLastLoop);

                    //SKill is no longer pausable => turn SkillIsPausable to false
                    SkillIsPausable = false;
                    inputs.StopOrPauseIfRequired();
                    inputs.Pausing -= inputs_Pausing;

                    //Update remaining time before sleeping
                    inputs.RemainingDuration = (UInt32)LastValue;

                    //Sleep the remaining time
                    System.Threading.Thread.Sleep((int)LastValue);
                }
                else
                {
                    //there are Less than 1 second of execution time

                    //SKill is now pausable => turn SkillIsPausable to true
                    SkillIsPausable = true;
                    inputs.StopOrPauseIfRequired();//You can use this line of code to block or stop the execution, if a Stop or pause was required

                    InputsForFakeWindow argsLess1 = new InputsForFakeWindow()
                    {
                        StartANewWindow = false,
                        RemainingTimeMs = value.ExecutionTimeMs,
                        CloseTheWindow  = false,
                        ExecutionTimeMs = value.ExecutionTimeMs,
                        NameOfSkill     = value.NameOfSkill,
                        Status          = "EXECUTING"
                    };

                    OnDisplayOnSkillWindow(argsLess1);

                    //SKill is no longer pausable => turn SkillIsPausable to false
                    SkillIsPausable = false;
                    inputs.StopOrPauseIfRequired();
                    inputs.Pausing -= inputs_Pausing;

                    //Update remaining time before sleeping
                    inputs.RemainingDuration = (UInt32)value.ExecutionTimeMs;

                    //Sleep
                    System.Threading.Thread.Sleep(value.ExecutionTimeMs);
                }


                //Display that skill execution is about to finish

                InputsForFakeWindow argsAboutToClose = new InputsForFakeWindow()
                {
                    StartANewWindow = false,
                    RemainingTimeMs = 0,
                    CloseTheWindow  = false,
                    ExecutionTimeMs = value.ExecutionTimeMs,
                    NameOfSkill     = value.NameOfSkill,
                    Status          = "ABOUT TO FINISH : ANSWER QUESTION FIRST"
                };

                OnDisplayOnSkillWindow(argsAboutToClose);


                //Then finnaly, you have to prepare the "OutputParams".
                //These "OutputParams" then returned in the overriden method GetOutputsOfExecutedSkill
                //So take care of what you are providing

                OutputParams outp = InterativeAskReturnedCode(value, ERROR_DURING_EXECUTION);

                InputsForFakeWindow argsClose = new InputsForFakeWindow()
                {
                    StartANewWindow = false,
                    RemainingTimeMs = 0,
                    CloseTheWindow  = false,
                    ExecutionTimeMs = value.ExecutionTimeMs,
                    NameOfSkill     = value.NameOfSkill,
                    Status          = "FINISHED"
                };

                OnDisplayOnSkillWindow(argsClose);

                //Check if you have an alternative post condition
                if (value.AlternativePostConditionAvailable && outp.ReturnCode == 0)
                {
                    //Ask user if he wants to go to alternative post condition
                    System.Windows.MessageBoxResult res = System.Windows.MessageBox.Show("Do you want to go to alternative post condition?", "Alternative", System.Windows.MessageBoxButton.YesNo);

                    switch (res)
                    {
                    case System.Windows.MessageBoxResult.Yes:
                        outp.GoToAlternativePostCondition = true;
                        break;

                    default:
                        outp.GoToAlternativePostCondition = false;
                        break;
                    }
                }

                //you don't have to Update remaining time to "0" => it is already done in the SEE mother class

                return(outp);
            }
            catch (OperationCanceledException ex)
            {
                //External element asked for "emergency stop".
                //The "Closing Method" will be called (second method passed to the constructor of the skill)

                //You can do some memory freeing here.

                //And then, rethrow the exception
                throw;
            }
            catch (Exception ex)
            {
                return(new OutputParams(ERROR_DURING_EXECUTION, null, false, new SkillProException(ex.Message, ex)));
            }
        }