Beispiel #1
0
        protected override void OnStop()
        {
            lock (ServiceLock)
            {
                Stopping = true;

                // TODO If agent service is killed make sure AgentListener also is killed
                try
                {
                    if (AgentListener != null && !AgentListener.HasExited)
                    {
                        // Try to let the agent process know that we are stopping
                        // TODO: This is not working, fix it
                        AgentListener.StandardInput.WriteLine("\x03");

                        // Wait for the process to finish (give it up to 30 seconds)
                        AgentListener.WaitForExit(30000);
                        // if agent is still running, kill it
                        if (!AgentListener.HasExited)
                        {
                            AgentListener.Kill();
                        }
                    }
                }
                catch (Exception exception)
                {
                    // InvalidOperationException is thrown when there is no process associated to the process object.
                    // There is no process to kill, Log the exception and shutdown the service.
                    // If we don't handle this here, the service get into a state where it can neither be stoped nor restarted (Error 1061)
                    WriteException(exception);
                }
            }
        }
Beispiel #2
0
        protected override void OnStop()
        {
            lock (ServiceLock)
            {
                Stopping = true;

                // throw exception during OnStop() will make SCM think the service crash and trigger recovery option.
                // in this way we can self-update the service host.
                if (_restart)
                {
                    throw new Exception(Resource.CrashServiceHost);
                }

                // TODO If agent service is killed make sure AgentListener also is killed
                try
                {
                    if (AgentListener != null && !AgentListener.HasExited)
                    {
                        // Try to let the agent process know that we are stopping
                        //Attach service process to console of Agent.Listener process. This is needed,
                        //because windows service doesn't use its own console.
                        if (AttachConsole((uint)AgentListener.Id))
                        {
                            //Prevent main service process from stopping because of Ctrl + C event with SetConsoleCtrlHandler
                            SetConsoleCtrlHandler(null, true);
                            try
                            {
                                //Generate console event for current console with GenerateConsoleCtrlEvent (processGroupId should be zero)
                                GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
                                //Wait for the process to finish (give it up to 30 seconds)
                                AgentListener.WaitForExit(30000);
                            }
                            finally
                            {
                                //Disconnect from console and restore Ctrl+C handling by main process
                                FreeConsole();
                                SetConsoleCtrlHandler(null, false);
                            }
                        }

                        // if agent is still running, kill it
                        if (!AgentListener.HasExited)
                        {
                            AgentListener.Kill();
                        }
                    }
                }
                catch (Exception exception)
                {
                    // InvalidOperationException is thrown when there is no process associated to the process object.
                    // There is no process to kill, Log the exception and shutdown the service.
                    // If we don't handle this here, the service get into a state where it can neither be stoped nor restarted (Error 1061)
                    WriteException(exception);
                }
            }
        }
Beispiel #3
0
        // this will send either Ctrl-C or Ctrl-Break to agent.listener
        // Ctrl-C will be used for OnStop()
        // Ctrl-Break will be used for OnShutdown()
        private void SendCtrlSignalToAgentListener(uint signal)
        {
            try
            {
                if (AgentListener != null && !AgentListener.HasExited)
                {
                    // Try to let the agent process know that we are stopping
                    //Attach service process to console of Agent.Listener process. This is needed,
                    //because windows service doesn't use its own console.
                    if (AttachConsole((uint)AgentListener.Id))
                    {
                        //Prevent main service process from stopping because of Ctrl + C event with SetConsoleCtrlHandler
                        SetConsoleCtrlHandler(null, true);
                        try
                        {
                            //Generate console event for current console with GenerateConsoleCtrlEvent (processGroupId should be zero)
                            GenerateConsoleCtrlEvent(signal, 0);
                            //Wait for the process to finish (give it up to 30 seconds)
                            AgentListener.WaitForExit(30000);
                        }
                        finally
                        {
                            //Disconnect from console and restore Ctrl+C handling by main process
                            FreeConsole();
                            SetConsoleCtrlHandler(null, false);
                        }
                    }

                    // if agent is still running, kill it
                    if (!AgentListener.HasExited)
                    {
                        AgentListener.Kill();
                    }
                }
            }
            catch (Exception exception)
            {
                // InvalidOperationException is thrown when there is no process associated to the process object.
                // There is no process to kill, Log the exception and shutdown the service.
                // If we don't handle this here, the service get into a state where it can neither be stoped nor restarted (Error 1061)
                WriteException(exception);
            }
        }
Beispiel #4
0
        protected override void OnStart(string[] args)
        {
            RunningLoop = Task.Run(
                () =>
            {
                try
                {
                    bool stopping;
                    WriteInfo("Starting VSTS Agent Service");
                    TimeSpan timeBetweenRetries = TimeSpan.FromSeconds(5);

                    lock (ServiceLock)
                    {
                        stopping = Stopping;
                    }

                    while (!stopping)
                    {
                        WriteInfo("Starting VSTS Agent listener");
                        lock (ServiceLock)
                        {
                            AgentListener = CreateAgentListener();
                            AgentListener.OutputDataReceived += AgentListener_OutputDataReceived;
                            AgentListener.ErrorDataReceived  += AgentListener_ErrorDataReceived;
                            AgentListener.Start();
                            AgentListener.BeginOutputReadLine();
                            AgentListener.BeginErrorReadLine();
                        }

                        AgentListener.WaitForExit();
                        int exitCode = AgentListener.ExitCode;

                        // exit code 0 and 1 need stop service
                        // exit code 2 and 3 need restart agent
                        switch (exitCode)
                        {
                        case 0:
                            Stopping = true;
                            WriteInfo(Resource.AgentExitWithoutError);
                            break;

                        case 1:
                            Stopping = true;
                            WriteInfo(Resource.AgentExitWithTerminatedError);
                            break;

                        case 2:
                            WriteInfo(Resource.AgentExitWithError);
                            break;

                        case 3:
                            WriteInfo(Resource.AgentUpdateInProcess);
                            var updateResult = HandleAgentUpdate();
                            if (updateResult == AgentUpdateResult.Succeed)
                            {
                                WriteInfo(Resource.AgentUpdateSucceed);
                            }
                            else if (updateResult == AgentUpdateResult.Failed)
                            {
                                WriteInfo(Resource.AgentUpdateFailed);
                                Stopping = true;
                            }
                            else if (updateResult == AgentUpdateResult.SucceedNeedRestart)
                            {
                                WriteInfo(Resource.AgentUpdateRestartNeeded);
                                _restart = true;
                                ExitCode = int.MaxValue;
                                Stop();
                            }
                            break;

                        default:
                            WriteInfo(Resource.AgentExitWithUndefinedReturnCode);
                            break;
                        }

                        if (Stopping)
                        {
                            ExitCode = exitCode;
                            Stop();
                        }
                        else
                        {
                            // wait for few seconds before restarting the process
                            Thread.Sleep(timeBetweenRetries);
                        }

                        lock (ServiceLock)
                        {
                            AgentListener.OutputDataReceived -= AgentListener_OutputDataReceived;
                            AgentListener.ErrorDataReceived  -= AgentListener_ErrorDataReceived;
                            AgentListener.Dispose();
                            AgentListener = null;
                            stopping      = Stopping;
                        }
                    }
                }
                catch (Exception exception)
                {
                    WriteException(exception);
                    ExitCode = 99;
                    Stop();
                }
            });
        }
Beispiel #5
0
        protected override void OnStart(string[] args)
        {
            RunningLoop = Task.Run(
                () =>
            {
                try
                {
                    bool stopping;
                    WriteInfo("Starting VSTS Agent Service");
                    TimeSpan timeBetweenRetries = TimeSpan.FromSeconds(5);

                    lock (ServiceLock)
                    {
                        stopping = Stopping;
                    }

                    while (!stopping)
                    {
                        WriteInfo("Starting VSTS Agent listener");
                        lock (ServiceLock)
                        {
                            AgentListener = CreateAgentListener();
                            AgentListener.Start();
                        }

                        AgentListener.WaitForExit();
                        int exitCode = AgentListener.ExitCode;

                        // Handle error code 1?
                        // If agent fails (because its not configured) also returns error code 1, in such case we dont want to run the service
                        // Killing a process also returns error code 1, but we want to restart the process here.
                        // TODO: change the error code for run method if agent is not configured?

                        if (exitCode == 2)
                        {
                            // Agent wants to stop the service as well
                            Stopping = true;
                            WriteInfo(Resource.ServiceRequestedToStop);
                            ExitCode = exitCode;
                            Stop();
                        }
                        else
                        {
                            // wait for few seconds before restarting the process
                            Thread.Sleep(timeBetweenRetries);
                        }
                    }

                    lock (ServiceLock)
                    {
                        AgentListener.Dispose();
                        AgentListener = null;
                    }
                }
                catch (Exception exception)
                {
                    WriteException(exception);
                    ExitCode = 1;
                    Stop();
                }
            });
        }