/// <summary> /// Resolves the location of the reference files. /// </summary> /// <param name="baseProject">The base project.</param> /// <param name="referenceReplacements">A different set of references to use instead of those in the project. /// Used by the GacReferencePanel.</param> public static IList <ReferenceProjectItem> ResolveAssemblyReferences( MSBuildBasedProject baseProject, ReferenceProjectItem[] additionalReferences = null, bool resolveOnlyAdditionalReferences = false, bool logErrorsToOutputPad = true) { ProjectInstance project = baseProject.CreateProjectInstance(); project.SetProperty("BuildingProject", "false"); project.SetProperty("DesignTimeBuild", "true"); List <ProjectItemInstance> references = ( from item in project.Items where ItemType.ReferenceItemTypes.Contains(new ItemType(item.ItemType)) select item ).ToList(); List <ReferenceProjectItem> referenceProjectItems; if (resolveOnlyAdditionalReferences) { // Remove existing references from project foreach (ProjectItemInstance reference in references) { project.RemoveItem(reference); } references.Clear(); referenceProjectItems = new List <ReferenceProjectItem>(); } else { // Remove the "Private" meta data. // This is necessary to detect the default value for "Private" foreach (ProjectItemInstance reference in references) { reference.RemoveMetadata("Private"); } referenceProjectItems = baseProject.Items.OfType <ReferenceProjectItem>().ToList(); } if (additionalReferences != null) { referenceProjectItems.AddRange(additionalReferences); foreach (ReferenceProjectItem item in additionalReferences) { references.Add(project.AddItem("Reference", item.Include)); } } List <string> targets = new List <string>(); if (baseProject.HasProjectType(ProjectTypeGuids.PortableLibrary)) { targets.Add("ResolveReferences"); targets.Add("DesignTimeResolveAssemblyReferences"); } else { targets.Add("ResolveAssemblyReferences"); } BuildRequestData requestData = new BuildRequestData(project, targets.ToArray(), new HostServices()); List <ILogger> loggers = new List <ILogger>(); //loggers.Add(new ConsoleLogger(LoggerVerbosity.Diagnostic)); if (logErrorsToOutputPad) { loggers.Add(new SimpleErrorLogger()); } lock (SolutionProjectCollectionLock) { BuildParameters parameters = new BuildParameters(baseProject.MSBuildProjectCollection); parameters.Loggers = loggers; LoggingService.Debug("Started build for ResolveAssemblyReferences"); BuildResult result = BuildManager.DefaultBuildManager.Build(parameters, requestData); if (result == null) { throw new InvalidOperationException("BuildResult is null"); } LoggingService.Debug("Build for ResolveAssemblyReferences finished: " + result.OverallResult); } IEnumerable <ProjectItemInstance> resolvedAssemblyProjectItems = project.GetItems("_ResolveAssemblyReferenceResolvedFiles"); var query = from msbuildItem in resolvedAssemblyProjectItems let originalInclude = msbuildItem.GetMetadataValue("OriginalItemSpec") join item in referenceProjectItems.Where(p => p.ItemType != ItemType.ProjectReference) on originalInclude equals item.Include into referenceItems select new { OriginalInclude = originalInclude, AssemblyName = new DomAssemblyName(msbuildItem.GetMetadataValue("FusionName")), FullPath = FileUtility.GetAbsolutePath(baseProject.Directory, msbuildItem.GetMetadataValue("Identity")), Redist = msbuildItem.GetMetadataValue("Redist"), CopyLocal = bool.Parse(msbuildItem.GetMetadataValue("CopyLocal")), ReferenceItems = referenceItems }; // HACK: mscorlib is reported twice for portable library projects (even if we don't specify it as additionalReference) query = query.DistinctBy(asm => asm.FullPath); List <ReferenceProjectItem> resolvedAssemblies = new List <ReferenceProjectItem>(); List <ReferenceProjectItem> handledReferenceItems = new List <ReferenceProjectItem>(); foreach (var assembly in query) { LoggingService.Debug("Got information about " + assembly.OriginalInclude + "; fullpath=" + assembly.FullPath); foreach (var referenceItem in assembly.ReferenceItems) { referenceItem.AssemblyName = assembly.AssemblyName; referenceItem.FileName = assembly.FullPath; referenceItem.Redist = assembly.Redist; referenceItem.DefaultCopyLocalValue = assembly.CopyLocal; handledReferenceItems.Add(referenceItem); } ReferenceProjectItem firstItem = assembly.ReferenceItems.FirstOrDefault(); if (firstItem != null) { resolvedAssemblies.Add(firstItem); } else { resolvedAssemblies.Add(new ReferenceProjectItem(baseProject, assembly.OriginalInclude) { FileName = assembly.FullPath }); } } // Add any assemblies that weren't resolved yet. This is important - for example, this adds back project references. foreach (var referenceItem in referenceProjectItems.Except(handledReferenceItems)) { resolvedAssemblies.Add(referenceItem); } return(resolvedAssemblies); }
/// <summary> /// Resolves the location of the reference files. /// </summary> /// <param name="baseProject">The base project.</param> /// <param name="referenceReplacements">A different set of references to use instead of those in the project. /// Used by the GacReferencePanel.</param> internal static void ResolveAssemblyReferences(MSBuildBasedProject baseProject, ReferenceProjectItem[] referenceReplacements) { ProjectInstance project = baseProject.CreateProjectInstance(); project.SetProperty("BuildingProject", "false"); List <ProjectItemInstance> references = ( from item in project.Items where ItemType.ReferenceItemTypes.Contains(new ItemType(item.ItemType)) select item ).ToList(); ReferenceProjectItem[] referenceProjectItems; if (referenceReplacements == null) { // Remove the "Private" meta data. // This is necessary to detect the default value for "Private" foreach (ProjectItemInstance reference in references) { reference.RemoveMetadata("Private"); } referenceProjectItems = baseProject.Items.OfType <ReferenceProjectItem>().ToArray(); } else { foreach (ProjectItemInstance reference in references) { project.RemoveItem(reference); } foreach (ReferenceProjectItem item in referenceReplacements) { project.AddItem("Reference", item.Include); } referenceProjectItems = referenceReplacements; } string[] targets = { "ResolveAssemblyReferences" }; BuildRequestData requestData = new BuildRequestData(project, targets, new HostServices()); List <ILogger> loggers = new List <ILogger>(); if (referenceReplacements == null) { loggers.Add(new SimpleErrorLogger()); } lock (SolutionProjectCollectionLock) { BuildParameters parameters = new BuildParameters(baseProject.MSBuildProjectCollection); parameters.Loggers = loggers; LoggingService.Debug("Started build for ResolveAssemblyReferences"); BuildResult result = BuildManager.DefaultBuildManager.Build(parameters, requestData); if (result == null) { throw new InvalidOperationException("BuildResult is null"); } LoggingService.Debug("Build for ResolveAssemblyReferences finished: " + result.OverallResult); } var referenceDict = new Dictionary <string, ReferenceProjectItem>(); foreach (ReferenceProjectItem item in referenceProjectItems) { // references could be duplicate, so we cannot use referenceDict.Add or reference.ToDictionary referenceDict[item.Include] = item; } foreach (ProjectItemInstance item in project.GetItems("_ResolveAssemblyReferenceResolvedFiles")) { string originalInclude = item.GetMetadataValue("OriginalItemSpec"); ReferenceProjectItem reference; if (referenceDict.TryGetValue(originalInclude, out reference)) { reference.AssemblyName = new Dom.DomAssemblyName(item.GetMetadataValue("FusionName")); //string fullPath = item.GetEvaluatedMetadata("FullPath"); is incorrect for relative paths string fullPath = FileUtility.GetAbsolutePath(baseProject.Directory, item.GetMetadataValue("Identity")); reference.FileName = fullPath; reference.Redist = item.GetMetadataValue("Redist"); LoggingService.Debug("Got information about " + originalInclude + "; fullpath=" + fullPath); reference.DefaultCopyLocalValue = bool.Parse(item.GetMetadataValue("CopyLocal")); } else { LoggingService.Warn("Unknown item " + originalInclude); } } }