【问题标题】:Loop projects in a solution within MSBuild在 MSBuild 中的解决方案中循环项目
【发布时间】:2014-05-19 09:17:39
【问题描述】:

在我的工作地点,我们有一个“核心”解决方案,其中包含许多提供不同实用功能的项目,这些功能通过 nuget 打包并发布到内部 nuget 服务器。为了从我们的 CI 中实现 nuget 打包,我们目前有一个如下所示的 MSBuild 脚本:

<Exec Command="nuget pack &quot;$(ProjectRoot)\Domain\Domain.csproj&quot; -Properties Configuration=$(Configuration)" />
<Exec Command="nuget pack &quot;$(ProjectRoot)\Logging\Logging.csproj&quot; -Properties Configuration=$(Configuration)" />
<Exec Command="nuget pack &quot;$(ProjectRoot)\Logging.NLog\Logging.NLog.csproj&quot; -Properties Configuration=$(Configuration)" />
<Exec Command="nuget pack &quot;$(ProjectRoot)\Persistence\Persistence.csproj&quot; -Properties Configuration=$(Configuration)" />
<Exec Command="nuget pack &quot;$(ProjectRoot)\Persistence.NHibernate\Persistence.NHibernate.csproj&quot; -Properties Configuration=$(Configuration)" />

我们有大约 20 个项目以这种方式打包,每次我们引入要打包的新项目时,我们都必须在 MSBuild 脚本中添加另一行。是否可以使用 MSbuild 枚举解决方案中的项目,从而将此脚本压缩成类似...

<foreach project in solution>
    <Exec Command="nuget pack project -Properties Configuration=$(Configuration)" />
</foreach>

此外,我们需要能够询问循环中的每个项目以排除测试项目(这些都在 Tests 目录下,所以应该是微不足道的?)

编辑: Other questions 处理循环执行 msbuild 任务的问题,但解决方案涉及手动枚举要在 ItemGroup 中循环的项目,因此会导致稍微简单但仍然非常冗长的代码。如果可能,我想避免手动枚举项目。

【问题讨论】:

  • 可能duplicate.
  • @Sinatr 我已经看到了这个问题,但它并没有解决我的问题 - 提出了一个解决方案,可以在 ItemGroup 的内容上循环执行 Exec,但您仍然必须键入项目手动将名称放入 ItemGroup。如果可能,我想避免实际命名所有项目。
  • 那么this one 呢?和this?
  • 那个也使用 ItemGroups 来枚举要循环的对象,这正是我希望避免的 - 如果我使用 Itemgroups,我仍然必须在每次我时向 ItemGroup 添加一行添加要打包的新项目。

标签: c# .net msbuild


【解决方案1】:

您可以使用属性SolutionDirSolutionName 来定位解决方案文件,然后编写自定义目标来查找包含在您的解决方案中的所有项目。我是这样设计的:

<Target Name="AfterBuild" DependsOnTargets="PublishNuGetPackages" />
<Target Name="PublishNuGetPackages">
    <CollectNuGetProjects SolutionDir="$(SolutionDir)" SolutionName="$(SolutionName)">
        <Output TaskParameter="NuGetProjects" ItemName="NuGetProjects" />
    </CollectNuGetProjects>
    <Message Text="Collected the following nuget projects: @(NuGetProjects)" Importance="high" />
    <Exec Command="nuget pack &quot;$(SolutionDir)\%(NuGetProjects.Identity)&quot; -Properties Configuration=$(Configuration)" />
    <!-- publish packages etc... -->
</Target>

<UsingTask TaskName="CollectNuGetProjects" 
       TaskFactory="CodeTaskFactory" 
       AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
    <ParameterGroup>
        <SolutionName ParameterType="System.String" Required="true" />
        <SolutionDir ParameterType="System.String" Required="true" />
        <NuGetProjects ParameterType="System.String[]" Output="true" />
    </ParameterGroup>
    <Task>
        <Reference Include="System.Linq" />
        <Using Namespace="System" />
        <Using Namespace="System.Linq" />
        <Using Namespace="System.Text.RegularExpressions" />
        <Code Type="Fragment" Language="cs">
            <![CDATA[
                var solutionFile = Path.Combine(SolutionDir, SolutionName + ".sln");
                var solutionText = File.ReadAllText(solutionFile);
                NuGetProjects = Regex.Matches(solutionText, @"""(?<projectFile>[^""]+?\.(csproj|wixproj|vcxproj))""")
                    .Cast<Match>()
                    .Select(m => m.Groups["projectFile"].Value)
                    .Where(p => !p.Contains(@"\Tests\"))
                    .ToArray();
        ]]>
        </Code>
    </Task>
</UsingTask>

自定义任务还可以根据需要过滤出位于文件夹 Tests 中的项目。

【讨论】:

  • 感谢@sburg,会试一试!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-24
  • 1970-01-01
  • 1970-01-01
  • 2017-12-23
  • 2019-03-02
相关资源
最近更新 更多