private async Task ExecuteInstantiatedTask()

in src/Build/BackEnd/Components/RequestBuilder/TaskBuilder.cs [736:968]


        private async Task<WorkUnitResult> ExecuteInstantiatedTask(ITaskExecutionHost taskExecutionHost, TaskLoggingContext taskLoggingContext, TaskHost taskHost, ItemBucket bucket, TaskExecutionMode howToExecuteTask)
        {
            UpdateContinueOnError(bucket, taskHost);

            bool taskResult = false;

            WorkUnitResultCode resultCode = WorkUnitResultCode.Success;
            WorkUnitActionCode actionCode = WorkUnitActionCode.Continue;

            if (!taskExecutionHost.SetTaskParameters(_taskNode.ParametersForBuild))
            {
                // The task cannot be initialized.
                ProjectErrorUtilities.VerifyThrowInvalidProject(false, _targetChildInstance.Location, "TaskParametersError", _taskNode.Name, String.Empty);
            }
            else
            {
                bool taskReturned = false;
                Exception taskException = null;

                // If this is the MSBuild task, we need to execute it's special internal method.
                TaskExecutionHost host = taskExecutionHost as TaskExecutionHost;
                Type taskType = host.TaskInstance.GetType();

                try
                {
                    if (taskType == typeof(MSBuild))
                    {
                        MSBuild msbuildTask = host.TaskInstance as MSBuild;
                        ErrorUtilities.VerifyThrow(msbuildTask != null, "Unexpected MSBuild internal task.");
                        _targetBuilderCallback.EnterMSBuildCallbackState();

                        try
                        {
                            taskResult = await msbuildTask.ExecuteInternal();
                        }
                        finally
                        {
                            _targetBuilderCallback.ExitMSBuildCallbackState();
                        }
                    }
                    else if (taskType == typeof(CallTarget))
                    {
                        CallTarget callTargetTask = host.TaskInstance as CallTarget;
                        taskResult = await callTargetTask.ExecuteInternal();
                    }
                    else
                    {
#if FEATURE_FILE_TRACKER
                        using (FullTracking.Track(taskLoggingContext.TargetLoggingContext.Target.Name, _taskNode.Name, _buildRequestEntry.ProjectRootDirectory, _buildRequestEntry.RequestConfiguration.Project.PropertiesToBuildWith))
#endif
                        {
                            taskResult = taskExecutionHost.Execute();
                        }
                    }
                }
                catch (Exception ex)
                {
                    if (ExceptionHandling.IsCriticalException(ex) || (Environment.GetEnvironmentVariable("MSBUILDDONOTCATCHTASKEXCEPTIONS") == "1"))
                    {
                        throw;
                    }

                    taskException = ex;
                }

                if (taskException == null)
                {
                    taskReturned = true;

                    // Set the property "MSBuildLastTaskResult" to reflect whether the task succeeded or not.
                    // The main use of this is if ContinueOnError is true -- so that the next task can consult the result.
                    // So we want it to be "false" even if ContinueOnError is true. 
                    // The constants "true" and "false" should NOT be localized. They become property values.
                    bucket.Lookup.SetProperty(ProjectPropertyInstance.Create(ReservedPropertyNames.lastTaskResult, taskResult ? "true" : "false", true/* may be reserved */, _buildRequestEntry.RequestConfiguration.Project.IsImmutable));
                }
                else
                {
                    Type type = taskException.GetType();

                    if (type == typeof(LoggerException))
                    {
                        // if a logger has failed, abort immediately
                        // Polite logger failure
                        _continueOnError = ContinueOnError.ErrorAndStop;

                        // Rethrow wrapped in order to avoid losing the callstack
                        throw new LoggerException(taskException.Message, taskException);
                    }
                    else if (type == typeof(InternalLoggerException))
                    {
                        // Logger threw arbitrary exception
                        _continueOnError = ContinueOnError.ErrorAndStop;
                        InternalLoggerException ex = taskException as InternalLoggerException;

                        // Rethrow wrapped in order to avoid losing the callstack
                        throw new InternalLoggerException(taskException.Message, taskException, ex.BuildEventArgs, ex.ErrorCode, ex.HelpKeyword, ex.InitializationException);
                    }
#if FEATURE_VARIOUS_EXCEPTIONS
                    else if (type == typeof(ThreadAbortException))
                    {
                        Thread.ResetAbort();
                        _continueOnError = ContinueOnError.ErrorAndStop;

                        // Cannot rethrow wrapped as ThreadAbortException is sealed and has no appropriate constructor
                        // Stack will be lost
                        throw taskException;
                    }
#endif
                    else if (type == typeof(BuildAbortedException))
                    {
                        _continueOnError = ContinueOnError.ErrorAndStop;

                        // Rethrow wrapped in order to avoid losing the callstack
                        throw new BuildAbortedException(taskException.Message, ((BuildAbortedException)taskException));
                    }
                    else if (type == typeof(CircularDependencyException))
                    {
                        _continueOnError = ContinueOnError.ErrorAndStop;
                        ProjectErrorUtilities.ThrowInvalidProject(taskLoggingContext.Task.Location, "CircularDependency", taskLoggingContext.TargetLoggingContext.Target.Name);
                    }
                    else if (type == typeof(InvalidProjectFileException))
                    {
                        // Just in case this came out of a task, make sure it's not
                        // marked as having been logged.
                        InvalidProjectFileException ipex = (InvalidProjectFileException)taskException;
                        ipex.HasBeenLogged = false;

                        if (_continueOnError != ContinueOnError.ErrorAndStop)
                        {
                            taskLoggingContext.LogInvalidProjectFileError(ipex);
                            taskLoggingContext.LogComment(MessageImportance.Normal, "ErrorConvertedIntoWarning");
                        }
                        else
                        {
                            // Rethrow wrapped in order to avoid losing the callstack
                            throw new InvalidProjectFileException(ipex.Message, ipex);
                        }
                    }
                    else if (type == typeof(Exception) || type.GetTypeInfo().IsSubclassOf(typeof(Exception)))
                    {
                        // Occasionally, when debugging a very uncommon task exception, it is useful to loop the build with 
                        // a debugger attached to break on 2nd chance exceptions.
                        // That requires that there needs to be a way to not catch here, by setting an environment variable.
                        if (ExceptionHandling.IsCriticalException(taskException) || (Environment.GetEnvironmentVariable("MSBUILDDONOTCATCHTASKEXCEPTIONS") == "1"))
                        {
                            // Wrapping in an Exception will unfortunately mean that this exception would fly through any IsCriticalException above.
                            // However, we should not have any, also we should not have stashed such an exception anyway.
                            throw new Exception(taskException.Message, taskException);
                        }

                        Exception exceptionToLog = taskException;

                        if (exceptionToLog is TargetInvocationException)
                        {
                            exceptionToLog = exceptionToLog.InnerException;
                        }

                        // handle any exception thrown by the task during execution
                        // NOTE: We catch ALL exceptions here, to attempt to completely isolate the Engine
                        // from failures in the task.
                        if (_continueOnError == ContinueOnError.WarnAndContinue)
                        {
                            taskLoggingContext.LogTaskWarningFromException
                            (
                                new BuildEventFileInfo(_targetChildInstance.Location),
                                exceptionToLog,
                                _taskNode.Name
                            );

                            // Log a message explaining why we converted the previous error into a warning.
                            taskLoggingContext.LogComment(MessageImportance.Normal, "ErrorConvertedIntoWarning");
                        }
                        else
                        {
                            taskLoggingContext.LogFatalTaskError
                            (
                                new BuildEventFileInfo(_targetChildInstance.Location),
                                exceptionToLog,
                                _taskNode.Name
                            );
                        }
                    }
                    else
                    {
                        ErrorUtilities.ThrowInternalErrorUnreachable();
                    }
                }

                // If the task returned attempt to gather its outputs.  If gathering outputs fails set the taskResults
                // to false
                if (taskReturned)
                {
                    taskResult = GatherTaskOutputs(taskExecutionHost, howToExecuteTask, bucket) && taskResult;
                }

                // If the taskResults are false look at ContinueOnError.  If ContinueOnError=false (default)
                // mark the taskExecutedSuccessfully=false.  Otherwise let the task succeed but log a normal
                // pri message that says this task is continuing because ContinueOnError=true
                resultCode = taskResult ? WorkUnitResultCode.Success : WorkUnitResultCode.Failed;
                actionCode = WorkUnitActionCode.Continue;
                if (resultCode == WorkUnitResultCode.Failed)
                {
                    if (_continueOnError == ContinueOnError.ErrorAndStop)
                    {
                        actionCode = WorkUnitActionCode.Stop;
                    }
                    else
                    {
                        // This is the ErrorAndContinue or WarnAndContinue case...
                        string settingString = "true";
                        if (_taskNode.ContinueOnErrorLocation != null)
                        {
                            settingString = bucket.Expander.ExpandIntoStringAndUnescape(_taskNode.ContinueOnError, ExpanderOptions.ExpandAll, _taskNode.ContinueOnErrorLocation); // expand embedded item vectors after expanding properties and item metadata
                        }

                        taskLoggingContext.LogComment
                        (
                            MessageImportance.Normal,
                            "TaskContinuedDueToContinueOnError",
                            "ContinueOnError",
                            _taskNode.Name,
                            settingString
                        );

                        actionCode = WorkUnitActionCode.Continue;
                    }
                }
            }

            WorkUnitResult result = new WorkUnitResult(resultCode, actionCode, null);

            return result;
        }