public static Project[] GetProjects(SolutionFile solution, IDictionary<string, string> args) { return solution.ProjectsInOrder .Where(p => p.ProjectType != SolutionProjectType.SolutionFolder) .Select(p => LoadProject(p.AbsolutePath, SpecializeArgsForSolutionProject(solution, p, args))) .ToArray(); }
/// <summary> /// Read the file. /// </summary> /// <param name="filename">The filename of the .sln.</param> public SolutionFile(string filename) { // SolutionFile.Parse() expects a rooted path. var fullPath = Path.GetFullPath(filename); solutionFile = Microsoft.Build.Construction.SolutionFile.Parse(fullPath); }
private void ValidateProjectInSolution(Action <SlnProject, ProjectInSolution> customValidator, SlnProject[] projects, bool folders) { string solutionFilePath = GetTempFileName(); SlnFile slnFile = new SlnFile(); slnFile.AddProjects(projects); slnFile.Save(solutionFilePath, folders); MSBuildSolutionFile solutionFile = MSBuildSolutionFile.Parse(solutionFilePath); foreach (SlnProject slnProject in projects) { solutionFile.ProjectsByGuid.ContainsKey(slnProject.ProjectGuid.ToSolutionString()).ShouldBeTrue(); ProjectInSolution projectInSolution = solutionFile.ProjectsByGuid[slnProject.ProjectGuid.ToSolutionString()]; projectInSolution.AbsolutePath.ShouldBe(slnProject.FullPath); projectInSolution.ProjectGuid.ShouldBe(slnProject.ProjectGuid.ToSolutionString()); projectInSolution.ProjectName.ShouldBe(slnProject.Name); IEnumerable <string> configurationPlatforms = from configuration in slnProject.Configurations from platform in slnProject.Platforms select $"{configuration}|{platform}"; configurationPlatforms.ShouldBe(projectInSolution.ProjectConfigurations.Keys, ignoreOrder: true); customValidator?.Invoke(slnProject, projectInSolution); } }
private async Task CreateProjectsAsync(SolutionFile solution, SolutionTemplateInfo solutionTemplateInfo) { var folders = new Dictionary<Guid, SolutionFolderTemplateInfo>(); folders.Add(Guid.Empty, solutionTemplateInfo); foreach (var proj in solution.ProjectsInOrder) { await CreateSolutionItemTemplateInfoAsync(solution, solutionTemplateInfo, proj, folders); } }
string GetNameOfMissing(SolutionFile solution, String guid) { Regex re_name = new Regex(@"<ProjectReference.*?<Project>"+guid+"</Project>.*?<Name>(?'name'.*?)</Name>.*?</ProjectReference>", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline); foreach(var project in solution.ProjectsInOrder.Where(IsCsharpProject)) foreach (Match m in re_name.Matches(File.ReadAllText(project.AbsolutePath))) return m.Groups["name"].Value; return "unresolved name"; }
private static IDictionary<string, string> SpecializeArgsForSolutionProject(SolutionFile solution, ProjectInSolution p, IDictionary<string, string> args) { var targetPlatform = args.ContainsKey("Platform") ? args["Platform"] : solution.GetDefaultPlatformName(); var targetConfiguration = args.ContainsKey("Configuration") ? args["Configuration"] : solution.GetDefaultConfigurationName(); var targetSolutionConfiguration = solution.SolutionConfigurations.FirstOrDefault(conf => conf.ConfigurationName == targetConfiguration && conf.PlatformName == targetPlatform)?.FullName; var foo = targetSolutionConfiguration == null || !p.ProjectConfigurations.ContainsKey(targetSolutionConfiguration) ? null : p.ProjectConfigurations[targetSolutionConfiguration]; var copy = new Dictionary<string, string>(args); copy["Platform"] = foo == null ? targetPlatform : foo.PlatformName; copy["Configuration"] = foo == null ? targetConfiguration : foo.ConfigurationName; return copy; }
private async Task<SolutionItemTemplateInfo> CreateSolutionItemTemplateInfoAsync( SolutionFile solution, SolutionTemplateInfo solutionTemplateInfo, ProjectInSolution proj, IDictionary<Guid, SolutionFolderTemplateInfo> folders) { var id = Guid.Parse(proj.ProjectGuid); var parentId = proj.ParentProjectGuid == null ? Guid.Empty : Guid.Parse(proj.ParentProjectGuid); SolutionFolderTemplateInfo folder; if (!folders.TryGetValue(parentId, out folder)) { ProjectInSolution parentProj; if (solution.ProjectsByGuid.TryGetValue(proj.ParentProjectGuid, out parentProj)) { folder = (SolutionFolderTemplateInfo)await CreateSolutionItemTemplateInfoAsync(solution, solutionTemplateInfo, parentProj, folders); } } Debug.Assert(folder != null); SolutionItemTemplateInfo result; switch (proj.ProjectType) { case SolutionProjectType.KnownToBeMSBuildFormat: Project project = new Project(proj.AbsolutePath); var rootNamespace = project.Properties.Single(x => x.Name == "RootNamespace").EvaluatedValue; var targetName = project.Properties.Single(x => x.Name == "TargetName").EvaluatedValue; var rootName = AddRootName(rootNamespace, solutionTemplateInfo); result = new ProjectTemplateInfo(id, proj.ProjectName) { NameWithoutRoot = targetName.Substring(rootName.Length + 1), FileName = proj.AbsolutePath, ProjectConfigurations = GetProjectConfigurations(proj.ProjectConfigurations) }; break; case SolutionProjectType.SolutionFolder: if (folders.ContainsKey(id)) { return folders[id]; } result = new SolutionFolderTemplateInfo(id, proj.ProjectName); folders.Add(id, (SolutionFolderTemplateInfo)result); break; default: throw new ArgumentOutOfRangeException(); } folder.Items.Add(result); return result; }
bool AreAllReferencedProjectsPresent(SolutionFile solution) { foreach(var project in solution.ProjectsInOrder.Where(IsCsharpProject)) { if (!File.Exists(project.AbsolutePath)) { _logger.LogErr("Error SV001: Missing file {0}", project.AbsolutePath); return false; } } return true; }
public void ParseFirstProjectLine_VC() { SolutionFile p = new SolutionFile(); p.FullPath = "c:\\foo.sln"; ProjectInSolution proj = new ProjectInSolution(p); p.ParseFirstProjectLine ( "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"Project name.vcproj\", \"Relative path\\to\\Project name.vcproj\", \"Unique name-GUID\"", proj ); Assert.Fail("Should not get here"); }
private static List<string> GetParentFolderChain(SolutionFile solutionFile, ProjectInSolution project) { var parentFolderChain = new List<string>(); var parentGuid = project.ParentProjectGuid; ProjectInSolution parentFolder; while (!string.IsNullOrEmpty(parentGuid) && solutionFile.ProjectsByGuid.TryGetValue(parentGuid, out parentFolder) && parentFolder != null) { parentFolderChain.Add(parentFolder.ProjectName); parentGuid = parentFolder.ParentProjectGuid; } parentFolderChain.Reverse(); return parentFolderChain; }
/// <summary> /// Loads the <see cref="SolutionInfo"/> for the specified solution file, including all projects referenced by the solution file and /// all the projects referenced by the project files. /// </summary> public async Task <SolutionInfo> LoadSolutionInfoAsync( string solutionFilePath, CancellationToken cancellationToken = default(CancellationToken)) { if (solutionFilePath == null) { throw new ArgumentNullException(nameof(solutionFilePath)); } var absoluteSolutionPath = this.GetAbsoluteSolutionPath(solutionFilePath, Directory.GetCurrentDirectory()); using (_dataGuard.DisposableWait(cancellationToken)) { this.SetSolutionProperties(absoluteSolutionPath); } VersionStamp version = default(VersionStamp); Microsoft.Build.Construction.SolutionFile solutionFile = Microsoft.Build.Construction.SolutionFile.Parse(absoluteSolutionPath); var reportMode = this.SkipUnrecognizedProjects ? ReportMode.Log : ReportMode.Throw; // a list to accumulate all the loaded projects var loadedProjects = new LoadState(null); // load all the projects foreach (var project in solutionFile.ProjectsInOrder) { cancellationToken.ThrowIfCancellationRequested(); if (project.ProjectType != SolutionProjectType.SolutionFolder) { var projectAbsolutePath = TryGetAbsolutePath(project.AbsolutePath, reportMode); if (projectAbsolutePath != null) { IProjectFileLoader loader; if (TryGetLoaderFromProjectPath(projectAbsolutePath, reportMode, out loader)) { // projects get added to 'loadedProjects' as side-effect // never prefer metadata when loading solution, all projects get loaded if they can. var tmp = await GetOrLoadProjectAsync(projectAbsolutePath, loader, preferMetadata : false, loadedProjects : loadedProjects, cancellationToken : cancellationToken).ConfigureAwait(false); } } } } // construct workspace from loaded project infos return(SolutionInfo.Create(SolutionId.CreateNewId(debugName: absoluteSolutionPath), version, absoluteSolutionPath, loadedProjects.Projects)); }
public void ParseFirstProjectLine_VC2() { SolutionFile p = new SolutionFile(); p.FullPath = "c:\\foo.sln"; ProjectInSolution proj = new ProjectInSolution(p); p.ParseFirstProjectLine ( "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"Project name.myvctype\", \"Relative path\\to\\Project name.myvctype\", \"Unique name-GUID\"", proj ); Assert.AreEqual(SolutionProjectType.KnownToBeMSBuildFormat, proj.ProjectType); Assert.AreEqual("Project name.myvctype", proj.ProjectName); Assert.AreEqual("Relative path\\to\\Project name.myvctype", proj.RelativePath); Assert.AreEqual("Unique name-GUID", proj.ProjectGuid); }
public void BasicParseFirstProjectLine() { SolutionFile p = new SolutionFile(); p.FullPath = "c:\\foo.sln"; ProjectInSolution proj = new ProjectInSolution(p); p.ParseFirstProjectLine ( "Project(\"{Project GUID}\") = \"Project name\", \"Relative path to project file\", \"Unique name-GUID\"", proj ); Assert.AreEqual(SolutionProjectType.Unknown, proj.ProjectType); Assert.AreEqual("Project name", proj.ProjectName); Assert.AreEqual("Relative path to project file", proj.RelativePath); Assert.AreEqual("Unique name-GUID", proj.ProjectGuid); }
private void ValidateProjectInSolution(Action <SlnProject, ProjectInSolution> customValidator, SlnProject[] projects) { string solutionFilePath = GetTempFileName(); SlnFile slnFile = new SlnFile(projects); slnFile.Save(solutionFilePath); MSBuildSolutionFile solutionFile = MSBuildSolutionFile.Parse(solutionFilePath); foreach (SlnProject slnProject in projects) { solutionFile.ProjectsByGuid.ContainsKey(slnProject.ProjectGuid).ShouldBeTrue(); ProjectInSolution projectInSolution = solutionFile.ProjectsByGuid[slnProject.ProjectGuid]; projectInSolution.AbsolutePath.ShouldBe(slnProject.FullPath); projectInSolution.ProjectGuid.ShouldBe(slnProject.ProjectGuid); projectInSolution.ProjectName.ShouldBe(slnProject.Name); customValidator?.Invoke(slnProject, projectInSolution); } }
public void ParseFirstProjectLineWhereProjectNameHasSpecialCharacters() { SolutionFile p = new SolutionFile(); p.FullPath = "c:\\foo.sln"; ProjectInSolution proj = new ProjectInSolution(p); p.ParseFirstProjectLine ( "Project(\"{Project GUID}\") = \"MyProject,(=IsGreat)\", \"Relative path to project file\" , \"Unique name-GUID\"", proj ); Assert.AreEqual(SolutionProjectType.Unknown, proj.ProjectType); Assert.AreEqual("MyProject,(=IsGreat)", proj.ProjectName); Assert.AreEqual("Relative path to project file", proj.RelativePath); Assert.AreEqual("Unique name-GUID", proj.ProjectGuid); }
internal ProjectInSolution(SolutionFile solution) { _projectType = SolutionProjectType.Unknown; _projectName = null; _relativePath = null; _projectGuid = null; _dependencies = new List<string>(); _projectReferences = new ArrayList(); _parentProjectGuid = null; _uniqueProjectName = null; _parentSolution = solution; // default to .NET Framework 3.5 if this is an old solution that doesn't explicitly say. _targetFrameworkMoniker = ".NETFramework,Version=v3.5"; // This hashtable stores a AspNetCompilerParameters struct for each configuration name supported. _aspNetConfigurations = new Hashtable(StringComparer.OrdinalIgnoreCase); _projectConfigurations = new Dictionary<string, ProjectConfigurationInSolution>(StringComparer.OrdinalIgnoreCase); }
public void ParseFirstProjectLine_InvalidProject() { SolutionFile p = new SolutionFile(); p.FullPath = "c:\\foo.sln"; ProjectInSolution proj = new ProjectInSolution(p); p.ParseFirstProjectLine ( "Project(\"{Project GUID}\") = \"\", \"src\\.proj\", \"Unique name-GUID\"", proj ); Assert.AreEqual(SolutionProjectType.Unknown, proj.ProjectType); Assert.IsTrue(proj.ProjectName.StartsWith("EmptyProjectName")); Assert.AreEqual("src\\.proj", proj.RelativePath); Assert.AreEqual("Unique name-GUID", proj.ProjectGuid); }
public void SolutionConfigurationWithDependenciesRelaysItsOutputs() { #region Large strings representing solution & projects const string solutionFileContents = @" Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 11 Project(`{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}`) = `B`, `B.csproj`, `{881C1674-4ECA-451D-85B6-D7C59B7F16FA}` ProjectSection(ProjectDependencies) = postProject {4A727FF8-65F2-401E-95AD-7C8BBFBE3167} = {4A727FF8-65F2-401E-95AD-7C8BBFBE3167} EndProjectSection EndProject Project(`{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}`) = `C`, `C.csproj`, `{4A727FF8-65F2-401E-95AD-7C8BBFBE3167}` EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = preSolution {4A727FF8-65F2-401E-95AD-7C8BBFBE3167}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4A727FF8-65F2-401E-95AD-7C8BBFBE3167}.Debug|Any CPU.Build.0 = Debug|Any CPU {4A727FF8-65F2-401E-95AD-7C8BBFBE3167}.Release|Any CPU.ActiveCfg = Release|Any CPU {4A727FF8-65F2-401E-95AD-7C8BBFBE3167}.Release|Any CPU.Build.0 = Release|Any CPU {881C1674-4ECA-451D-85B6-D7C59B7F16FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {881C1674-4ECA-451D-85B6-D7C59B7F16FA}.Debug|Any CPU.Build.0 = Debug|Any CPU {881C1674-4ECA-451D-85B6-D7C59B7F16FA}.Release|Any CPU.ActiveCfg = Release|Any CPU {881C1674-4ECA-451D-85B6-D7C59B7F16FA}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal "; const string projectBravoFileContents = @" <Project ToolsVersion='msbuilddefaulttoolsversion' DefaultTargets='Build' xmlns='msbuildnamespace'> <Target Name='Build' Outputs='@(ComputedQuestion)'> <ItemGroup> <ComputedQuestion Include='What do you get if you multiply six by nine' /> </ItemGroup> </Target> </Project> "; const string projectCharlieFileContents = @" <Project ToolsVersion='msbuilddefaulttoolsversion' DefaultTargets='Build' xmlns='msbuildnamespace'> <Target Name='Build' Outputs='@(ComputedAnswer)'> <ItemGroup> <ComputedAnswer Include='42' /> </ItemGroup> </Target> </Project> "; const string automaticProjectFileContents = @" <Project ToolsVersion='msbuilddefaulttoolsversion' DefaultTargets='compile' xmlns='msbuildnamespace'> <Target Name='compile'> <MSBuild Projects='B.csproj' Targets='Build'> <Output TaskParameter='TargetOutputs' ItemName='BravoProjectOutputs' /> </MSBuild> <Message Importance='high' Text='BravoProjectOutputs: @(BravoProjectOutputs)' /> <MSBuild Projects='C.csproj' Targets='Build'> <Output TaskParameter='TargetOutputs' ItemName='CharlieProjectOutputs' /> </MSBuild> <Message Importance='high' Text='CharlieProjectOutputs: @(CharlieProjectOutputs)' /> <MSBuild Projects='B.csproj.metaproj' Targets='Build'> <Output TaskParameter='TargetOutputs' ItemName='BravoMetaProjectOutputs' /> </MSBuild> <Message Importance='high' Text='BravoMetaProjectOutputs: @(BravoMetaProjectOutputs)' /> <Error Condition=` '@(CharlieProjectOutputs);@(BravoProjectOutputs)' != '@(BravoMetaProjectOutputs)' ` Text='Metaproj must relay outputs' /> </Target> </Project>"; #endregion // arrange var logger = new MockLogger(); var loggers = new List<ILogger>(1) {logger}; var solutionFile = ObjectModelHelpers.CreateFileInTempProjectDirectory("MSBuildIssue.sln", solutionFileContents); ObjectModelHelpers.CreateFileInTempProjectDirectory("B.csproj", projectBravoFileContents); ObjectModelHelpers.CreateFileInTempProjectDirectory("C.csproj", projectCharlieFileContents); var solution = new SolutionFile {FullPath = solutionFile}; solution.ParseSolutionFile(); // act var instances = SolutionProjectGenerator.Generate(solution, null, null, new BuildEventContext(0, 0, 0, 0), null); // assert var projectBravoMetaProject = instances[1]; Assert.IsFalse(projectBravoMetaProject.Targets.Any(kvp => kvp.Value.Outputs.Equals("@()")), "The outputItem parameter can be null; the Target element should not have an Outputs attribute in that case."); // saves the in-memory metaproj to disk projectBravoMetaProject.ToProjectRootElement().Save(projectBravoMetaProject.FullPath); var automaticProjectFile = ObjectModelHelpers.CreateFileInTempProjectDirectory("automatic.msbuild", automaticProjectFileContents); var automaticProject = new Project(automaticProjectFile); var buildResult = automaticProject.Build(loggers); Assert.AreEqual(true, buildResult, String.Join(Environment.NewLine, logger.Errors.Select(beea => beea.Message))); }
/// <summary> /// This method takes a path to a solution file, parses the projects and project dependencies /// in the solution file, and creates internal data structures representing the projects within /// the SLN. /// </summary> public static SolutionFile Parse(string solutionFile) { SolutionFile parser = new SolutionFile(); parser.FullPath = solutionFile; parser.ParseSolutionFile(); return parser; }
IEnumerable<String> GetAllProjects(SolutionFile solution) { return solution.ProjectsByGuid.Keys.Cast<String>(); }
/// <summary> /// Adds a new property group with contents of the given solution configuration to the project /// Internal for unit-testing. /// </summary> internal static void AddPropertyGroupForSolutionConfiguration(ProjectRootElement msbuildProject, SolutionFile solutionFile, SolutionConfigurationInSolution solutionConfiguration) { ProjectPropertyGroupElement solutionConfigurationProperties = msbuildProject.CreatePropertyGroupElement(); msbuildProject.AppendChild(solutionConfigurationProperties); solutionConfigurationProperties.Condition = GetConditionStringForConfiguration(solutionConfiguration); StringBuilder solutionConfigurationContents = new StringBuilder(1024); XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.OmitXmlDeclaration = true; using (XmlWriter xw = XmlWriter.Create(solutionConfigurationContents, settings)) { xw.WriteStartElement("SolutionConfiguration"); // add a project configuration entry for each project in the solution foreach (ProjectInSolution project in solutionFile.ProjectsInOrder) { ProjectConfigurationInSolution projectConfiguration = null; if (project.ProjectConfigurations.TryGetValue(solutionConfiguration.FullName, out projectConfiguration)) { xw.WriteStartElement("ProjectConfiguration"); xw.WriteAttributeString("Project", project.ProjectGuid); xw.WriteAttributeString("AbsolutePath", project.AbsolutePath); xw.WriteAttributeString("BuildProjectInSolution", projectConfiguration.IncludeInBuild.ToString()); xw.WriteString(projectConfiguration.FullName); foreach (string dependencyProjectGuid in project.Dependencies) { // This is a project that the current project depends *ON* (ie., it must build first) ProjectInSolution dependencyProject; if (!solutionFile.ProjectsByGuid.TryGetValue(dependencyProjectGuid, out dependencyProject)) { // If it's not itself part of the solution, that's an invalid solution ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(dependencyProject != null, "SubCategoryForSolutionParsingErrors", new BuildEventFileInfo(solutionFile.FullPath), "SolutionParseProjectDepNotFoundError", project.ProjectGuid, dependencyProjectGuid); } // Add it to the list of dependencies, but only if it should build in this solution configuration // (If a project is not selected for build in the solution configuration, it won't build even if it's depended on by something that IS selected for build) // .. and only if it's known to be MSBuild format, as projects can't use the information otherwise if (dependencyProject.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat) { ProjectConfigurationInSolution dependencyProjectConfiguration = null; if (dependencyProject.ProjectConfigurations.TryGetValue(solutionConfiguration.FullName, out dependencyProjectConfiguration) && WouldProjectBuild(solutionFile, solutionConfiguration.FullName, dependencyProject, dependencyProjectConfiguration)) { xw.WriteStartElement("ProjectDependency"); xw.WriteAttributeString("Project", dependencyProjectGuid); xw.WriteEndElement(); } } } xw.WriteEndElement(); // </ProjectConfiguration> } } xw.WriteEndElement(); // </SolutionConfiguration> } var escapedSolutionConfigurationContents = EscapingUtilities.Escape(solutionConfigurationContents.ToString()); solutionConfigurationProperties.AddProperty("CurrentSolutionConfigurationContents", escapedSolutionConfigurationContents); msbuildProject.AddItem( "SolutionConfiguration", solutionConfiguration.FullName, new Dictionary<string, string> { { "Configuration", solutionConfiguration.ConfigurationName }, { "Platform", solutionConfiguration.PlatformName }, { "Content", escapedSolutionConfigurationContents }, }); }
/// <summary> /// Constructor. /// </summary> private SolutionProjectGenerator ( SolutionFile solution, IDictionary<string, string> globalProperties, string toolsVersionOverride, BuildEventContext projectBuildEventContext, ILoggingService loggingService ) { _solutionFile = solution; _globalProperties = globalProperties ?? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); _toolsVersionOverride = toolsVersionOverride; _projectBuildEventContext = projectBuildEventContext; _loggingService = loggingService; }
/// <summary> /// To convert project-to-project references correctly, we need some data /// out of the solution file. If we weren't given a solution file, then /// we search the project's directory and every parent directory all the /// way up to the root for the corresponding SLN file. /// </summary> /// <owner>RGoel</owner> private void SearchForSolutionFile ( ) { error.VerifyThrow(this.solutionFile == null, "Solution file already passed in!"); error.VerifyThrow(this.projectGuid != null, "Need project Guid to find solution file."); // Start by looking for a solution file in the directory of the original project file. DirectoryInfo searchDirectory = new DirectoryInfo(Path.GetDirectoryName(Path.GetFullPath(this.oldProjectFile))); while (searchDirectory != null) { // Get a list of all the .SLN files in the current search directory. FileInfo[] slnFiles = searchDirectory.GetFiles("*.sln"); // Open each .SLN file and parse it. We're searching for a .SLN // file that contains the current project that we're converting. foreach (FileInfo slnFile in slnFiles) { // Check that the extension really is ".SLN", because the above call to // GetFiles will also return files such as blah.SLN1 and bloo.SLN2. if (0 == String.Compare(".sln", slnFile.Extension, StringComparison.OrdinalIgnoreCase)) { // Parse the .SLN file. SolutionFile solutionParser = new SolutionFile(); solutionParser.FullPath = slnFile.FullName; try { solutionParser.ParseSolutionFile(); this.conversionWarnings.AddRange(solutionParser.SolutionParserWarnings); // Determine if our current project guid (for the project we're converting) // is listed in the .SLN file. if (solutionParser.GetProjectUniqueNameByGuid(this.projectGuid) != null) { // If we found our project listed, then this is the solution we will // use to help us convert the project-to-project references. this.solutionFile = slnFile.FullName; this.solution = solutionParser; return; } } catch (InvalidProjectFileException) { // If the SLN wasn't valid, that's fine ... just skip it, and // move on to the next one. } } } // Go up one directory, and search there. Stop when we hit the root. searchDirectory = searchDirectory.Parent; } // If we don't find a solution file that contains our project, that's okay... // we can still proceed. It just means that the converted project-to-project // references won't have the relative path to the referenced project. This // may prevent command-line builds from being fully functional, but it's // not the end of the world. }
/// <summary> /// Helper method to create a SolutionFile object, and call it to parse the SLN file /// represented by the string contents passed in. /// </summary> /// <param name="solutionFileContents"></param> /// <returns></returns> static internal SolutionFile ParseSolutionHelper ( string solutionFileContents ) { solutionFileContents = solutionFileContents.Replace('\'', '"'); StreamReader sr = StreamHelpers.StringToStreamReader(solutionFileContents); SolutionFile sp = new SolutionFile(); sp.SolutionFileDirectory = Path.GetTempPath(); sp.SolutionReader = sr; string tmpFileName = FileUtilities.GetTemporaryFile(); sp.FullPath = tmpFileName + ".sln"; // This file is not expected to exist at this point, so make sure it doesn't File.Delete(sp.FullPath); sp.ParseSolution(); // Clean up the temporary file that got created with this call File.Delete(tmpFileName); return sp; }
/// <summary> /// Open a solution file and all referenced projects. /// </summary> public async Task <Solution> OpenSolutionAsync(string solutionFilePath, CancellationToken cancellationToken = default(CancellationToken)) { if (solutionFilePath == null) { throw new ArgumentNullException(nameof(solutionFilePath)); } this.ClearSolution(); var absoluteSolutionPath = this.GetAbsoluteSolutionPath(solutionFilePath, Directory.GetCurrentDirectory()); using (_dataGuard.DisposableWait(cancellationToken)) { this.SetSolutionProperties(absoluteSolutionPath); } VersionStamp version = default(VersionStamp); #if !MSBUILD12 Microsoft.Build.Construction.SolutionFile solutionFile = Microsoft.Build.Construction.SolutionFile.Parse(absoluteSolutionPath); var reportMode = this.SkipUnrecognizedProjects ? ReportMode.Log : ReportMode.Throw; var invalidProjects = new List <ProjectInSolution>(); // seed loaders from known project types using (_dataGuard.DisposableWait(cancellationToken)) { foreach (var project in solutionFile.ProjectsInOrder) { if (project.ProjectType == SolutionProjectType.SolutionFolder) { continue; } var projectAbsolutePath = TryGetAbsolutePath(project.AbsolutePath, reportMode); if (projectAbsolutePath != null) { var extension = Path.GetExtension(projectAbsolutePath); if (extension.Length > 0 && extension[0] == '.') { extension = extension.Substring(1); } var loader = ProjectFileLoader.GetLoaderForProjectFileExtension(this, extension); if (loader != null) { _projectPathToLoaderMap[projectAbsolutePath] = loader; } } else { invalidProjects.Add(project); } } } // a list to accumulate all the loaded projects var loadedProjects = new List <ProjectInfo>(); // load all the projects foreach (var project in solutionFile.ProjectsInOrder) { cancellationToken.ThrowIfCancellationRequested(); if (project.ProjectType != SolutionProjectType.SolutionFolder && !invalidProjects.Contains(project)) { var projectAbsolutePath = TryGetAbsolutePath(project.AbsolutePath, reportMode); if (projectAbsolutePath != null) { IProjectFileLoader loader; if (TryGetLoaderFromProjectPath(projectAbsolutePath, reportMode, out loader)) { // projects get added to 'loadedProjects' as side-effect // never perfer metadata when loading solution, all projects get loaded if they can. var tmp = await GetOrLoadProjectAsync(projectAbsolutePath, loader, preferMetadata : false, loadedProjects : loadedProjects, cancellationToken : cancellationToken).ConfigureAwait(false); } } } } #else SolutionFile solutionFile = null; using (var reader = new StreamReader(absoluteSolutionPath)) { version = VersionStamp.Create(File.GetLastWriteTimeUtc(absoluteSolutionPath)); var text = await reader.ReadToEndAsync().ConfigureAwait(false); solutionFile = SolutionFile.Parse(new StringReader(text)); } var solutionFolder = Path.GetDirectoryName(absoluteSolutionPath); // seed loaders from known project types using (_dataGuard.DisposableWait()) { foreach (var projectBlock in solutionFile.ProjectBlocks) { string absoluteProjectPath; if (TryGetAbsoluteProjectPath(projectBlock.ProjectPath, solutionFolder, ReportMode.Ignore, out absoluteProjectPath)) { var loader = ProjectFileLoader.GetLoaderForProjectTypeGuid(this, projectBlock.ProjectTypeGuid); if (loader != null) { _projectPathToLoaderMap[absoluteProjectPath] = loader; } } } } // a list to accumulate all the loaded projects var loadedProjects = new List <ProjectInfo>(); var reportMode = this.SkipUnrecognizedProjects ? ReportMode.Log : ReportMode.Throw; // load all the projects foreach (var projectBlock in solutionFile.ProjectBlocks) { cancellationToken.ThrowIfCancellationRequested(); string absoluteProjectPath; if (TryGetAbsoluteProjectPath(projectBlock.ProjectPath, solutionFolder, reportMode, out absoluteProjectPath)) { IProjectFileLoader loader; if (TryGetLoaderFromProjectPath(absoluteProjectPath, reportMode, out loader)) { // projects get added to 'loadedProjects' as side-effect // never perfer metadata when loading solution, all projects get loaded if they can. var tmp = await GetOrLoadProjectAsync(absoluteProjectPath, loader, preferMetadata : false, loadedProjects : loadedProjects, cancellationToken : cancellationToken).ConfigureAwait(false); } } } #endif // construct workspace from loaded project infos this.OnSolutionAdded(SolutionInfo.Create(SolutionId.CreateNewId(debugName: absoluteSolutionPath), version, absoluteSolutionPath, loadedProjects)); this.UpdateReferencesAfterAdd(); return(this.CurrentSolution); }
/// <summary> /// Helper method to create a SolutionFile object, and call it to parse the SLN file /// represented by the string contents passed in. /// </summary> /// <param name="solutionFileContents"></param> /// <returns></returns> static internal SolutionFile ParseSolutionHelper(string solutionFileContents) { solutionFileContents = solutionFileContents.Replace('\'', '"'); StreamReader sr = StreamHelpers.StringToStreamReader(solutionFileContents); SolutionFile sp = new SolutionFile(); sp.SolutionFileDirectory = Path.GetTempPath(); sp.SolutionReader = sr; sp.FullPath = FileUtilities.GetTemporaryFileName(".sln"); sp.ParseSolution(); // Clean up the temporary file that got created with this call return sp; }
/// <summary> /// Figure out what solution configuration we are going to build, whether or not it actually exists in the solution /// file. /// </summary> private static string DetermineLikelyActiveSolutionConfiguration(SolutionFile solutionFile, IDictionary<string, string> globalProperties) { string activeSolutionConfiguration = null; string activeSolutionPlatform = null; globalProperties.TryGetValue("Configuration", out activeSolutionConfiguration); globalProperties.TryGetValue("Platform", out activeSolutionPlatform); if (String.IsNullOrEmpty(activeSolutionConfiguration)) { activeSolutionConfiguration = solutionFile.GetDefaultConfigurationName(); } if (String.IsNullOrEmpty(activeSolutionPlatform)) { activeSolutionPlatform = solutionFile.GetDefaultPlatformName(); } SolutionConfigurationInSolution configurationInSolution = new SolutionConfigurationInSolution(activeSolutionConfiguration, activeSolutionPlatform); return configurationInSolution.FullName; }
/// <summary> /// Initialize all member variables to get ready for a conversion. /// </summary> /// <owner>RGoel</owner> private void Initialize() { this.xmakeProject = null; this.globalPropertyGroup = null; this.language = null; this.projectGuid = null; this.preBuildEvent = null; this.postBuildEvent = null; this.solution = null; this.newWebReferencePropertiesAdded = false; this.platformForVSD = null; this.assemblyName = null; this.outputType = null; this.hasWindowsFormsReference = false; this.isMyTypeAlreadySetInOriginalProject = false; this.conversionWarnings = new ArrayList(); this.propertiesToEscape = new Dictionary<string,string>(StringComparer.OrdinalIgnoreCase); this.propertiesToEscape.Add("ApplicationIcon", null); this.propertiesToEscape.Add("AssemblyKeyContainerName", null); this.propertiesToEscape.Add("AssemblyName", null); this.propertiesToEscape.Add("AssemblyOriginatorKeyFile", null); this.propertiesToEscape.Add("RootNamespace", null); this.propertiesToEscape.Add("StartupObject", null); this.propertiesToEscape.Add("ConfigurationOverrideFile", null); this.propertiesToEscape.Add("DocumentationFile", null); this.propertiesToEscape.Add("OutputPath", null); }
public void SolutionConfigurationWithDependenciesRelaysItsOutputs() { #region Large strings representing solution & projects const string solutionFileContents = @" Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 11 Project(`{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}`) = `B`, `B.csproj`, `{881C1674-4ECA-451D-85B6-D7C59B7F16FA}` ProjectSection(ProjectDependencies) = postProject {4A727FF8-65F2-401E-95AD-7C8BBFBE3167} = {4A727FF8-65F2-401E-95AD-7C8BBFBE3167} EndProjectSection EndProject Project(`{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}`) = `C`, `C.csproj`, `{4A727FF8-65F2-401E-95AD-7C8BBFBE3167}` EndProject Project(`{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}`) = `D`, `D.csproj`, `{B6E7E06F-FC0B-48F1-911A-55E0E1566F00}` EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = preSolution {4A727FF8-65F2-401E-95AD-7C8BBFBE3167}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4A727FF8-65F2-401E-95AD-7C8BBFBE3167}.Debug|Any CPU.Build.0 = Debug|Any CPU {881C1674-4ECA-451D-85B6-D7C59B7F16FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {881C1674-4ECA-451D-85B6-D7C59B7F16FA}.Debug|Any CPU.Build.0 = Debug|Any CPU {B6E7E06F-FC0B-48F1-911A-55E0E1566F00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B6E7E06F-FC0B-48F1-911A-55E0E1566F00}.Debug|Any CPU.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal "; const string projectBravoFileContents = @" <Project ToolsVersion='msbuilddefaulttoolsversion' DefaultTargets='Build' xmlns='msbuildnamespace'> <Target Name='Build' Outputs='@(ComputedQuestion)'> <ItemGroup> <ComputedQuestion Include='What do you get if you multiply six by nine' /> </ItemGroup> </Target> <ItemGroup> <ProjectReference Include='D.csproj'> <Project>{B6E7E06F-FC0B-48F1-911A-55E0E1566F00}</Project> <Name>D</Name> </ProjectReference> </ItemGroup> </Project> "; const string projectCharlieFileContents = @" <Project ToolsVersion='msbuilddefaulttoolsversion' DefaultTargets='Build' xmlns='msbuildnamespace'> <Target Name='Build' Outputs='@(ComputedAnswer)'> <ItemGroup> <ComputedAnswer Include='42' /> </ItemGroup> </Target> </Project> "; const string projectDeltaFileContents = @" <Project ToolsVersion='msbuilddefaulttoolsversion' DefaultTargets='Build' xmlns='msbuildnamespace'> <PropertyGroup> <ProjectGuid>{B6E7E06F-FC0B-48F1-911A-55E0E1566F00}</ProjectGuid> </PropertyGroup> <Target Name='Build' Outputs='@(ComputedPunctuation)'> <ItemGroup> <ComputedPunctuation Include='!!!' /> </ItemGroup> </Target> </Project> "; const string automaticProjectFileContents = @" <Project ToolsVersion='msbuilddefaulttoolsversion' DefaultTargets='compile' xmlns='msbuildnamespace'> <Target Name='compile'> <!-- Build projects to get a baseline for their output --> <MSBuild Projects='B.csproj' Targets='Build'> <Output TaskParameter='TargetOutputs' ItemName='BravoProjectOutputs' /> </MSBuild> <Message Importance='high' Text='BravoProjectOutputs: @(BravoProjectOutputs)' /> <MSBuild Projects='C.csproj' Targets='Build'> <Output TaskParameter='TargetOutputs' ItemName='CharlieProjectOutputs' /> </MSBuild> <Message Importance='high' Text='CharlieProjectOutputs: @(CharlieProjectOutputs)' /> <MSBuild Projects='D.csproj' Targets='Build'> <Output TaskParameter='TargetOutputs' ItemName='DeltaProjectOutputs' /> </MSBuild> <Message Importance='high' Text='DeltaProjectOutputs: @(DeltaProjectOutputs)' /> <PropertyGroup> <StringifiedBravoProjectOutputs>@(BravoProjectOutputs)</StringifiedBravoProjectOutputs> <StringifiedCharlieProjectOutputs>@(CharlieProjectOutputs)</StringifiedCharlieProjectOutputs> <StringifiedDeltaProjectOutputs>@(DeltaProjectOutputs)</StringifiedDeltaProjectOutputs> </PropertyGroup> <!-- Explicitly build the metaproject generated for B --> <MSBuild Projects='B.csproj.metaproj' Targets='Build'> <Output TaskParameter='TargetOutputs' ItemName='BravoMetaProjectOutputs' /> </MSBuild> <Message Importance='high' Text='BravoMetaProjectOutputs: @(BravoMetaProjectOutputs)' /> <Error Condition=` '@(BravoProjectOutputs)' != '@(BravoMetaProjectOutputs)' ` Text='Metaproj outputs must match outputs of normal project build.' /> <!-- Build the solution as a whole (which will build the metaproj and return overall outputs) --> <MSBuild Projects='MSBuildIssue.sln'> <Output TaskParameter='TargetOutputs' ItemName='SolutionProjectOutputs' /> </MSBuild> <Message Importance='high' Text='SolutionProjectOutputs: @(SolutionProjectOutputs)' /> <Error Condition=` '@(SolutionProjectOutputs->Count())' != '3' ` Text='Overall sln outputs must include outputs of each referenced project (there should be 3).' /> <Error Condition=` '@(SolutionProjectOutputs->AnyHaveMetadataValue('Identity', '$(StringifiedBravoProjectOutputs)'))' != 'true'` Text='Overall sln outputs must include outputs of normal project build of project B.' /> <Error Condition=` '@(SolutionProjectOutputs->AnyHaveMetadataValue('Identity', '$(StringifiedCharlieProjectOutputs)'))' != 'true' ` Text='Overall sln outputs must include outputs of normal project build of project C.' /> <Error Condition=` '@(SolutionProjectOutputs->AnyHaveMetadataValue('Identity', '$(StringifiedDeltaProjectOutputs)'))' != 'true' ` Text='Overall sln outputs must include outputs of normal project build of project D.' /> </Target> </Project>"; #endregion var logger = new MockLogger(); var loggers = new List<ILogger>(1) { logger }; var solutionFile = ObjectModelHelpers.CreateFileInTempProjectDirectory("MSBuildIssue.sln", solutionFileContents); ObjectModelHelpers.CreateFileInTempProjectDirectory("B.csproj", projectBravoFileContents); ObjectModelHelpers.CreateFileInTempProjectDirectory("C.csproj", projectCharlieFileContents); ObjectModelHelpers.CreateFileInTempProjectDirectory("D.csproj", projectDeltaFileContents); var solution = new SolutionFile { FullPath = solutionFile }; solution.ParseSolutionFile(); var instances = SolutionProjectGenerator.Generate(solution, null, null, new BuildEventContext(0, 0, 0, 0), null); var projectBravoMetaProject = instances[1]; Assert.False(projectBravoMetaProject.Targets.Any(kvp => kvp.Value.Outputs.Equals("@()"))); // "The outputItem parameter can be null; the Target element should not have an Outputs attribute in that case." // saves the in-memory metaproj to disk projectBravoMetaProject.ToProjectRootElement().Save(projectBravoMetaProject.FullPath); var automaticProjectFile = ObjectModelHelpers.CreateFileInTempProjectDirectory("automatic.msbuild", automaticProjectFileContents); var automaticProject = new Project(automaticProjectFile); var buildResult = automaticProject.Build(loggers); // NOTE: most of the actual assertions for this test are embedded in automaticProjectFileContents as <Error>s Assert.True(buildResult, String.Join(Environment.NewLine, logger.Errors.Select(beea => beea.Message))); }
/// <summary> /// This method generates an MSBuild project file from the list of projects and project dependencies /// that have been collected from the solution file. /// </summary> /// <param name="solution">The parser which contains the solution file.</param> /// <param name="globalProperties">The global properties.</param> /// <param name="toolsVersionOverride">Tools Version override (may be null). This should be any tools version explicitly passed to the command-line or from an MSBuild ToolsVersion parameter.</param> /// <param name="projectBuildEventContext">The logging context for this project.</param> /// <param name="loggingService">The logging service.</param> /// <returns>An array of ProjectInstances. The first instance is the traversal project, the remaining are the metaprojects for each project referenced in the solution.</returns> internal static ProjectInstance[] Generate ( SolutionFile solution, IDictionary<string, string> globalProperties, string toolsVersionOverride, BuildEventContext projectBuildEventContext, ILoggingService loggingService ) { SolutionProjectGenerator projectGenerator = new SolutionProjectGenerator ( solution, globalProperties, toolsVersionOverride, projectBuildEventContext, loggingService ); return projectGenerator.Generate(); }
/// <summary> /// Convert passed in solution file to an MSBuild project. This method is used by Sln2Proj /// </summary> public bool ConvertSLN2Proj(string nameSolutionFile) { // Set the environment variable to cause the SolutionProjectGenerator to emit the project to disk string oldValueForMSBuildEmitSolution = Environment.GetEnvironmentVariable("MSBuildEmitSolution"); Environment.SetEnvironmentVariable("MSBuildEmitSolution", "1"); if (nameSolutionFile == null || !File.Exists(nameSolutionFile)) { return false; } // Parse the solution SolutionFile solution = new SolutionFile(); solution.FullPath = nameSolutionFile; solution.ParseSolutionFile(); // Generate the in-memory MSBuild project and output it to disk ProjectInstance[] instance = SolutionProjectGenerator.Generate(solution, null, null, BuildEventContext.Invalid, null); //Reset the environment variable Environment.SetEnvironmentVariable("MSBuildEmitSolution", oldValueForMSBuildEmitSolution); return true; }
/// <summary> /// Normally the active solution configuration/platform is determined when we build the solution /// wrapper project, not when we create it. However, we need to know them to scan project references /// for the right project configuration/platform. It's unlikely that references would be conditional, /// but still possible and we want to get that case right. /// </summary> internal static string PredictActiveSolutionConfigurationName(SolutionFile solutionFile, IDictionary<string, string> globalProperties) { string candidateFullSolutionConfigurationName = DetermineLikelyActiveSolutionConfiguration(solutionFile, globalProperties); // Now check if this solution configuration actually exists string fullSolutionConfigurationName = null; foreach (SolutionConfigurationInSolution solutionConfiguration in solutionFile.SolutionConfigurations) { if (String.Equals(solutionConfiguration.FullName, candidateFullSolutionConfigurationName, StringComparison.OrdinalIgnoreCase)) { fullSolutionConfigurationName = solutionConfiguration.FullName; break; } } return fullSolutionConfigurationName; }
// Ignore: Changes to the current directory interfere with the toolset reader. public void SolutionPassesSubToolsetToChildProjects2() { string classLibraryContentsToolsV4 = ObjectModelHelpers.CleanupFileContents( @" <Project ToolsVersion=""4.0"" DefaultTargets=""Build"" xmlns='msbuildnamespace'> <Target Name='Build'> <Message Text='.[$(VisualStudioVersion)]. .[$(MSBuildToolsVersion)].' /> </Target> </Project> "); string classLibraryContentsToolsV12 = ObjectModelHelpers.CleanupFileContents( @" <Project ToolsVersion=""msbuilddefaulttoolsversion"" DefaultTargets=""Build"" xmlns='msbuildnamespace'> <Target Name='Build'> <Message Text='.[$(VisualStudioVersion)]. .[$(MSBuildToolsVersion)].' /> </Target> </Project> "); string solutionFilePreambleV11 = @" Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Dev11 "; string solutionFilePreambleV12 = @" Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Dev11 VisualStudioVersion = 12.0.20311.0 VSPRO_PLATFORM MinimumVisualStudioVersion = 10.0.40219.1 "; string solutionBodySingleProjectContents = @" Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""ClassLibrary1"", ""ClassLibrary1.csproj"", ""{6185CC21-BE89-448A-B3C0-D1C27112E595}"" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Mixed Platforms = Debug|Mixed Platforms Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {6185CC21-BE89-448A-B3C0-D1C27112E595}.Debug|Mixed Platforms.ActiveCfg = CSConfig1|Any CPU {6185CC21-BE89-448A-B3C0-D1C27112E595}.Debug|Mixed Platforms.Build.0 = CSConfig1|Any CPU {6185CC21-BE89-448A-B3C0-D1C27112E595}.Release|Any CPU.ActiveCfg = CSConfig2|Any CPU EndGlobalSection EndGlobal "; string solutionBodyMultipleProjectsContents = @" Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""ClassLibrary1"", ""ClassLibrary1.csproj"", ""{A437DBE9-DCAA-46D8-9D80-A50EDB2244FD}"" EndProject Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""ClassLibrary2"", ""ClassLibrary2.csproj"", ""{84AA5584-4B0F-41DE-95AA-589E1447EDA0}"" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {A437DBE9-DCAA-46D8-9D80-A50EDB2244FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A437DBE9-DCAA-46D8-9D80-A50EDB2244FD}.Debug|Any CPU.Build.0 = Debug|Any CPU {A437DBE9-DCAA-46D8-9D80-A50EDB2244FD}.Release|Any CPU.ActiveCfg = Release|Any CPU {A437DBE9-DCAA-46D8-9D80-A50EDB2244FD}.Release|Any CPU.Build.0 = Release|Any CPU {84AA5584-4B0F-41DE-95AA-589E1447EDA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {84AA5584-4B0F-41DE-95AA-589E1447EDA0}.Debug|Any CPU.Build.0 = Debug|Any CPU {84AA5584-4B0F-41DE-95AA-589E1447EDA0}.Release|Any CPU.ActiveCfg = Release|Any CPU {84AA5584-4B0F-41DE-95AA-589E1447EDA0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal "; string solutionFileContentsDev11 = solutionFilePreambleV11 + solutionBodySingleProjectContents; string solutionFileContentsDev12 = solutionFilePreambleV12 + solutionBodySingleProjectContents; string[] solutions = { solutionFileContentsDev11, solutionFileContentsDev12, solutionFileContentsDev12 }; string[] projects = { classLibraryContentsToolsV4, classLibraryContentsToolsV4, classLibraryContentsToolsV12 }; string[] logoutputs = { ".[11.0]. .[4.0].", ".[11.0]. .[4.0].", String.Format(".[{0}]. .[{0}].", ObjectModelHelpers.MSBuildDefaultToolsVersion) }; string previousLegacyEnvironmentVariable = Environment.GetEnvironmentVariable("MSBUILDLEGACYDEFAULTTOOLSVERSION"); try { Environment.SetEnvironmentVariable("MSBUILDLEGACYDEFAULTTOOLSVERSION", "1"); InternalUtilities.RefreshInternalEnvironmentValues(); for (int i = 0; i < solutions.Length; i++) { string solutionFile = ObjectModelHelpers.CreateFileInTempProjectDirectory("Foo.sln", solutions[i]); string projectFile = ObjectModelHelpers.CreateFileInTempProjectDirectory("ClassLibrary1.csproj", projects[i]); SolutionFile sp = new SolutionFile(); sp.FullPath = solutionFile; sp.ParseSolutionFile(); ProjectInstance[] instances = SolutionProjectGenerator.Generate(sp, null, null, new BuildEventContext(0, 0, 0, 0), null); MockLogger logger = new MockLogger(); List<ILogger> loggers = new List<ILogger>(1); loggers.Add(logger); instances[0].Build(loggers); logger.AssertLogContains(logoutputs[i]); } // Test Dev 12 sln and mixed v4.0 and v12.0 projects string solutionFileContentsDev12MultipleProjects = solutionFilePreambleV12 + solutionBodyMultipleProjectsContents; string solutionFileMultipleProjects = ObjectModelHelpers.CreateFileInTempProjectDirectory("Foo.sln", solutionFileContentsDev12MultipleProjects); string projectFileV4 = ObjectModelHelpers.CreateFileInTempProjectDirectory("ClassLibrary1.csproj", classLibraryContentsToolsV4); string projectFileV12 = ObjectModelHelpers.CreateFileInTempProjectDirectory("ClassLibrary2.csproj", classLibraryContentsToolsV12); SolutionFile sp1 = new SolutionFile(); sp1.FullPath = solutionFileMultipleProjects; sp1.ParseSolutionFile(); ProjectInstance[] instances1 = SolutionProjectGenerator.Generate(sp1, null, null, new BuildEventContext(0, 0, 0, 0), null); MockLogger logger1 = new MockLogger(); List<ILogger> loggers1 = new List<ILogger>(1); loggers1.Add(logger1); instances1[0].Build(loggers1); logger1.AssertLogContains(".[11.0]. .[4.0]."); logger1.AssertLogContains(String.Format(".[{0}]. .[{0}].", ObjectModelHelpers.MSBuildDefaultToolsVersion)); } finally { Environment.SetEnvironmentVariable("MSBUILDLEGACYDEFAULTTOOLSVERSION", previousLegacyEnvironmentVariable); InternalUtilities.RefreshInternalEnvironmentValues(); } }
/// <summary> /// Returns true if the specified project will build in the currently selected solution configuration. /// </summary> private static bool WouldProjectBuild(SolutionFile solutionFile, string selectedSolutionConfiguration, ProjectInSolution project, ProjectConfigurationInSolution projectConfiguration) { if (projectConfiguration == null) { if (project.ProjectType == SolutionProjectType.WebProject) { // Sometimes web projects won't have the configuration we need (Release typically.) But they should still build if there is // a solution configuration for it foreach (SolutionConfigurationInSolution configuration in solutionFile.SolutionConfigurations) { if (String.Equals(configuration.FullName, selectedSolutionConfiguration, StringComparison.OrdinalIgnoreCase)) { return true; } } } // No configuration, so it can't build. return false; } if (!projectConfiguration.IncludeInBuild) { // Not included in the build. return false; } return true; }
// Ignore: Changes to the current directory interfere with the toolset reader. public void SolutionDoesntPassSubToolsetToChildProjects() { try { string classLibraryContents = @" <Project ToolsVersion=""4.0"" DefaultTargets=""Build"" xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> <Target Name='Build'> <Message Text='.[$(VisualStudioVersion)].' /> <Message Text='.[[$(MSBuildToolsVersion)]].' /> </Target> </Project> "; string projectFile = ObjectModelHelpers.CreateFileInTempProjectDirectory("ClassLibrary1.csproj", classLibraryContents); string solutionFileContents = @" Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Dev11 Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""ClassLibrary1"", ""ClassLibrary1.csproj"", ""{6185CC21-BE89-448A-B3C0-D1C27112E595}"" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Mixed Platforms = Debug|Mixed Platforms Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {6185CC21-BE89-448A-B3C0-D1C27112E595}.Debug|Mixed Platforms.ActiveCfg = CSConfig1|Any CPU {6185CC21-BE89-448A-B3C0-D1C27112E595}.Debug|Mixed Platforms.Build.0 = CSConfig1|Any CPU {6185CC21-BE89-448A-B3C0-D1C27112E595}.Release|Any CPU.ActiveCfg = CSConfig2|Any CPU EndGlobalSection EndGlobal "; string solutionFile = ObjectModelHelpers.CreateFileInTempProjectDirectory("Foo.sln", solutionFileContents); SolutionFile sp = new SolutionFile(); sp.FullPath = solutionFile; sp.ParseSolutionFile(); ProjectInstance[] instances = SolutionProjectGenerator.Generate(sp, null, null, new BuildEventContext(0, 0, 0, 0), null); Assert.AreEqual(ObjectModelHelpers.MSBuildDefaultToolsVersion, instances[0].ToolsVersion); Assert.AreEqual("11.0", instances[0].SubToolsetVersion); Assert.AreEqual("11.0", instances[0].GetPropertyValue("VisualStudioVersion")); MockLogger logger = new MockLogger(); List<ILogger> loggers = new List<ILogger>(1); loggers.Add(logger); instances[0].Build(loggers); logger.AssertLogContains(String.Format(".[{0}].", ObjectModelHelpers.MSBuildDefaultToolsVersion)); } finally { ObjectModelHelpers.DeleteTempProjectDirectory(); } }