/// <summary>
        /// Initializes a configuration from a BuildRequestData structure.  Used by the BuildManager.
        /// Figures out the correct tools version to use, falling back to the provided default if necessary.
        /// May throw InvalidProjectFileException.
        /// </summary>
        /// <param name="configId">The configuration ID to assign to this new configuration.</param>
        /// <param name="data">The data containing the configuration information.</param>
        /// <param name="defaultToolsVersion">The default ToolsVersion to use as a fallback</param>
        /// <param name="getToolset">Callback used to get a Toolset based on a ToolsVersion</param>
        internal BuildRequestConfiguration(int configId, BuildRequestData data, string defaultToolsVersion, Internal.Utilities.GetToolset getToolset = null)
        {
            ErrorUtilities.VerifyThrowArgumentNull(data, "data");
            ErrorUtilities.VerifyThrowInternalLength(data.ProjectFullPath, "data.ProjectFullPath");

            _configId        = configId;
            _projectFullPath = data.ProjectFullPath;
            _explicitToolsVersionSpecified = data.ExplicitToolsVersionSpecified;
            _toolsVersion     = ResolveToolsVersion(data, defaultToolsVersion, getToolset);
            _globalProperties = data.GlobalPropertiesDictionary;
            TargetNames       = new List <string>(data.TargetNames);

            // The following information only exists when the request is populated with an existing project.
            if (data.ProjectInstance != null)
            {
                _project = data.ProjectInstance;
                _projectInitialTargets = data.ProjectInstance.InitialTargets;
                _projectDefaultTargets = data.ProjectInstance.DefaultTargets;
                _translateEntireProjectInstanceState = data.ProjectInstance.TranslateEntireState;

                if (data.PropertiesToTransfer != null)
                {
                    _transferredProperties = new List <ProjectPropertyInstance>();
                    foreach (var name in data.PropertiesToTransfer)
                    {
                        _transferredProperties.Add(data.ProjectInstance.GetProperty(name));
                    }
                }

                this.IsCacheable = false;
            }
            else
            {
                this.IsCacheable = true;
            }
        }
        /// <summary>
        /// Determines what the real tools version is.
        /// </summary>
        private string ResolveToolsVersion(BuildRequestData data, string defaultToolsVersion, Internal.Utilities.GetToolset getToolset)
        {
            if (data.ExplicitToolsVersionSpecified)
            {
                return(data.ExplicitlySpecifiedToolsVersion);
            }

            // None was specified by the call, fall back to the project's ToolsVersion attribute
            if (data.ProjectInstance != null)
            {
                return(data.ProjectInstance.Toolset.ToolsVersion);
            }
            else if (FileUtilities.IsVCProjFilename(data.ProjectFullPath))
            {
                ProjectFileErrorUtilities.ThrowInvalidProjectFile(new BuildEventFileInfo(data.ProjectFullPath), "ProjectUpgradeNeededToVcxProj", data.ProjectFullPath);
            }
            else if (!FileUtilities.IsSolutionFilename(data.ProjectFullPath))
            {
                // If the file does not exist, it's a failure of the host, possibly msbuild.exe; so it's an ArgumentException here
                ErrorUtilities.VerifyThrowArgument(File.Exists(data.ProjectFullPath), "ProjectFileNotFound", data.ProjectFullPath);

                string toolsVersionFromFile = null;

                // We use an XmlTextReader to sniff, rather than simply loading a ProjectRootElement into the cache, because
                // quite likely this won't be the node on which the request will be built, so we'd be loading the ProjectRootElement
                // on this node unnecessarily.
                toolsVersionFromFile = XmlUtilities.SniffAttributeValueFromXmlFile(ProjectFullPath, XMakeAttributes.project, XMakeAttributes.toolsVersion);

                // Instead of just using the ToolsVersion from the file, though, ask our "source of truth" what the ToolsVersion
                // we should use is.  This takes into account the various environment variables that can affect ToolsVersion, etc.,
                // to make it more likely that the ToolsVersion we come up with is going to be the one actually being used by the
                // project at build time.
                string toolsVersionToUse = Utilities.GenerateToolsVersionToUse
                                           (
                    data.ExplicitlySpecifiedToolsVersion,
                    toolsVersionFromFile,
                    getToolset,
                    defaultToolsVersion
                                           );

                return(toolsVersionToUse);
            }

            // Couldn't find out the right ToolsVersion any other way, so just return the default.
            return(defaultToolsVersion);
        }
 /// <summary>
 /// Initializes a configuration from a BuildRequestData structure.  Used by the BuildManager.
 /// Figures out the correct tools version to use, falling back to the provided default if necessary.
 /// May throw InvalidProjectFileException.
 /// </summary>
 /// <param name="data">The data containing the configuration information.</param>
 /// <param name="defaultToolsVersion">The default ToolsVersion to use as a fallback</param>
 /// <param name="getToolset">Callback used to get a Toolset based on a ToolsVersion</param>
 internal BuildRequestConfiguration(BuildRequestData data, string defaultToolsVersion, Internal.Utilities.GetToolset getToolset = null)
     : this(0, data, defaultToolsVersion, getToolset)
 {
 }