/// <summary> /// Task runner method /// </summary> private void RunTask(object state) { _isTaskExecuting = true; OutOfProcTaskHostTaskResult taskResult = null; TaskHostConfiguration taskConfiguration = state as TaskHostConfiguration; IDictionary<string, TaskParameter> taskParams = taskConfiguration.TaskParameters; // We only really know the values of these variables for sure once we see what we received from our parent // environment -- otherwise if this was a completely new build, we could lose out on expected environment // variables. _debugCommunications = taskConfiguration.BuildProcessEnvironment.ContainsValueAndIsEqual("MSBUILDDEBUGCOMM", "1", StringComparison.OrdinalIgnoreCase); _updateEnvironment = !taskConfiguration.BuildProcessEnvironment.ContainsValueAndIsEqual("MSBuildTaskHostDoNotUpdateEnvironment", "1", StringComparison.OrdinalIgnoreCase); _updateEnvironmentAndLog = taskConfiguration.BuildProcessEnvironment.ContainsValueAndIsEqual("MSBuildTaskHostUpdateEnvironmentAndLog", "1", StringComparison.OrdinalIgnoreCase); try { // Change to the startup directory NativeMethodsShared.SetCurrentDirectory(taskConfiguration.StartupDirectory); if (_updateEnvironment) { InitializeMismatchedEnvironmentTable(taskConfiguration.BuildProcessEnvironment); } // Now set the new environment SetTaskHostEnvironment(taskConfiguration.BuildProcessEnvironment); // Set culture Thread.CurrentThread.CurrentCulture = taskConfiguration.Culture; Thread.CurrentThread.CurrentUICulture = taskConfiguration.UICulture; string taskName = taskConfiguration.TaskName; string taskLocation = taskConfiguration.TaskLocation; // We will not create an appdomain now because of a bug // As a fix, we will create the class directly without wrapping it in a domain _taskWrapper = new OutOfProcTaskAppDomainWrapper(); taskResult = _taskWrapper.ExecuteTask ( this as IBuildEngine, taskName, taskLocation, taskConfiguration.ProjectFileOfTask, taskConfiguration.LineNumberOfTask, taskConfiguration.ColumnNumberOfTask, taskConfiguration.AppDomainSetup, taskParams ); } catch (Exception e) { if (e is ThreadAbortException) { // This thread was aborted as part of Cancellation, we will return a failure task result taskResult = new OutOfProcTaskHostTaskResult(TaskCompleteType.Failure); } else if (ExceptionHandling.IsCriticalException(e)) { throw; } else { taskResult = new OutOfProcTaskHostTaskResult(TaskCompleteType.CrashedDuringExecution, e); } } finally { try { _isTaskExecuting = false; IDictionary<string, string> currentEnvironment = CommunicationsUtilities.GetEnvironmentVariables(); currentEnvironment = UpdateEnvironmentForMainNode(currentEnvironment); if (taskResult == null) { taskResult = new OutOfProcTaskHostTaskResult(TaskCompleteType.Failure); } lock (_taskCompleteLock) { _taskCompletePacket = new TaskHostTaskComplete ( taskResult, currentEnvironment ); } foreach (TaskParameter param in taskParams.Values) { // Tell remoting to forget connections to the parameter RemotingServices.Disconnect(param); } // Restore the original clean environment CommunicationsUtilities.SetEnvironment(_savedEnvironment); } catch (Exception e) { lock (_taskCompleteLock) { // Create a minimal taskCompletePacket to carry the exception so that the TaskHostTask does not hang while waiting _taskCompletePacket = new TaskHostTaskComplete(new OutOfProcTaskHostTaskResult(TaskCompleteType.CrashedAfterExecution, e), null); } } finally { // Call CleanupTask to unload any domains and other necessary cleanup in the taskWrapper _taskWrapper.CleanupTask(); // The task has now fully completed executing _taskCompleteEvent.Set(); } } }
/// <summary> /// Constructor /// </summary> /// <param name="result">Result of the task's execution.</param> /// <param name="buildProcessEnvironment">The build process environment as it was at the end of the task's execution.</param> public TaskHostTaskComplete(OutOfProcTaskHostTaskResult result, IDictionary<string, string> buildProcessEnvironment) { ErrorUtilities.VerifyThrowInternalNull(result, "result"); _taskResult = result.Result; _taskException = result.TaskException; _taskExceptionMessage = result.ExceptionMessage; _taskExceptionMessageArgs = result.ExceptionMessageArgs; if (result.FinalParameterValues != null) { _taskOutputParameters = new Dictionary<string, TaskParameter>(StringComparer.OrdinalIgnoreCase); foreach (KeyValuePair<string, object> parameter in result.FinalParameterValues) { _taskOutputParameters[parameter.Key] = new TaskParameter(parameter.Value); } } if (buildProcessEnvironment != null) { _buildProcessEnvironment = buildProcessEnvironment as Dictionary<string, string>; if (_buildProcessEnvironment == null) { _buildProcessEnvironment = new Dictionary<string, string>(buildProcessEnvironment); } } }