private void ReadEachToolset ( Dictionary <string, Toolset> toolsets, PropertyDictionary <ProjectPropertyInstance> globalProperties, PropertyDictionary <ProjectPropertyInstance> initialProperties, bool accumulateProperties ) { foreach (ToolsetPropertyDefinition toolsVersion in ToolsVersions) { // If there's already an existing toolset, it's of higher precedence, so // don't even bother to read this toolset in. if (!toolsets.ContainsKey(toolsVersion.Name)) { // We clone here because we don't want to interfere with the evaluation // of subsequent Toolsets; otherwise, properties found during the evaluation // of this Toolset would be persisted in initialProperties and appear // to later Toolsets as Global or Environment properties from the Engine. PropertyDictionary <ProjectPropertyInstance> initialPropertiesClone = new PropertyDictionary <ProjectPropertyInstance>(initialProperties); Toolset toolset = ReadToolset(toolsVersion, globalProperties, initialPropertiesClone, accumulateProperties); // Register toolset paths into list of immutable directories // example: C:\Windows\Microsoft.NET\Framework\v4.0.30319\ FileClassifier.Shared.RegisterImmutableDirectory(initialPropertiesClone.GetProperty("MSBuildFrameworkToolsPath32")?.EvaluatedValue?.Trim()); // example: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\ FileClassifier.Shared.RegisterImmutableDirectory(initialPropertiesClone.GetProperty("MSBuildFrameworkToolsPath64")?.EvaluatedValue?.Trim()); if (toolset != null) { toolsets[toolset.ToolsVersion] = toolset; } } } }
// for 'default' tasks. BuildTaskDatabase (Toolset toolset) { ProjectRootElement root; using (var xml = XmlReader.Create (Path.Combine (toolset.ToolsPath, default_tasks_file))) root = ProjectRootElement.Create (xml); LoadUsingTasks (null, root.UsingTasks); }
/// <summary> /// Reads all the toolsets and populates the given ToolsetCollection with them /// </summary> private void ReadEachToolset ( Dictionary <string, Toolset> toolsets, PropertyDictionary <ProjectPropertyInstance> globalProperties, PropertyDictionary <ProjectPropertyInstance> initialProperties, bool accumulateProperties ) { foreach (ToolsetPropertyDefinition toolsVersion in ToolsVersions) { // If there's already an existing toolset, it's of higher precedence, so // don't even bother to read this toolset in. if (!toolsets.ContainsKey(toolsVersion.Name)) { // We clone here because we don't want to interfere with the evaluation // of subsequent Toolsets; otherwise, properties found during the evaluation // of this Toolset would be persisted in initialProperties and appear // to later Toolsets as Global or Environment properties from the Engine. PropertyDictionary <ProjectPropertyInstance> initialPropertiesClone = new PropertyDictionary <ProjectPropertyInstance>(initialProperties); Toolset toolset = ReadToolset(toolsVersion, globalProperties, initialPropertiesClone, accumulateProperties); if (toolset != null) { toolsets[toolset.ToolsVersion] = toolset; } } } }
public void Regress27993_TrailingSlashTrimmedFromMSBuildToolsPath() { Toolset t; t = new Toolset("x", "C:", new ProjectCollection(), null); Assert.Equal(@"C:", t.ToolsPath); t = new Toolset("x", @"C:\", new ProjectCollection(), null); Assert.Equal(@"C:\", t.ToolsPath); t = new Toolset("x", @"C:\\", new ProjectCollection(), null); Assert.Equal(@"C:\", t.ToolsPath); t = new Toolset("x", @"C:\foo", new ProjectCollection(), null); Assert.Equal(@"C:\foo", t.ToolsPath); t = new Toolset("x", @"C:\foo\", new ProjectCollection(), null); Assert.Equal(@"C:\foo", t.ToolsPath); t = new Toolset("x", @"C:\foo\\", new ProjectCollection(), null); Assert.Equal(@"C:\foo\", t.ToolsPath); // trim at most one slash t = new Toolset("x", @"\\foo\share", new ProjectCollection(), null); Assert.Equal(@"\\foo\share", t.ToolsPath); t = new Toolset("x", @"\\foo\share\", new ProjectCollection(), null); Assert.Equal(@"\\foo\share", t.ToolsPath); t = new Toolset("x", @"\\foo\share\\", new ProjectCollection(), null); Assert.Equal(@"\\foo\share\", t.ToolsPath); // trim at most one slash }
public void ToolsetCtorErrors3() { Assert.Throws<ArgumentException>(() => { Toolset t = new Toolset(String.Empty, "x", new ProjectCollection(), null); } ); }
public void ToolsetCtorErrors2() { Assert.Throws<ArgumentNullException>(() => { Toolset t = new Toolset("x", null, new ProjectCollection(), null); } ); }
public static BuildTaskDatabase GetDefaultTaskDatabase (Toolset toolset) { if (toolset == null) throw new ArgumentNullException ("toolset"); BuildTaskDatabase defaults; if (!default_factory.TryGetValue (toolset.ToolsVersion, out defaults)) { defaults = new BuildTaskDatabase (toolset); } return defaults; }
public void Constructor () { var ts = new Toolset ("4.3", "c:\\", ProjectCollection.GlobalProjectCollection, null); Assert.IsNotNull (ts.Properties, "#1"); Assert.AreEqual (0, ts.Properties.Count, "#2"); Assert.IsNull (ts.DefaultSubToolsetVersion, "#3"); Assert.IsNotNull (ts.SubToolsets, "#4"); Assert.AreEqual (0, ts.SubToolsets.Count, "#5"); Assert.AreEqual ("c:\\", ts.ToolsPath, "#6"); Assert.AreEqual ("4.3", ts.ToolsVersion, "#7"); }
public void OverrideTaskPathIsRelative() { //Note Engine's BinPath is distinct from the ToolsVersion's ToolsPath ProjectCollection e = new ProjectCollection(); Toolset t = new Toolset("toolsversionname", "c:\\directory1\\directory2", new PropertyDictionary<ProjectPropertyInstance>(), new ProjectCollection(), new DirectoryGetFiles(this.getFiles), new LoadXmlFromPath(this.loadXmlFromPath), "msbuildoverridetasks", new DirectoryExists(this.directoryExists)); MockLogger mockLogger = new MockLogger(); LoggingService service = (LoggingService)LoggingService.CreateLoggingService(LoggerMode.Synchronous, 1); service.RegisterLogger(mockLogger); TaskRegistry taskoverrideRegistry = (TaskRegistry)t.GetOverrideTaskRegistry(service, new BuildEventContext(1, 2, BuildEventContext.InvalidProjectContextId, 4), e.ProjectRootElementCache); Assert.IsNotNull(taskoverrideRegistry); Assert.IsTrue(taskoverrideRegistry.TaskRegistrations.Count == 0); string rootedPathMessage = ResourceUtilities.FormatResourceString("OverrideTaskNotRootedPath", "msbuildoverridetasks"); mockLogger.AssertLogContains(ResourceUtilities.FormatResourceString("OverrideTasksFileFailure", rootedPathMessage)); }
// seealso http://msdn.microsoft.com/en-us/library/ms164309.aspx IEnumerable <T> GetReservedProperties <T> (Toolset toolset, ProjectRootElement project, Func <string, Func <string>, T> create, Func <string> projectFullPath) { yield return(create("MSBuildBinPath", () => toolset.ToolsPath)); // FIXME: add MSBuildLastTaskResult // FIXME: add MSBuildNodeCount // FIXME: add MSBuildProgramFiles32 yield return(create("MSBuildProjectDefaultTargets", () => project.DefaultTargets)); yield return(create("MSBuildProjectDirectory", () => project.DirectoryPath + Path.DirectorySeparatorChar)); yield return(create("MSBuildProjectDirectoryNoRoot", () => project.DirectoryPath.Substring(Path.GetPathRoot(project.DirectoryPath).Length))); yield return(create("MSBuildProjectExtension", () => Path.GetExtension(project.FullPath))); yield return(create("MSBuildProjectFile", () => Path.GetFileName(project.FullPath))); yield return(create("MSBuildProjectFullPath", () => project.FullPath)); yield return(create("MSBuildProjectName", () => Path.GetFileNameWithoutExtension(project.FullPath))); yield return(create("MSBuildStartupDirectory", () => BuildStartupDirectory)); yield return(create("MSBuildThisFile", () => Path.GetFileName(GetEvaluationTimeThisFile(projectFullPath)))); yield return(create("MSBuildThisFileFullPath", () => GetEvaluationTimeThisFile(projectFullPath))); yield return(create("MSBuildThisFileName", () => Path.GetFileNameWithoutExtension(GetEvaluationTimeThisFile(projectFullPath)))); yield return(create("MSBuildThisFileExtension", () => Path.GetExtension(GetEvaluationTimeThisFile(projectFullPath)))); yield return(create("MSBuildThisFileDirectory", () => Path.GetDirectoryName(GetEvaluationTimeThisFileDirectory(projectFullPath)))); yield return(create("MSBuildThisFileDirectoryNoRoot", () => { string dir = GetEvaluationTimeThisFileDirectory(projectFullPath) + Path.DirectorySeparatorChar; return dir.Substring(Path.GetPathRoot(dir).Length); })); yield return(create("MSBuildToolsPath", () => toolset.ToolsPath)); yield return(create("MSBuildToolsVersion", () => toolset.ToolsVersion)); // This is an implementation specific special property for this Microsoft.Build.dll to differentiate // the build from Microsoft.Build.Engine.dll. It is significantly used in some *.targets file we share // between old and new build engine. yield return(create("MonoUseMicrosoftBuildDll", () => "True")); }
// seealso http://msdn.microsoft.com/en-us/library/ms164309.aspx IEnumerable <T> GetReservedProperties <T> (Toolset toolset, ProjectRootElement project, Func <string, Func <string>, T> create, Func <string> projectFullPath) { yield return(create("MSBuildBinPath", () => toolset.ToolsPath)); // FIXME: add MSBuildLastTaskResult // FIXME: add MSBuildNodeCount // FIXME: add MSBuildProgramFiles32 yield return(create("MSBuildProjectDefaultTargets", () => project.DefaultTargets)); yield return(create("MSBuildProjectDirectory", () => project.DirectoryPath + Path.DirectorySeparatorChar)); yield return(create("MSBuildProjectDirectoryNoRoot", () => project.DirectoryPath.Substring(Path.GetPathRoot(project.DirectoryPath).Length))); yield return(create("MSBuildProjectExtension", () => Path.GetExtension(project.FullPath))); yield return(create("MSBuildProjectFile", () => Path.GetFileName(project.FullPath))); yield return(create("MSBuildProjectFullPath", () => project.FullPath)); yield return(create("MSBuildProjectName", () => Path.GetFileNameWithoutExtension(project.FullPath))); yield return(create("MSBuildStartupDirectory", () => BuildStartupDirectory)); yield return(create("MSBuildThisFile", () => Path.GetFileName(GetEvaluationTimeThisFile(projectFullPath)))); yield return(create("MSBuildThisFileFullPath", () => GetEvaluationTimeThisFile(projectFullPath))); yield return(create("MSBuildThisFileName", () => Path.GetFileNameWithoutExtension(GetEvaluationTimeThisFile(projectFullPath)))); yield return(create("MSBuildThisFileExtension", () => Path.GetExtension(GetEvaluationTimeThisFile(projectFullPath)))); yield return(create("MSBuildThisFileDirectory", () => Path.GetDirectoryName(GetEvaluationTimeThisFileDirectory(projectFullPath)))); yield return(create("MSBuildThisFileDirectoryNoRoot", () => { string dir = GetEvaluationTimeThisFileDirectory(projectFullPath) + Path.DirectorySeparatorChar; return dir.Substring(Path.GetPathRoot(dir).Length); })); yield return(create("MSBuildToolsPath", () => toolset.ToolsPath)); yield return(create("MSBuildToolsVersion", () => toolset.ToolsVersion)); }
public void OverrideTasksAreFoundInOverridePath() { //Note Engine's BinPath is distinct from the ToolsVersion's ToolsPath ProjectCollection e = new ProjectCollection(); Toolset t = new Toolset("toolsversionname", "c:\\directory1\\directory2", new PropertyDictionary<ProjectPropertyInstance>(), new ProjectCollection(), new DirectoryGetFiles(this.getFiles), new LoadXmlFromPath(this.loadXmlFromPath), "c:\\msbuildoverridetasks", new DirectoryExists(this.directoryExists)); LoggingService service = (LoggingService)LoggingService.CreateLoggingService(LoggerMode.Synchronous, 1); TaskRegistry taskRegistry = (TaskRegistry)t.GetTaskRegistry(service, new BuildEventContext(1, 2, BuildEventContext.InvalidProjectContextId, 4), e.ProjectRootElementCache); TaskRegistry taskoverrideRegistry = (TaskRegistry)t.GetOverrideTaskRegistry(service, new BuildEventContext(1, 2, BuildEventContext.InvalidProjectContextId, 4), e.ProjectRootElementCache); string[] expectedRegisteredTasks = { "a1", "a2", "a3", "a4", "b1", "e1", "g1", "g2", "g3" }; string[] expectedOverrideTasks = { "a1" /* special because it is in the override tasks file as well as in the tasks file*/, "oa1", "oa2", "og1", "ooo" }; string[] unexpectedRegisteredTasks = { "c1", "d1", "f1", "11", "12", "13", "21", "oa1", "oa2", "og1", "ooo" }; string[] unexpectedOverrideRegisteredTasks = { "c1", "d1", "f1", "11", "12", "13", "21", "a2", "a3", "a4", "b1", "e1", "g1", "g2", "g3" }; foreach (string expectedRegisteredTask in expectedRegisteredTasks) { Assert.IsTrue(taskRegistry.TaskRegistrations.ContainsKey(new TaskRegistry.RegisteredTaskIdentity(expectedRegisteredTask, null)), String.Format("Expected task '{0}' registered!", expectedRegisteredTask)); } foreach (string expectedRegisteredTask in expectedOverrideTasks) { Assert.IsTrue(taskoverrideRegistry.TaskRegistrations.ContainsKey(new TaskRegistry.RegisteredTaskIdentity(expectedRegisteredTask, null)), String.Format("Expected task '{0}' registered!", expectedRegisteredTask)); } foreach (string unexpectedRegisteredTask in unexpectedRegisteredTasks) { Assert.IsFalse(taskRegistry.TaskRegistrations.ContainsKey(new TaskRegistry.RegisteredTaskIdentity(unexpectedRegisteredTask, null)), String.Format("Unexpected task '{0}' registered!", unexpectedRegisteredTask)); } foreach (string unexpectedRegisteredTask in unexpectedOverrideRegisteredTasks) { Assert.IsFalse(taskoverrideRegistry.TaskRegistrations.ContainsKey(new TaskRegistry.RegisteredTaskIdentity(unexpectedRegisteredTask, null)), String.Format("Unexpected task '{0}' registered!", unexpectedRegisteredTask)); } }
public void DefaultTasksAreFoundInToolsPath() { //Note Engine's BinPath is distinct from the ToolsVersion's ToolsPath Toolset t = new Toolset("toolsversionname", "c:\\directory1\\directory2", new PropertyDictionary<ProjectPropertyInstance>(), new ProjectCollection(), new DirectoryGetFiles(this.getFiles), new LoadXmlFromPath(this.loadXmlFromPath), null, new DirectoryExists(this.directoryExists)); TaskRegistry taskRegistry = (TaskRegistry)t.GetTaskRegistry(null, new BuildEventContext(1, 2, BuildEventContext.InvalidProjectContextId, 4), ProjectCollection.GlobalProjectCollection.ProjectRootElementCache); string[] expectedRegisteredTasks = { "a1", "a2", "a3", "a4", "b1", "e1", "g1", "g2", "g3" }; string[] unexpectedRegisteredTasks = { "c1", "d1", "f1", "11", "12", "13", "21" }; foreach (string expectedRegisteredTask in expectedRegisteredTasks) { Assert.IsTrue(taskRegistry.TaskRegistrations.ContainsKey(new TaskRegistry.RegisteredTaskIdentity(expectedRegisteredTask, null)), String.Format("Expected task '{0}' registered!", expectedRegisteredTask)); } foreach (string unexpectedRegisteredTask in unexpectedRegisteredTasks) { Assert.IsFalse(taskRegistry.TaskRegistrations.ContainsKey(new TaskRegistry.RegisteredTaskIdentity(unexpectedRegisteredTask, null)), String.Format("Unexpected task '{0}' registered!", unexpectedRegisteredTask)); } }
/// <summary> /// Gathers toolset data from the registry and configuration file, if any. /// NOTE: this method is internal for unit testing purposes only. /// </summary> internal static string ReadAllToolsets ( Dictionary<string, Toolset> toolsets, ToolsetRegistryReader registryReader, ToolsetConfigurationReader configurationReader, PropertyDictionary<ProjectPropertyInstance> environmentProperties, PropertyDictionary<ProjectPropertyInstance> globalProperties, ToolsetDefinitionLocations locations ) { PropertyDictionary<ProjectPropertyInstance> initialProperties = new PropertyDictionary<ProjectPropertyInstance>(environmentProperties); initialProperties.ImportProperties(globalProperties); // The ordering here is important because the configuration file should have greater precedence // than the registry, and we do a check and don't read in the new toolset if there's already one. string defaultToolsVersionFromConfiguration = null; string overrideTasksPathFromConfiguration = null; string defaultOverrideToolsVersionFromConfiguration = null; if ((locations & ToolsetDefinitionLocations.ConfigurationFile) == ToolsetDefinitionLocations.ConfigurationFile) { if (configurationReader == null && ToolsetConfigurationReaderHelpers.ConfigurationFileMayHaveToolsets()) { // We haven't been passed in a fake configuration reader by a unit test, // and it looks like we have a .config file to read, so create a real // configuration reader configurationReader = new ToolsetConfigurationReader(environmentProperties, globalProperties); } if (configurationReader != null) { // Accumulation of properties is okay in the config file because it's deterministically ordered defaultToolsVersionFromConfiguration = configurationReader.ReadToolsets(toolsets, globalProperties, initialProperties, true /* accumulate properties */, out overrideTasksPathFromConfiguration, out defaultOverrideToolsVersionFromConfiguration); } } string defaultToolsVersionFromRegistry = null; string overrideTasksPathFromRegistry = null; string defaultOverrideToolsVersionFromRegistry = null; if ((locations & ToolsetDefinitionLocations.Registry) == ToolsetDefinitionLocations.Registry) { // If we haven't been provided a registry reader (i.e. unit tests), create one registryReader = registryReader ?? new ToolsetRegistryReader(environmentProperties, globalProperties); // We do not accumulate properties when reading them from the registry, because the order // in which values are returned to us is essentially random: so we disallow one property // in the registry to refer to another also in the registry defaultToolsVersionFromRegistry = registryReader.ReadToolsets(toolsets, globalProperties, initialProperties, false /* do not accumulate properties */, out overrideTasksPathFromRegistry, out defaultOverrideToolsVersionFromRegistry); } // The 2.0 .NET Framework installer did not write a ToolsVersion key for itself in the registry. // The 3.5 installer writes one for 2.0, but 3.5 might not be installed. // The 4.0 and subsequent installers can't keep writing the 2.0 one, because (a) it causes SxS issues and (b) we // don't want it unless 2.0 is installed. // So if the 2.0 framework is actually installed, we're reading the registry, and either the registry or the config // file have not already created the 2.0 toolset, mock up a fake one. if ( ((locations & ToolsetDefinitionLocations.Registry) != 0) && !toolsets.ContainsKey("2.0") && FrameworkLocationHelper.PathToDotNetFrameworkV20 != null ) { Toolset synthetic20Toolset = new Toolset("2.0", FrameworkLocationHelper.PathToDotNetFrameworkV20, environmentProperties, globalProperties, null /* 2.0 did not have override tasks */, null /* 2.0 did not have a default override toolsversion */); toolsets.Add("2.0", synthetic20Toolset); } // We'll use the path from the configuration file if it was specified, otherwise we'll try // the one from the registry. It's possible (and valid) that neither the configuration file // nor the registry specify a override in which case we'll just return null. string overrideTasksPath = overrideTasksPathFromConfiguration ?? overrideTasksPathFromRegistry; // We'll use the path from the configuration file if it was specified, otherwise we'll try // the one from the registry. It's possible (and valid) that neither the configuration file // nor the registry specify a override in which case we'll just return null. string defaultOverrideToolsVersion = defaultOverrideToolsVersionFromConfiguration ?? defaultOverrideToolsVersionFromRegistry; // We'll use the default from the configuration file if it was specified, otherwise we'll try // the one from the registry. It's possible (and valid) that neither the configuration file // nor the registry specify a default, in which case we'll just return null. string defaultToolsVersion = defaultToolsVersionFromConfiguration ?? defaultToolsVersionFromRegistry; // If we got a default version from the registry or config file, and it // actually exists, fine. // Otherwise we have to come up with one. if (defaultToolsVersion == null || !toolsets.ContainsKey(defaultToolsVersion)) { // We're going to choose a hard coded default tools version of 2.0. defaultToolsVersion = Constants.defaultToolsVersion; // But don't overwrite any existing tools path for this default we're choosing. if (!toolsets.ContainsKey(Constants.defaultToolsVersion)) { // There's no tools path already for 2.0, so use the path to the v2.0 .NET Framework. // If an old-fashioned caller sets BinPath property, or passed a BinPath to the constructor, // that will overwrite what we're setting here. ErrorUtilities.VerifyThrow(Constants.defaultToolsVersion == "2.0", "Getting 2.0 FX path so default should be 2.0"); string pathToFramework = FrameworkLocationHelper.PathToDotNetFrameworkV20; // We could not find the default toolsversion because it was not installed on the machine. Fallback to the // one we expect to always be there when running msbuild 4.0. if (pathToFramework == null) { pathToFramework = FrameworkLocationHelper.PathToDotNetFrameworkV40; defaultToolsVersion = Constants.defaultFallbackToolsVersion; } // Again don't overwrite any existing tools path for this default we're choosing. if (!toolsets.ContainsKey(defaultToolsVersion)) { Toolset defaultToolset = new Toolset(defaultToolsVersion, pathToFramework, environmentProperties, globalProperties, overrideTasksPath, defaultOverrideToolsVersion); toolsets.Add(defaultToolsVersion, defaultToolset); } } } return defaultToolsVersion; }
/// <summary> /// Gathers toolset data from the registry and configuration file, if any. /// NOTE: this method is internal for unit testing purposes only. /// </summary> internal static string ReadAllToolsets ( Dictionary <string, Toolset> toolsets, ToolsetRegistryReader registryReader, ToolsetConfigurationReader configurationReader, PropertyDictionary <ProjectPropertyInstance> environmentProperties, PropertyDictionary <ProjectPropertyInstance> globalProperties, ToolsetDefinitionLocations locations ) { PropertyDictionary <ProjectPropertyInstance> initialProperties = new PropertyDictionary <ProjectPropertyInstance>(environmentProperties); initialProperties.ImportProperties(globalProperties); // The ordering here is important because the configuration file should have greater precedence // than the registry, and we do a check and don't read in the new toolset if there's already one. string defaultToolsVersionFromConfiguration = null; string overrideTasksPathFromConfiguration = null; string defaultOverrideToolsVersionFromConfiguration = null; if ((locations & ToolsetDefinitionLocations.ConfigurationFile) == ToolsetDefinitionLocations.ConfigurationFile) { if (configurationReader == null && ToolsetConfigurationReaderHelpers.ConfigurationFileMayHaveToolsets()) { // We haven't been passed in a fake configuration reader by a unit test, // and it looks like we have a .config file to read, so create a real // configuration reader configurationReader = new ToolsetConfigurationReader(environmentProperties, globalProperties); } if (configurationReader != null) { // Accumulation of properties is okay in the config file because it's deterministically ordered defaultToolsVersionFromConfiguration = configurationReader.ReadToolsets(toolsets, globalProperties, initialProperties, true /* accumulate properties */, out overrideTasksPathFromConfiguration, out defaultOverrideToolsVersionFromConfiguration); } } string defaultToolsVersionFromRegistry = null; string overrideTasksPathFromRegistry = null; string defaultOverrideToolsVersionFromRegistry = null; if ((locations & ToolsetDefinitionLocations.Registry) == ToolsetDefinitionLocations.Registry) { // If we haven't been provided a registry reader (i.e. unit tests), create one registryReader = registryReader ?? new ToolsetRegistryReader(environmentProperties, globalProperties); // We do not accumulate properties when reading them from the registry, because the order // in which values are returned to us is essentially random: so we disallow one property // in the registry to refer to another also in the registry defaultToolsVersionFromRegistry = registryReader.ReadToolsets(toolsets, globalProperties, initialProperties, false /* do not accumulate properties */, out overrideTasksPathFromRegistry, out defaultOverrideToolsVersionFromRegistry); } // The 2.0 .NET Framework installer did not write a ToolsVersion key for itself in the registry. // The 3.5 installer writes one for 2.0, but 3.5 might not be installed. // The 4.0 and subsequent installers can't keep writing the 2.0 one, because (a) it causes SxS issues and (b) we // don't want it unless 2.0 is installed. // So if the 2.0 framework is actually installed, we're reading the registry, and either the registry or the config // file have not already created the 2.0 toolset, mock up a fake one. if ( ((locations & ToolsetDefinitionLocations.Registry) != 0) && !toolsets.ContainsKey("2.0") && FrameworkLocationHelper.PathToDotNetFrameworkV20 != null ) { Toolset synthetic20Toolset = new Toolset("2.0", FrameworkLocationHelper.PathToDotNetFrameworkV20, environmentProperties, globalProperties, null /* 2.0 did not have override tasks */, null /* 2.0 did not have a default override toolsversion */); toolsets.Add("2.0", synthetic20Toolset); } // We'll use the path from the configuration file if it was specified, otherwise we'll try // the one from the registry. It's possible (and valid) that neither the configuration file // nor the registry specify a override in which case we'll just return null. string overrideTasksPath = overrideTasksPathFromConfiguration ?? overrideTasksPathFromRegistry; // We'll use the path from the configuration file if it was specified, otherwise we'll try // the one from the registry. It's possible (and valid) that neither the configuration file // nor the registry specify a override in which case we'll just return null. string defaultOverrideToolsVersion = defaultOverrideToolsVersionFromConfiguration ?? defaultOverrideToolsVersionFromRegistry; // We'll use the default from the configuration file if it was specified, otherwise we'll try // the one from the registry. It's possible (and valid) that neither the configuration file // nor the registry specify a default, in which case we'll just return null. string defaultToolsVersion = defaultToolsVersionFromConfiguration ?? defaultToolsVersionFromRegistry; // If we got a default version from the registry or config file, and it // actually exists, fine. // Otherwise we have to come up with one. if (defaultToolsVersion == null || !toolsets.ContainsKey(defaultToolsVersion)) { // We're going to choose a hard coded default tools version of 2.0. defaultToolsVersion = Constants.defaultToolsVersion; // But don't overwrite any existing tools path for this default we're choosing. if (!toolsets.ContainsKey(Constants.defaultToolsVersion)) { // There's no tools path already for 2.0, so use the path to the v2.0 .NET Framework. // If an old-fashioned caller sets BinPath property, or passed a BinPath to the constructor, // that will overwrite what we're setting here. ErrorUtilities.VerifyThrow(Constants.defaultToolsVersion == "2.0", "Getting 2.0 FX path so default should be 2.0"); string pathToFramework = FrameworkLocationHelper.PathToDotNetFrameworkV20; // We could not find the default toolsversion because it was not installed on the machine. Fallback to the // one we expect to always be there when running msbuild 4.0. if (pathToFramework == null) { pathToFramework = FrameworkLocationHelper.PathToDotNetFrameworkV40; defaultToolsVersion = Constants.defaultFallbackToolsVersion; } // Again don't overwrite any existing tools path for this default we're choosing. if (!toolsets.ContainsKey(defaultToolsVersion)) { Toolset defaultToolset = new Toolset(defaultToolsVersion, pathToFramework, environmentProperties, globalProperties, overrideTasksPath, defaultOverrideToolsVersion); toolsets.Add(defaultToolsVersion, defaultToolset); } } } return(defaultToolsVersion); }
public void OverrideTaskPathHasInvalidChars() { ProjectCollection e = new ProjectCollection(); Toolset t = new Toolset("toolsversionname", "c:\\directory1\\directory2", new PropertyDictionary<ProjectPropertyInstance>(), new ProjectCollection(), new DirectoryGetFiles(this.getFiles), new LoadXmlFromPath(this.loadXmlFromPath), "k:\\||^%$#*msbuildoverridetasks", new DirectoryExists(this.directoryExists)); MockLogger mockLogger = new MockLogger(); LoggingService service = (LoggingService)LoggingService.CreateLoggingService(LoggerMode.Synchronous, 1); service.RegisterLogger(mockLogger); TaskRegistry taskoverrideRegistry = (TaskRegistry)t.GetOverrideTaskRegistry(service, new BuildEventContext(1, 2, BuildEventContext.InvalidProjectContextId, 4), e.ProjectRootElementCache); Assert.IsNotNull(taskoverrideRegistry); Assert.IsTrue(taskoverrideRegistry.TaskRegistrations.Count == 0); mockLogger.AssertLogContains("MSB4194"); }
/// <summary> /// Creates a standard ProjectCollection and adds a fake toolset with the following contents to it: /// /// ToolsVersion = Fake /// Base Properties: /// a = a1 /// b = b1 /// /// SubToolset "12.0": /// d = d4 /// e = e5 /// /// SubToolset "v11.0": /// b = b2 /// c = c2 /// /// SubToolset "FakeSubToolset": /// a = a3 /// c = c3 /// /// SubToolset "v13.0": /// f = f6 /// g = g7 /// </summary> private Toolset GetFakeToolset(IDictionary<string, string> globalPropertiesForProjectCollection) { ProjectCollection projectCollection = new ProjectCollection(globalPropertiesForProjectCollection); IDictionary<string, string> properties = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); properties.Add("a", "a1"); properties.Add("b", "b1"); Dictionary<string, SubToolset> subToolsets = new Dictionary<string, SubToolset>(StringComparer.OrdinalIgnoreCase); // SubToolset 12.0 properties PropertyDictionary<ProjectPropertyInstance> subToolset12Properties = new PropertyDictionary<ProjectPropertyInstance>(); subToolset12Properties.Set(ProjectPropertyInstance.Create("d", "d4")); subToolset12Properties.Set(ProjectPropertyInstance.Create("e", "e5")); // SubToolset v11.0 properties PropertyDictionary<ProjectPropertyInstance> subToolset11Properties = new PropertyDictionary<ProjectPropertyInstance>(); subToolset11Properties.Set(ProjectPropertyInstance.Create("b", "b2")); subToolset11Properties.Set(ProjectPropertyInstance.Create("c", "c2")); // FakeSubToolset properties PropertyDictionary<ProjectPropertyInstance> fakeSubToolsetProperties = new PropertyDictionary<ProjectPropertyInstance>(); fakeSubToolsetProperties.Set(ProjectPropertyInstance.Create("a", "a3")); fakeSubToolsetProperties.Set(ProjectPropertyInstance.Create("c", "c3")); // SubToolset v13.0 properties PropertyDictionary<ProjectPropertyInstance> subToolset13Properties = new PropertyDictionary<ProjectPropertyInstance>(); subToolset13Properties.Set(ProjectPropertyInstance.Create("f", "f6")); subToolset13Properties.Set(ProjectPropertyInstance.Create("g", "g7")); subToolsets.Add("12.0", new SubToolset("12.0", subToolset12Properties)); subToolsets.Add("v11.0", new SubToolset("v11.0", subToolset11Properties)); subToolsets.Add("FakeSubToolset", new SubToolset("FakeSubToolset", fakeSubToolsetProperties)); subToolsets.Add("v13.0", new SubToolset("v13.0", subToolset13Properties)); Toolset parentToolset = projectCollection.GetToolset("4.0"); Toolset fakeToolset = new Toolset("Fake", parentToolset.ToolsPath, properties, projectCollection, subToolsets, parentToolset.OverrideTasksPath); projectCollection.AddToolset(fakeToolset); return fakeToolset; }
public void ToolsetCtorErrors3() { Toolset t = new Toolset(String.Empty, "x", new ProjectCollection(), null); }
public void TestGenerateSubToolsetVersion_ExplicitlyPassedGlobalPropertyWins() { string originalVisualStudioVersion = Environment.GetEnvironmentVariable("VisualStudioVersion"); try { Environment.SetEnvironmentVariable("VisualStudioVersion", ObjectModelHelpers.CurrentVisualStudioVersion); IDictionary<string, string> globalProperties = new Dictionary<string, string>(); globalProperties.Add("VisualStudioVersion", "v13.0"); ProjectCollection projectCollection = new ProjectCollection(globalProperties); Toolset parentToolset = projectCollection.GetToolset("4.0"); Toolset t = new Toolset("Fake", parentToolset.ToolsPath, null, projectCollection, null, parentToolset.OverrideTasksPath); IDictionary<string, string> explicitGlobalProperties = new Dictionary<string, string>(); explicitGlobalProperties.Add("VisualStudioVersion", "FakeSubToolset"); Assert.Equal("FakeSubToolset", t.GenerateSubToolsetVersion(explicitGlobalProperties, 0)); } finally { Environment.SetEnvironmentVariable("VisualStudioVersion", originalVisualStudioVersion); } }
public void TestNoSubToolset_EnvironmentOverrides() { string originalVisualStudioVersion = Environment.GetEnvironmentVariable("VisualStudioVersion"); try { Environment.SetEnvironmentVariable("VisualStudioVersion", "foo"); ProjectCollection projectCollection = new ProjectCollection(); Toolset parentToolset = projectCollection.GetToolset("4.0"); Toolset t = new Toolset("Fake", parentToolset.ToolsPath, null, projectCollection, null, parentToolset.OverrideTasksPath); Assert.Equal("foo", t.GenerateSubToolsetVersion()); } finally { Environment.SetEnvironmentVariable("VisualStudioVersion", originalVisualStudioVersion); } }
public void TestNoSubToolset_GlobalPropertyOverrides() { string originalVisualStudioVersion = Environment.GetEnvironmentVariable("VisualStudioVersion"); try { Environment.SetEnvironmentVariable("VisualStudioVersion", null); IDictionary<string, string> globalProperties = new Dictionary<string, string>(); globalProperties.Add("VisualStudioVersion", "99.0"); ProjectCollection projectCollection = new ProjectCollection(globalProperties); Toolset parentToolset = projectCollection.GetToolset("4.0"); Toolset t = new Toolset("Fake", parentToolset.ToolsPath, null, projectCollection, null, parentToolset.OverrideTasksPath); Assert.Equal("99.0", t.GenerateSubToolsetVersion()); } finally { Environment.SetEnvironmentVariable("VisualStudioVersion", originalVisualStudioVersion); } }
public void TestGenerateSubToolsetVersionWhenNoSubToolset() { string originalVisualStudioVersion = Environment.GetEnvironmentVariable("VisualStudioVersion"); try { Environment.SetEnvironmentVariable("VisualStudioVersion", null); ProjectCollection projectCollection = new ProjectCollection(); Toolset parentToolset = projectCollection.GetToolset("4.0"); Toolset t = new Toolset("Fake", parentToolset.ToolsPath, null, projectCollection, null, parentToolset.OverrideTasksPath); string subToolsetVersion = t.GenerateSubToolsetVersion(); if (Toolset.Dev10IsInstalled) { Assert.Equal(Constants.Dev10SubToolsetValue, subToolsetVersion); } else { Assert.Null(subToolsetVersion); } } finally { Environment.SetEnvironmentVariable("VisualStudioVersion", originalVisualStudioVersion); } }
public void WarningLoggedIfNoDefaultTasksFound() { //Note Engine's BinPath is distinct from the ToolsVersion's ToolsPath ProjectCollection p = new ProjectCollection(); MockLogger mockLogger = new MockLogger(); LoggingService service = (LoggingService)LoggingService.CreateLoggingService(LoggerMode.Synchronous, 1); service.RegisterLogger(mockLogger); Toolset t = new Toolset("toolsversionname", "c:\\directory1\\directory2\\doesntexist", new PropertyDictionary<ProjectPropertyInstance>(), new ProjectCollection(), new DirectoryGetFiles(this.getFiles), new LoadXmlFromPath(this.loadXmlFromPath), null, new DirectoryExists(this.directoryExists)); TaskRegistry taskRegistry = (TaskRegistry)t.GetTaskRegistry(service, BuildEventContext.Invalid, ProjectCollection.GlobalProjectCollection.ProjectRootElementCache); string[] unexpectedRegisteredTasks = { "a1", "a2", "a3", "a4", "b1", "c1", "d1", "e1", "f1", "g1", "g2", "g3", "11", "12", "13", "21" }; Assert.AreEqual(1, mockLogger.WarningCount, "Expected 1 warning logged!"); foreach (string unexpectedRegisteredTask in unexpectedRegisteredTasks) { Assert.IsFalse(taskRegistry.TaskRegistrations.ContainsKey(new TaskRegistry.RegisteredTaskIdentity(unexpectedRegisteredTask, null)), String.Format("Unexpected task '{0}' registered!", unexpectedRegisteredTask)); } }
public void InvalidToolPath() { //Note Engine's BinPath is distinct from the ToolsVersion's ToolsPath ProjectCollection p = new ProjectCollection(); MockLogger mockLogger = new MockLogger(); LoggingService service = (LoggingService)LoggingService.CreateLoggingService(LoggerMode.Synchronous, 1); service.RegisterLogger(mockLogger); Toolset t = new Toolset("toolsversionname", "invalid||path", new PropertyDictionary<ProjectPropertyInstance>(), p, new DirectoryGetFiles(this.getFiles), new LoadXmlFromPath(this.loadXmlFromPath), null, new DirectoryExists(this.directoryExists)); TaskRegistry taskRegistry = (TaskRegistry)t.GetTaskRegistry(service, BuildEventContext.Invalid, ProjectCollection.GlobalProjectCollection.ProjectRootElementCache); Console.WriteLine(mockLogger.FullLog); Assert.AreEqual(1, mockLogger.WarningCount, "Expected a warning for invalid character in toolpath"); }
/// <summary> /// Creates a toolset with the given tools version if one does not already exist. /// </summary> private static void CreateMockToolsetIfNotExists(string toolsVersion, ProjectCollection projectCollection) { ProjectCollection pc = projectCollection; if (!pc.Toolsets.Any(t => String.Equals(t.ToolsVersion, toolsVersion, StringComparison.OrdinalIgnoreCase))) { Toolset template = pc.Toolsets.First(t => String.Equals(t.ToolsVersion, pc.DefaultToolsVersion, StringComparison.OrdinalIgnoreCase)); var toolset = new Toolset( toolsVersion, template.ToolsPath, template.Properties.ToDictionary(p => p.Key, p => p.Value.EvaluatedValue), pc, null); pc.AddToolset(toolset); } }
public void CustomToolsVersionIsHonored() { Environment.SetEnvironmentVariable("MSBUILDTREATALLTOOLSVERSIONSASCURRENT", String.Empty); try { string content = @"<Project ToolsVersion=""14.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003""> <Target Name=""a""> <Message Text=""[$(MSBUILDTOOLSVERSION)]"" /> </Target> </Project> "; string projectPath = Path.GetTempFileName(); File.WriteAllText(projectPath, content); ProjectCollection p = new ProjectCollection(); MockLogger mockLogger = new MockLogger(); LoggingService service = (LoggingService)LoggingService.CreateLoggingService(LoggerMode.Synchronous, 1); service.RegisterLogger(mockLogger); Toolset source = p.GetToolset("14.0"); Toolset potato = new Toolset("potato", source.ToolsPath, ProjectCollection.GlobalProjectCollection, source.ToolsPath); p.AddToolset(potato); bool success = false; Project project = p.LoadProject(projectPath, "potato"); success = project.Build(mockLogger); Assert.IsTrue(success); mockLogger.AssertLogContains("[potato]"); } finally { // Nothing } }
internal IEnumerable <ReservedProjectProperty> GetReservedProperties(Toolset toolset, Project project) { Func <string, Func <string>, ReservedProjectProperty> create = (name, value) => new ReservedProjectProperty(project, name, value); return(GetReservedProperties <ReservedProjectProperty> (toolset, project.Xml, create, () => project.FullPath)); }
public void InlineTasksInDotTasksFile() { Toolset t = new Toolset("t", "c:\\inline", new PropertyDictionary<ProjectPropertyInstance>(), new ProjectCollection(), new DirectoryGetFiles(this.getFiles), new LoadXmlFromPath(this.loadXmlFromPath), null, new DirectoryExists(directoryExists)); TaskRegistry taskRegistry = (TaskRegistry)t.GetTaskRegistry(null, new BuildEventContext(1, 2, BuildEventContext.InvalidProjectContextId, 4), ProjectCollection.GlobalProjectCollection.ProjectRootElementCache); // Did not crash due to trying to expand items without having items }
public void ToolsetCtorErrors2() { Toolset t = new Toolset("x", null, new ProjectCollection(), null); }
/// <summary> /// Factory for deserialization. /// </summary> static internal Toolset FactoryForDeserialization(INodePacketTranslator translator) { Toolset toolset = new Toolset(translator); return toolset; }
internal static string GenerateToolsVersionToUse(string explicitToolsVersion, string toolsVersionFromProject, GetToolset getToolset, string defaultToolsVersion, out bool usingDifferentToolsVersionFromProjectFile) { string toolsVersionToUse = explicitToolsVersion; // hosts may need to treat toolsversions later than the current one as the current one ... or may just // want to treat all toolsversions as though they're the current one, so give them that ability // through an environment variable if (s_shouldTreatOtherToolsVersionsAsCurrent) { toolsVersionToUse = MSBuildConstants.CurrentToolsVersion; } else { if (s_shouldTreatHigherToolsVersionsAsCurrent) { if (Version.TryParse(toolsVersionFromProject, out var toolsVersionAsVersion)) { // This is higher than the 'legacy' toolsversion values. // Therefore we need to enter best effort mode and // present the current one. if (toolsVersionAsVersion > new Version(15, 0)) { toolsVersionToUse = MSBuildConstants.CurrentToolsVersion; } } } // If ToolsVersion has not either been explicitly set or been overridden via one of the methods // mentioned above if (toolsVersionToUse == null) { // We want to generate the ToolsVersion based on the legacy behavior if EITHER: // - the environment variable (MSBUILDLEGACYDEFAULTTOOLSVERSION) is set // - the current ToolsVersion doesn't actually exist. This is extremely unlikely // to happen normally, but may happen in checked-in toolset scenarios, in which // case we want to make sure we're at least as tolerant as Dev11 was. Toolset currentToolset = null; if (getToolset != null) { currentToolset = getToolset(MSBuildConstants.CurrentToolsVersion); } // if we want to do the legacy behavior, act as we did through Dev11: // - If project file defines a ToolsVersion that has a valid toolset associated with it, use that // - Otherwise, if project file defines an invalid ToolsVersion, use the current ToolsVersion // - Otherwise, if project file does not define a ToolsVersion, use the default ToolsVersion (must // be "2.0" since 2.0 projects did not have a ToolsVersion field). if (s_uselegacyDefaultToolsVersionBehavior || (getToolset != null && currentToolset == null)) { if (!String.IsNullOrEmpty(toolsVersionFromProject)) { toolsVersionToUse = toolsVersionFromProject; // If we can tell that the toolset specified in the project is not present // then we'll use the current version. Otherwise, we'll assume our caller // knew what it was doing. if (getToolset != null && getToolset(toolsVersionToUse) == null) { toolsVersionToUse = MSBuildConstants.CurrentToolsVersion; } } else { toolsVersionToUse = defaultToolsVersion; } } else { // Otherwise, first check to see if the default ToolsVersion has been set in the environment. // Ideally we'll check to make sure it's a valid ToolsVersion, but if we don't have the ability // to do so, we'll assume the person who set the environment variable knew what they were doing. if (!String.IsNullOrEmpty(s_defaultToolsVersionFromEnvironment)) { if (getToolset == null || getToolset(s_defaultToolsVersionFromEnvironment) != null) { toolsVersionToUse = s_defaultToolsVersionFromEnvironment; } } // Otherwise, check to see if the override default toolsversion from the toolset works. Though // it's attached to the Toolset, it's actually MSBuild version dependent, so any loaded Toolset // should have the same one. // // And if that doesn't work, then just fall back to the current ToolsVersion. if (toolsVersionToUse == null) { if (getToolset != null && currentToolset != null) { string defaultOverrideToolsVersion = currentToolset.DefaultOverrideToolsVersion; if (!String.IsNullOrEmpty(defaultOverrideToolsVersion) && getToolset(defaultOverrideToolsVersion) != null) { toolsVersionToUse = defaultOverrideToolsVersion; } else { toolsVersionToUse = MSBuildConstants.CurrentToolsVersion; } } else { toolsVersionToUse = MSBuildConstants.CurrentToolsVersion; } } } } } ErrorUtilities.VerifyThrow(!String.IsNullOrEmpty(toolsVersionToUse), "Should always return a ToolsVersion"); var explicitToolsVersionSpecified = explicitToolsVersion != null; usingDifferentToolsVersionFromProjectFile = UsingDifferentToolsVersionFromProjectFile(toolsVersionFromProject, toolsVersionToUse, explicitToolsVersionSpecified); return(toolsVersionToUse); }
public void AddToolset(Toolset toolset) { toolsets.Add(toolset); }
public void ValidateToolsetTranslation() { PropertyDictionary<ProjectPropertyInstance> buildProperties = new PropertyDictionary<ProjectPropertyInstance>(); buildProperties.Set(ProjectPropertyInstance.Create("a", "a1")); PropertyDictionary<ProjectPropertyInstance> environmentProperties = new PropertyDictionary<ProjectPropertyInstance>(); environmentProperties.Set(ProjectPropertyInstance.Create("b", "b1")); PropertyDictionary<ProjectPropertyInstance> globalProperties = new PropertyDictionary<ProjectPropertyInstance>(); globalProperties.Set(ProjectPropertyInstance.Create("c", "c1")); PropertyDictionary<ProjectPropertyInstance> subToolsetProperties = new PropertyDictionary<ProjectPropertyInstance>(); subToolsetProperties.Set(ProjectPropertyInstance.Create("d", "d1")); Dictionary<string, SubToolset> subToolsets = new Dictionary<string, SubToolset>(StringComparer.OrdinalIgnoreCase); subToolsets.Add("dogfood", new SubToolset("dogfood", subToolsetProperties)); Toolset t = new Toolset("4.0", "c:\\bar", buildProperties, environmentProperties, globalProperties, subToolsets, "c:\\foo", "4.0", new Dictionary<string, List<string>> { ["MSBuildExtensionsPath"] = new List<string> {@"c:\foo"} }); ((INodePacketTranslatable)t).Translate(TranslationHelpers.GetWriteTranslator()); Toolset t2 = Toolset.FactoryForDeserialization(TranslationHelpers.GetReadTranslator()); Assert.Equal(t.ToolsVersion, t2.ToolsVersion); Assert.Equal(t.ToolsPath, t2.ToolsPath); Assert.Equal(t.OverrideTasksPath, t2.OverrideTasksPath); Assert.Equal(t.Properties.Count, t2.Properties.Count); foreach (string key in t.Properties.Keys) { Assert.Equal(t.Properties[key].Name, t2.Properties[key].Name); Assert.Equal(t.Properties[key].EvaluatedValue, t2.Properties[key].EvaluatedValue); } Assert.Equal(t.SubToolsets.Count, t2.SubToolsets.Count); foreach (string key in t.SubToolsets.Keys) { SubToolset subToolset1 = t.SubToolsets[key]; SubToolset subToolset2 = null; if (t2.SubToolsets.TryGetValue(key, out subToolset2)) { Assert.Equal(subToolset1.SubToolsetVersion, subToolset2.SubToolsetVersion); Assert.Equal(subToolset1.Properties.Count, subToolset2.Properties.Count); foreach (string subToolsetPropertyKey in subToolset1.Properties.Keys) { Assert.Equal(subToolset1.Properties[subToolsetPropertyKey].Name, subToolset2.Properties[subToolsetPropertyKey].Name); Assert.Equal(subToolset1.Properties[subToolsetPropertyKey].EvaluatedValue, subToolset2.Properties[subToolsetPropertyKey].EvaluatedValue); } } else { Assert.True(false, $"Sub-toolset {key} was lost in translation."); } } Assert.Equal(t.DefaultOverrideToolsVersion, t2.DefaultOverrideToolsVersion); Assert.NotNull(t2.ImportPropertySearchPathsTable); Assert.Equal(1, t2.ImportPropertySearchPathsTable.Count); Assert.Equal(@"c:\foo", t2.ImportPropertySearchPathsTable["MSBuildExtensionsPath"][0]); }
internal IEnumerable <ProjectPropertyInstance> GetReservedProperties(Toolset toolset, ProjectInstance project, ProjectRootElement xml) { Func <string, Func <string>, ProjectPropertyInstance> create = (name, value) => new ProjectPropertyInstance(name, true, null, value); return(GetReservedProperties <ProjectPropertyInstance> (toolset, xml, create, () => project.FullPath)); }
public void OverrideTaskPathHasTooLongOfAPath() { string tooLong = "c:\\" + new string('C', 6000); ProjectCollection e = new ProjectCollection(); Toolset t = new Toolset("toolsversionname", "c:\\directory1\\directory2", new PropertyDictionary<ProjectPropertyInstance>(), new ProjectCollection(), new DirectoryGetFiles(this.getFiles), new LoadXmlFromPath(this.loadXmlFromPath), tooLong, new DirectoryExists(this.directoryExists)); MockLogger mockLogger = new MockLogger(); LoggingService service = (LoggingService)LoggingService.CreateLoggingService(LoggerMode.Synchronous, 1); service.RegisterLogger(mockLogger); TaskRegistry taskoverrideRegistry = (TaskRegistry)t.GetOverrideTaskRegistry(service, new BuildEventContext(1, 2, BuildEventContext.InvalidProjectContextId, 4), e.ProjectRootElementCache); Assert.NotNull(taskoverrideRegistry); Assert.Equal(0, taskoverrideRegistry.TaskRegistrations.Count); string rootedPathMessage = ResourceUtilities.FormatResourceString("OverrideTaskNotRootedPath", tooLong); mockLogger.AssertLogContains(ResourceUtilities.FormatResourceString("OverrideTasksFileFailure", rootedPathMessage)); }
/// <summary> /// Gathers toolset data from the registry and configuration file, if any. /// NOTE: this method is internal for unit testing purposes only. /// </summary> internal static string ReadAllToolsets ( Dictionary <string, Toolset> toolsets, #if FEATURE_WIN32_REGISTRY ToolsetRegistryReader registryReader, #endif #if FEATURE_SYSTEM_CONFIGURATION ToolsetConfigurationReader configurationReader, #endif PropertyDictionary <ProjectPropertyInstance> environmentProperties, PropertyDictionary <ProjectPropertyInstance> globalProperties, ToolsetDefinitionLocations locations ) { var initialProperties = new PropertyDictionary <ProjectPropertyInstance>(environmentProperties); initialProperties.ImportProperties(globalProperties); // The ordering here is important because the configuration file should have greater precedence // than the registry, and we do a check and don't read in the new toolset if there's already one. string defaultToolsVersionFromConfiguration = null; string overrideTasksPathFromConfiguration = null; string defaultOverrideToolsVersionFromConfiguration = null; #if FEATURE_SYSTEM_CONFIGURATION if ((locations & ToolsetDefinitionLocations.ConfigurationFile) == ToolsetDefinitionLocations.ConfigurationFile) { if (configurationReader == null) { configurationReader = new ToolsetConfigurationReader(environmentProperties, globalProperties); } // Accumulation of properties is okay in the config file because it's deterministically ordered defaultToolsVersionFromConfiguration = configurationReader.ReadToolsets(toolsets, globalProperties, initialProperties, true /* accumulate properties */, out overrideTasksPathFromConfiguration, out defaultOverrideToolsVersionFromConfiguration); } #endif string defaultToolsVersionFromRegistry = null; string overrideTasksPathFromRegistry = null; string defaultOverrideToolsVersionFromRegistry = null; if ((locations & ToolsetDefinitionLocations.Registry) == ToolsetDefinitionLocations.Registry) { #if FEATURE_WIN32_REGISTRY if (NativeMethodsShared.IsWindows || registryReader != null) { // If we haven't been provided a registry reader (i.e. unit tests), create one registryReader = registryReader ?? new ToolsetRegistryReader(environmentProperties, globalProperties); // We do not accumulate properties when reading them from the registry, because the order // in which values are returned to us is essentially random: so we disallow one property // in the registry to refer to another also in the registry defaultToolsVersionFromRegistry = registryReader.ReadToolsets(toolsets, globalProperties, initialProperties, false /* do not accumulate properties */, out overrideTasksPathFromRegistry, out defaultOverrideToolsVersionFromRegistry); } else #endif { var currentDir = BuildEnvironmentHelper.Instance.CurrentMSBuildToolsDirectory.TrimEnd(Path.DirectorySeparatorChar); var props = new PropertyDictionary <ProjectPropertyInstance>(); var libraryPath = NativeMethodsShared.FrameworkBasePath; if (!string.IsNullOrEmpty(libraryPath)) { // The 4.0 toolset is installed in the framework directory var v4Dir = FrameworkLocationHelper.GetPathToDotNetFrameworkV40(DotNetFrameworkArchitecture.Current); if (v4Dir != null && !toolsets.ContainsKey("4.0")) { // Create standard properties. On Mono they are well known var buildProperties = CreateStandardProperties(globalProperties, "4.0", libraryPath, v4Dir); toolsets.Add( "4.0", new Toolset( "4.0", v4Dir, buildProperties, environmentProperties, globalProperties, null, currentDir, string.Empty)); } // Other toolsets are installed in the xbuild directory var xbuildToolsetsDir = Path.Combine(libraryPath, $"xbuild{Path.DirectorySeparatorChar}"); if (FileSystems.Default.DirectoryExists(xbuildToolsetsDir)) { var r = new Regex(Regex.Escape(xbuildToolsetsDir) + @"\d+\.\d+"); foreach (var d in Directory.GetDirectories(xbuildToolsetsDir).Where(d => r.IsMatch(d))) { var version = Path.GetFileName(d); var binPath = Path.Combine(d, "bin"); if (toolsets.ContainsKey(version)) { continue; } if (NativeMethodsShared.IsMono && Version.TryParse(version, out Version parsedVersion) && parsedVersion.Major > 14) { continue; } // Create standard properties. On Mono they are well known var buildProperties = CreateStandardProperties(globalProperties, version, xbuildToolsetsDir, binPath); toolsets.Add( version, new Toolset( version, binPath, buildProperties, environmentProperties, globalProperties, null, currentDir, string.Empty)); } } } if (!toolsets.ContainsKey(MSBuildConstants.CurrentToolsVersion)) { toolsets.Add( MSBuildConstants.CurrentToolsVersion, new Toolset( MSBuildConstants.CurrentToolsVersion, currentDir, props, new PropertyDictionary <ProjectPropertyInstance>(), currentDir, string.Empty)); } } } // The 2.0 .NET Framework installer did not write a ToolsVersion key for itself in the registry. // The 3.5 installer writes one for 2.0, but 3.5 might not be installed. // The 4.0 and subsequent installers can't keep writing the 2.0 one, because (a) it causes SxS issues and (b) we // don't want it unless 2.0 is installed. // So if the 2.0 framework is actually installed, we're reading the registry, and either the registry or the config // file have not already created the 2.0 toolset, mock up a fake one. if (((locations & ToolsetDefinitionLocations.Registry) != 0) && !toolsets.ContainsKey("2.0") && FrameworkLocationHelper.PathToDotNetFrameworkV20 != null) { var synthetic20Toolset = new Toolset( "2.0", FrameworkLocationHelper.PathToDotNetFrameworkV20, environmentProperties, globalProperties, null /* 2.0 did not have override tasks */, null /* 2.0 did not have a default override toolsversion */); toolsets.Add("2.0", synthetic20Toolset); } string defaultToolsVersionFromLocal = null; string overrideTasksPathFromLocal = null; string defaultOverrideToolsVersionFromLocal = null; if ((locations & ToolsetDefinitionLocations.Local) == ToolsetDefinitionLocations.Local) { var localReader = new ToolsetLocalReader(environmentProperties, globalProperties); defaultToolsVersionFromLocal = localReader.ReadToolsets( toolsets, globalProperties, initialProperties, false /* accumulate properties */, out overrideTasksPathFromLocal, out defaultOverrideToolsVersionFromLocal); } // We'll use the path from the configuration file if it was specified, otherwise we'll try // the one from the registry. It's possible (and valid) that neither the configuration file // nor the registry specify a override in which case we'll just return null. var overrideTasksPath = overrideTasksPathFromConfiguration ?? overrideTasksPathFromRegistry ?? overrideTasksPathFromLocal; // We'll use the path from the configuration file if it was specified, otherwise we'll try // the one from the registry. It's possible (and valid) that neither the configuration file // nor the registry specify a override in which case we'll just return null. var defaultOverrideToolsVersion = defaultOverrideToolsVersionFromConfiguration ?? defaultOverrideToolsVersionFromRegistry ?? defaultOverrideToolsVersionFromLocal; // We'll use the default from the configuration file if it was specified, otherwise we'll try // the one from the registry. It's possible (and valid) that neither the configuration file // nor the registry specify a default, in which case we'll just return null. var defaultToolsVersion = defaultToolsVersionFromConfiguration ?? defaultToolsVersionFromRegistry ?? defaultToolsVersionFromLocal; // If we got a default version from the registry or config file, and it // actually exists, fine. // Otherwise we have to come up with one. if (defaultToolsVersion != null && toolsets.ContainsKey(defaultToolsVersion)) { return(defaultToolsVersion); } // We're going to choose a hard coded default tools version of 2.0. defaultToolsVersion = Constants.defaultToolsVersion; // But don't overwrite any existing tools path for this default we're choosing. if (toolsets.ContainsKey(Constants.defaultToolsVersion)) { return(defaultToolsVersion); } // There's no tools path already for 2.0, so use the path to the v2.0 .NET Framework. // If an old-fashioned caller sets BinPath property, or passed a BinPath to the constructor, // that will overwrite what we're setting here. ErrorUtilities.VerifyThrow( Constants.defaultToolsVersion == "2.0", "Getting 2.0 FX path so default should be 2.0"); var pathToFramework = FrameworkLocationHelper.PathToDotNetFrameworkV20; // We could not find the default toolsversion because it was not installed on the machine. Fallback to the // one we expect to always be there when running msbuild 4.0. if (pathToFramework == null) { pathToFramework = FrameworkLocationHelper.PathToDotNetFrameworkV40; defaultToolsVersion = Constants.defaultFallbackToolsVersion; } // Again don't overwrite any existing tools path for this default we're choosing. if (toolsets.ContainsKey(defaultToolsVersion)) { return(defaultToolsVersion); } var defaultToolset = new Toolset( defaultToolsVersion, pathToFramework, environmentProperties, globalProperties, overrideTasksPath, defaultOverrideToolsVersion); toolsets.Add(defaultToolsVersion, defaultToolset); return(defaultToolsVersion); }
public void ReplaceToolset() { ProjectCollection collection = new ProjectCollection(); collection.RemoveAllToolsets(); Toolset toolset1 = new Toolset("x", "c:\\y", collection, null); Toolset toolset2 = new Toolset("x", "c:\\z", collection, null); collection.AddToolset(toolset1); collection.AddToolset(toolset2); Assert.Equal(toolset2, collection.GetToolset("x")); List<Toolset> toolsets = Helpers.MakeList(collection.Toolsets); Assert.Equal(1, toolsets.Count); Assert.Equal(toolset2, toolsets[0]); }
/// <summary> /// Reads the settings for a specified tools version /// </summary> private Toolset ReadToolset ( ToolsetPropertyDefinition toolsVersion, PropertyDictionary <ProjectPropertyInstance> globalProperties, PropertyDictionary <ProjectPropertyInstance> initialProperties, bool accumulateProperties ) { // Initial properties is the set of properties we're going to use to expand property expressions like $(foo) // in the values we read out of the registry or config file. We'll add to it as we pick up properties (including binpath) // from the registry or config file, so that properties there can be referenced in values below them. // After processing all the properties, we don't need initialProperties anymore. string toolsPath = null; string binPath = null; PropertyDictionary <ProjectPropertyInstance> properties = new PropertyDictionary <ProjectPropertyInstance>(); IEnumerable <ToolsetPropertyDefinition> rawProperties = GetPropertyDefinitions(toolsVersion.Name); Expander <ProjectPropertyInstance, ProjectItemInstance> expander = new Expander <ProjectPropertyInstance, ProjectItemInstance>(initialProperties, FileSystems.Default); foreach (ToolsetPropertyDefinition property in rawProperties) { EvaluateAndSetProperty(property, properties, globalProperties, initialProperties, accumulateProperties, ref toolsPath, ref binPath, ref expander); } Dictionary <string, SubToolset> subToolsets = new Dictionary <string, SubToolset>(StringComparer.OrdinalIgnoreCase); IEnumerable <string> subToolsetVersions = GetSubToolsetVersions(toolsVersion.Name); foreach (string subToolsetVersion in subToolsetVersions) { string subToolsetToolsPath = null; string subToolsetBinPath = null; IEnumerable <ToolsetPropertyDefinition> rawSubToolsetProperties = GetSubToolsetPropertyDefinitions(toolsVersion.Name, subToolsetVersion); PropertyDictionary <ProjectPropertyInstance> subToolsetProperties = new PropertyDictionary <ProjectPropertyInstance>(); // If we have a sub-toolset, any values defined here will override the toolset properties. foreach (ToolsetPropertyDefinition property in rawSubToolsetProperties) { EvaluateAndSetProperty(property, subToolsetProperties, globalProperties, initialProperties, false /* do not ever accumulate sub-toolset properties */, ref subToolsetToolsPath, ref subToolsetBinPath, ref expander); } if (subToolsetToolsPath != null || subToolsetBinPath != null) { InvalidToolsetDefinitionException.Throw("MSBuildToolsPathNotSupportedInSubToolsets", toolsVersion.Name, toolsVersion.Source.LocationString, subToolsetVersion); } subToolsets[subToolsetVersion] = new SubToolset(subToolsetVersion, subToolsetProperties); } // All tools versions must specify a value for MSBuildToolsPath (or MSBuildBinPath) if (String.IsNullOrEmpty(toolsPath) && String.IsNullOrEmpty(binPath)) { return(null); } // If both MSBuildBinPath and MSBuildToolsPath are present, they must be the same if (toolsPath != null && binPath != null && !toolsPath.Equals(binPath, StringComparison.OrdinalIgnoreCase)) { InvalidToolsetDefinitionException.Throw("ConflictingValuesOfMSBuildToolsPath", toolsVersion.Name, toolsVersion.Source.LocationString); } AppendStandardProperties(properties, globalProperties, toolsVersion.Name, null, toolsPath); Toolset toolset = null; try { var importSearchPathsTable = GetProjectImportSearchPathsTable(toolsVersion.Name, NativeMethodsShared.GetOSNameForExtensionsPath()); toolset = new Toolset(toolsVersion.Name, toolsPath == null ? binPath : toolsPath, properties, _environmentProperties, globalProperties, subToolsets, MSBuildOverrideTasksPath, DefaultOverrideToolsVersion, importSearchPathsTable); } catch (ArgumentException e) { InvalidToolsetDefinitionException.Throw("ErrorCreatingToolset", toolsVersion.Name, e.Message); } return(toolset); }
public void RemoveToolset() { ProjectCollection collection = new ProjectCollection(); Toolset toolset1 = new Toolset("x", "c:\\y", collection, null); Toolset toolset2 = new Toolset("y", "c:\\z", collection, null); int initial = Helpers.MakeList<Toolset>(collection.Toolsets).Count; collection.AddToolset(toolset1); collection.AddToolset(toolset2); Assert.Equal(true, collection.RemoveToolset("x")); Assert.Equal(false, collection.ContainsToolset("x")); Assert.Equal(1, Helpers.MakeList<Toolset>(collection.Toolsets).Count - initial); }
/// <summary> /// Reads the settings for a specified tools version /// </summary> private Toolset ReadToolset ( ToolsetPropertyDefinition toolsVersion, PropertyDictionary<ProjectPropertyInstance> globalProperties, PropertyDictionary<ProjectPropertyInstance> initialProperties, bool accumulateProperties ) { // Initial properties is the set of properties we're going to use to expand property expressions like $(foo) // in the values we read out of the registry or config file. We'll add to it as we pick up properties (including binpath) // from the registry or config file, so that properties there can be referenced in values below them. // After processing all the properties, we don't need initialProperties anymore. string toolsPath = null; string binPath = null; PropertyDictionary<ProjectPropertyInstance> properties = new PropertyDictionary<ProjectPropertyInstance>(); IEnumerable<ToolsetPropertyDefinition> rawProperties = GetPropertyDefinitions(toolsVersion.Name); Expander<ProjectPropertyInstance, ProjectItemInstance> expander = new Expander<ProjectPropertyInstance, ProjectItemInstance>(initialProperties); foreach (ToolsetPropertyDefinition property in rawProperties) { EvaluateAndSetProperty(property, properties, globalProperties, initialProperties, accumulateProperties, ref toolsPath, ref binPath, ref expander); } Dictionary<string, SubToolset> subToolsets = new Dictionary<string, SubToolset>(StringComparer.OrdinalIgnoreCase); IEnumerable<string> subToolsetVersions = GetSubToolsetVersions(toolsVersion.Name); foreach (string subToolsetVersion in subToolsetVersions) { string subToolsetToolsPath = null; string subToolsetBinPath = null; IEnumerable<ToolsetPropertyDefinition> rawSubToolsetProperties = GetSubToolsetPropertyDefinitions(toolsVersion.Name, subToolsetVersion); PropertyDictionary<ProjectPropertyInstance> subToolsetProperties = new PropertyDictionary<ProjectPropertyInstance>(); // If we have a sub-toolset, any values defined here will override the toolset properties. foreach (ToolsetPropertyDefinition property in rawSubToolsetProperties) { EvaluateAndSetProperty(property, subToolsetProperties, globalProperties, initialProperties, false /* do not ever accumulate sub-toolset properties */, ref subToolsetToolsPath, ref subToolsetBinPath, ref expander); } if (subToolsetToolsPath != null || subToolsetBinPath != null) { InvalidToolsetDefinitionException.Throw("MSBuildToolsPathNotSupportedInSubToolsets", toolsVersion.Name, toolsVersion.Source.LocationString, subToolsetVersion); } subToolsets[subToolsetVersion] = new SubToolset(subToolsetVersion, subToolsetProperties); } // All tools versions must specify a value for MSBuildToolsPath (or MSBuildBinPath) if (String.IsNullOrEmpty(toolsPath) && String.IsNullOrEmpty(binPath)) { return null; } // If both MSBuildBinPath and MSBuildToolsPath are present, they must be the same if (toolsPath != null && binPath != null && !toolsPath.Equals(binPath, StringComparison.OrdinalIgnoreCase)) { InvalidToolsetDefinitionException.Throw("ConflictingValuesOfMSBuildToolsPath", toolsVersion.Name, toolsVersion.Source.LocationString); } Toolset toolset = null; try { var importSearchPathsTable = GetProjectImportSearchPathsTable(toolsVersion.Name, NativeMethodsShared.GetOSNameForExtensionsPath()); toolset = new Toolset(toolsVersion.Name, toolsPath == null ? binPath : toolsPath, properties, _environmentProperties, globalProperties, subToolsets, MSBuildOverrideTasksPath, DefaultOverrideToolsVersion, importSearchPathsTable); } catch (ArgumentException e) { InvalidToolsetDefinitionException.Throw("ErrorCreatingToolset", toolsVersion.Name, e.Message); } return toolset; }
public void AddTwoToolsets() { ProjectCollection collection = new ProjectCollection(); collection.RemoveAllToolsets(); Toolset toolset1 = new Toolset("x", "c:\\y", collection, null); Toolset toolset2 = new Toolset("y", "c:\\z", collection, null); collection.AddToolset(toolset1); collection.AddToolset(toolset2); Assert.Equal(toolset1, collection.GetToolset("x")); Assert.Equal(toolset2, collection.GetToolset("y")); List<Toolset> toolsets = Helpers.MakeList(collection.Toolsets); Assert.Equal(2, toolsets.Count); Assert.Equal(true, toolsets.Contains(toolset1)); Assert.Equal(true, toolsets.Contains(toolset2)); }