/// <summary> /// Factory for deserialization. /// </summary> internal static INodePacket FactoryForDeserialization(ITranslator translator) { TaskHostTaskComplete taskComplete = new TaskHostTaskComplete(); taskComplete.Translate(translator); return(taskComplete); }
/// <summary> /// Task completed executing in the task host /// </summary> private void HandleTaskHostTaskComplete(TaskHostTaskComplete taskHostTaskComplete) { // If it crashed, or if it failed, it didn't succeed. _taskExecutionSucceeded = taskHostTaskComplete.TaskResult == TaskCompleteType.Success ? true : false; // reset the environment, as though the task were executed in this process all along. CommunicationsUtilities.SetEnvironment(taskHostTaskComplete.BuildProcessEnvironment); // If it crashed during the execution phase, then we can effectively replicate the inproc task execution // behaviour by just throwing here and letting the taskbuilder code take care of it the way it would // have normally. // We will also replicate the same behaviour if the TaskHost caught some exceptions after execution of the task. if ((taskHostTaskComplete.TaskResult == TaskCompleteType.CrashedDuringExecution) || (taskHostTaskComplete.TaskResult == TaskCompleteType.CrashedAfterExecution)) { throw new TargetInvocationException(taskHostTaskComplete.TaskException); } // On the other hand, if it crashed during initialization, there's not really a way to effectively replicate // the inproc behavior -- in the inproc case, the task would have failed to load and crashed long before now. // Furthermore, if we were just to throw here like in the execution case, we'd lose the ability to log // different messages based on the circumstances of the initialization failure -- whether it was a setter failure, // the task just could not be loaded, etc. // So instead, when we catch the exception in the task host, we'll also record what message we want it to use // when the error is logged; and given that information, log that error here. This has the effect of differing // from the inproc case insofar as ContinueOnError is now respected, instead of forcing a stop here. if (taskHostTaskComplete.TaskResult == TaskCompleteType.CrashedDuringInitialization) { string exceptionMessage; string[] exceptionMessageArgs; if (taskHostTaskComplete.TaskExceptionMessage != null) { exceptionMessage = taskHostTaskComplete.TaskExceptionMessage; exceptionMessageArgs = taskHostTaskComplete.TaskExceptionMessageArgs; } else { exceptionMessage = "TaskInstantiationFailureError"; exceptionMessageArgs = new string[] { _taskType.Type.Name, AssemblyUtilities.GetAssemblyLocation(_taskType.Type.GetTypeInfo().Assembly), string.Empty }; } _taskLoggingContext.LogFatalError(taskHostTaskComplete.TaskException, new BuildEventFileInfo(_taskLocation), taskHostTaskComplete.TaskExceptionMessage, taskHostTaskComplete.TaskExceptionMessageArgs); } // Set the output parameters for later foreach (KeyValuePair <string, TaskParameter> outputParam in taskHostTaskComplete.TaskOutputParameters) { _setParameters[outputParam.Key] = outputParam.Value?.WrappedParameter; } }