/// <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);
        }
Beispiel #2
0
        /// <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);
                }
            }
        }