Exemple #1
0
        /// <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);
                }
            }
        }
        /// <summary>
        /// Execute a task on the STA thread.
        /// </summary>
        /// <comment>
        /// STA thread launching code lifted from XMakeBuildEngine\BackEnd\Components\RequestBuilder\TaskBuilder.cs, ExecuteTaskInSTAThread method.
        /// Any bug fixes made to this code, please ensure that you also fix that code.
        /// </comment>
        private OutOfProcTaskHostTaskResult InstantiateAndExecuteTaskInSTAThread
        (
            IBuildEngine oopTaskHostNode,
            LoadedType taskType,
            string taskName,
            string taskLocation,
            string taskFile,
            int taskLine,
            int taskColumn,
#if FEATURE_APPDOMAIN
            AppDomainSetup appDomainSetup,
#endif
            IDictionary <string, TaskParameter> taskParams
        )
        {
            ManualResetEvent            taskRunnerFinished = new ManualResetEvent(false);
            OutOfProcTaskHostTaskResult taskResult         = null;
            Exception exceptionFromExecution = null;

            try
            {
                ThreadStart taskRunnerDelegate = delegate()
                {
                    try
                    {
                        taskResult = InstantiateAndExecuteTask
                                     (
                            oopTaskHostNode,
                            taskType,
                            taskName,
                            taskLocation,
                            taskFile,
                            taskLine,
                            taskColumn,
#if FEATURE_APPDOMAIN
                            appDomainSetup,
#endif
                            taskParams
                                     );
                    }
                    catch (Exception e)
                    {
                        if (ExceptionHandling.IsCriticalException(e))
                        {
                            throw;
                        }

                        exceptionFromExecution = e;
                    }
                    finally
                    {
                        taskRunnerFinished.Set();
                    }
                };

                Thread staThread = new Thread(taskRunnerDelegate);
                staThread.SetApartmentState(ApartmentState.STA);
                staThread.Name             = "MSBuild STA task runner thread";
                staThread.CurrentCulture   = Thread.CurrentThread.CurrentCulture;
                staThread.CurrentUICulture = Thread.CurrentThread.CurrentUICulture;
                staThread.Start();

                // TODO: Why not just Join on the thread???
                taskRunnerFinished.WaitOne();
            }
            finally
            {
#if CLR2COMPATIBILITY
                taskRunnerFinished.Close();
#else
                taskRunnerFinished.Dispose();
#endif
                taskRunnerFinished = null;
            }

            if (exceptionFromExecution != null)
            {
                // Unfortunately this will reset the callstack
                throw exceptionFromExecution;
            }

            return(taskResult);
        }
        /// <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();
                }
            }
        }