Esempio n. 1
0
        /// <summary>
        ///     Retrieve metadata for all tasks defined in the project.
        /// </summary>
        /// <param name="cancellationToken">
        ///     An optional cancellation token that can be used to cancel the operation.
        /// </param>
        /// <returns>
        ///     A dictionary of task assembly metadata, keyed by assembly path.
        /// </returns>
        /// <remarks>
        ///     Cache metadata (and persist cache to file).
        /// </remarks>
        public async Task <List <MSBuildTaskAssemblyMetadata> > GetMSBuildProjectTaskAssemblies(CancellationToken cancellationToken = default(CancellationToken))
        {
            if (!HasMSBuildProject)
            {
                throw new InvalidOperationException($"MSBuild project '{ProjectFile.FullName}' is not loaded.");
            }

            List <string> taskAssemblyFiles = new List <string>
            {
                // Include "built-in" tasks.
                Path.Combine(DotNetRuntimeInfo.GetCurrent().BaseDirectory, "Microsoft.Build.Tasks.Core.dll"),
                Path.Combine(DotNetRuntimeInfo.GetCurrent().BaseDirectory, "Roslyn", "Microsoft.Build.Tasks.CodeAnalysis.dll")
            };

            taskAssemblyFiles.AddRange(
                MSBuildProject.GetAllUsingTasks()
                .Where(usingTask => !String.IsNullOrWhiteSpace(usingTask.AssemblyFile))
                .Distinct(UsingTaskAssemblyEqualityComparer.Instance)     // Ensure each assembly path is only evaluated once.
                .Select(usingTask => Path.GetFullPath(
                            Path.Combine(
                                usingTask.ContainingProject.DirectoryPath,
                                MSBuildProject.ExpandString(usingTask.AssemblyFile)
                                .Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar)
                                )
                            ))
                .Distinct(StringComparer.OrdinalIgnoreCase)
                );

            cancellationToken.ThrowIfCancellationRequested();

            List <MSBuildTaskAssemblyMetadata> metadata = new List <MSBuildTaskAssemblyMetadata>();

            foreach (string taskAssemblyFile in taskAssemblyFiles)
            {
                Log.Verbose("Scanning assembly {TaskAssemblyFile} for task metadata...", taskAssemblyFile);

                if (!File.Exists(taskAssemblyFile))
                {
                    Log.Information("Skipped scan of task metadata for assembly {TaskAssemblyFile} (file not found).", taskAssemblyFile);

                    continue;
                }

                cancellationToken.ThrowIfCancellationRequested();

                MSBuildTaskAssemblyMetadata assemblyMetadata = await Workspace.TaskMetadataCache.GetAssemblyMetadata(taskAssemblyFile);

                metadata.Add(assemblyMetadata);

                Log.Verbose("Completed scanning of assembly {TaskAssemblyFile} for task metadata ({DiscoveredTaskCount} tasks discovered).", taskAssemblyFile, assemblyMetadata.Tasks.Count);
            }

            // Persist any changes to cached metadata.
            Workspace.PersistTaskMetadataCache();

            return(metadata);
        }
        public async Task Scan_FrameworkTaskAssembly_Success(string fileName)
        {
            string taskAssemblyFile = GetFrameworkTaskAssemblyFile(fileName);

            Assert.True(File.Exists(taskAssemblyFile), "Task assembly exists");

            MSBuildTaskAssemblyMetadata metadata = await MSBuildTaskScanner.GetAssemblyTaskMetadata(taskAssemblyFile);

            Assert.NotNull(metadata);

            Assert.NotEqual(0, metadata.Tasks.Count);

            foreach (MSBuildTaskMetadata taskMetadata in metadata.Tasks.OrderBy(task => task.TypeName))
            {
                TestOutput.WriteLine("Found task '{0}'.", taskMetadata.TypeName);
            }
        }