tags:

views:

128

answers:

2

Hi,

How does one call a class static method from msbuild and store its results in a list?

EDIT: Okay, let me explain a bit further. I am using sandcastle help file builder to generate documentation for my application. One of the requirements is that you must specify the documentation sources as follows:

<DocumentationSources>
 <DocumentationSource sourceFile="$(MSBuildProjectDirectory)\..\src\myApp\bin\Debug\myApp.exe" xmlns="" />
 <DocumentationSource sourceFile="$(MSBuildProjectDirectory)\..\src\myApp\bin\Debug\myApp.xml" xmlns="" />
</DocumentationSources>

Sandcastle Help File Builder comes with a utils assembly that has a way of retrieving all dll and xml files from a specified directory. I want to call the method from this assembly and store its result as a list of <DocumentationSource>. This is a static method which returns Collection<string>

+2  A: 

Create a custom task calling that static method and returning an array of ITaskItem.

Or

You could try using the MSBuild Extension Pack Assembly.Invoke :

<PropertyGroup>
  <StaticMethodAssemblyPath>path</StaticMethodAssemblyPath>
</PropertyGroup>

<MSBuild.ExtensionPack.Framework.Assembly TaskAction="Invoke" 
                                          NetArguments="@(ArgsM)" 
                                          NetClass="StaticMethodClassName" 
                                          NetMethod="StaticMethodName" 
                                          NetAssembly="${StaticMethodAssemblyPath}">
        <Output TaskParameter="Result" PropertyName="R"/>
</MSBuild.ExtensionPack.Framework.Assembly>
madgnome
+1  A: 

Generally, the most flexible option is to create a custom MSBuild task. This is all untested code meant to just to give you the idea:

In your msbuild file:

<UsingTask TaskName="FindFiles" AssemblyFile="FindFiles.dll" />

<!-- 
As you'll see below, SearchDirectory and SearchPatterns are input parameters,
MatchingFiles is an output parameter, SourceFiles is an ItemGroup assigned to
the output.
-->
<FindFiles SearchDirectory="$(MyDirectory)" SearchPatterns="*.dll;*.xml">
    <Output ItemName="SourceFiles" TaskParameter="MatchingFiles" />
</FindFiles>

<!-- You can then use the generated ItemGroup output elsewhere. -->
<DocumentationSources>
    <DocumentationSource sourceFile="@(SourceFiles)" xmlns="" />
</DocumentationSources>

FindFiles.cs:

using System;
using System.IO;
using System.Collections.Generic;

using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace FindFiles
{
    public class FindFiles : Task
    {
        // input parameter
        [Required]
        public string SearchDirectory { get; set; }

        // output parameter
        [Required]
        public string[] SearchPatterns { get; set; }

        [Output]
        public string[] MatchingFiles { get; private set; }

        private bool ValidateParameters()
        {
      if (String.IsNullOrEmpty(SearchDirectory))
      {
       return false;
      }
      if (!Directory.Exists(SearchDirectory))
      {
       return false;
      }
      if (SearchPatterns == null || SearchPatterns.Length == 0)
      {
       return false;
      }
      return true;
     }

        // MSBuild tasks use the command pattern, this is where the magic happens,
        // refactor as needed
        public override bool Execute()
        {
            if (!ValidateParameters())
            {
             return false;
            }
            List<string> matchingFiles = new List<string>();
            try
            {

                foreach (string searchPattern in SearchPatterns)
                {
                    matchingFiles.AddRange(
                        Directory.GetFiles(SearchDirectory, searchPattern)
                        );
                }
            }
            catch (IOException)
            {
                // it might be smarter to just let this exception fly, depending on
                // how you want the task to behave
                return false;
            }
            MatchingFiles = matchingFiles.ToArray();
            return true;
        }
    }
}
Wedge