【问题标题】:MSBuild - Calling target multiple times with different parametersMSBuild - 使用不同的参数多次调用目标
【发布时间】:2013-10-21 22:08:18
【问题描述】:

我正在尝试通过 MSBuild 将 web.configs 转换为构建过程的一部分,这很好;但是在同一个解决方案中处理多个 web.config 会导致问题。

我们目前使用的代码提取 web.config 特定信息并将其传递给转换目标,这两个操作都捆绑在 DependsOnTargets 目标中:

<Target Name="ExtractWebConfigParams_1">
  <!-- Get webConfig1 info -->
</Target>

<Target Name="TransformWebConfig_1">
  <TransformXml Source="%(webConfig1).Web.config"
                Transform="%(webConfig1).Web.Stage.config"
                Destination="%(webConfig1).Web.config"
                StackTrace="$(StackTraceEnabled)" />
</Target>

<Target Name="ExtractWebConfigParams_2">
  <!-- Get webConfig2 info -->
</Target>

<Target Name="TransformWebConfig_2">
  <TransformXml Source="%(webConfig2).Web.config"
                Transform="%(webConfig2).Web.Stage.config"
                Destination="(webConfig2).Web.config"
                StackTrace="$(StackTraceEnabled)" />
</Target>

<Target
    Name="Transform_1"
    DependsOnTargets="ExtractWebConfigParams_1;                                                                                                     
                      TransformWebConfig_1;">
</Target>   

<Target
    Name="Transform_2"
    DependsOnTargets="ExtractWebConfigParams_2;                                                                                                     
                      TransformWebConfig_2;">
</Target>   

我们的解决方案可能包含多达 5 个不同的 web.config,因此必须为它们中的每一个设置一个提取、转换和 DependsOnTargets 目标。

我看不到使用多个提取目标的方法,但有谁知道是否有一种方法可以使用不同的参数调用转换目标,而不是每次都创建一个全新的目标?

【问题讨论】:

    标签: msbuild target


    【解决方案1】:

    您可以编写一个单独的 .msbuild (.proj) 文件作为“可重用逻辑”。

    我有一个“压缩网站”的常见逻辑,我将在下面发布。 我的示例是关于压缩一个 asp.net 网站,但封装了有关忽略哪些文件的规则(例如 .csproj)......并且还有一些“钩子”用于忽略某些文件。就像“images”目录一样,我们的目录很大,所以我不想每次都把它压缩起来。

    我的示例与您的需求没有直接关系。它的想法很重要。 将所有逻辑封装到一个文件中,并将参数传递给它。

    我将 .proj 文件包含在 Main.proj 文件中。然后给它传参数。

    一个警告。如果子 .proj 文件位于与 Main.proj 文件相同的目录之外的任何位置,则相对目录在子 .proj 文件中不起作用。
    唉,您不能将目录属性设置为“.\bin\”之类的东西,您必须在调用子项目文件并传递完整文件夹名称之前找出完整路径。这个例子是 "c:\myfolder\mysolution\myproject1\bin" ... aka,随便 f

    放入“外部”Main.proj 文件的代码:

      <Target Name="ZipItUpUsingCommonLogic">
    
        <Message Text="    " />
        <Message Text=" About to Call External MSBUILD File " />
        <Message Text="    " />
    
        <MSBuild Projects="..\..\CommonLogicMsBuildStuff\WebSiteZippingCommonLogic.proj" Targets="WebSiteZippingAllTargetsWrapper" Properties="WebSiteFolderFullPath=c:\workstuff\mywebsolution;OutputFolderFullPath=c:\workstuff\buildoutputs;WebSiteZipFileNameNonConfig=MyNonConfigFiles$(Configuration).zip;WebSiteZipFileNameConfigFiles=MyWebSiteConfigFiles$(Configuration).zip;RevisionNumber=333;IgnoreFolder1=c:\workstuff\mywebsolution\images" />
    
    </Target>
    

    名为“WebSiteZippingCommonLogic.proj”的文件的代码:

    <?xml version="1.0" encoding="utf-8"?>
    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="WebSiteZippingAllTargetsWrapper">
    
      <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />
      <Import Project="$(MSBuildExtensionsPath)\ExtensionPack\MSBuild.ExtensionPack.tasks" />
      <!-- There was an issue with the xsl/document(path) function......this help address the issue.  -->
    
        <Target Name="WebSiteZippingAllTargetsWrapper">
            <CallTarget Targets="ShowParameters" />
            <CallTarget Targets="ValidateParameters" />
            <CallTarget Targets="ZipTheWebSite" />
      </Target>
    
      <Target Name="ValidateParameters">
        <Error Text="The WebSiteFolderFullPath property was not passed in correctly." Condition="'$(WebSiteFolderFullPath)' == ''" />
        <Error Text="The OutputFolderFullPath property was not passed in correctly." Condition="'$(OutputFolderFullPath)' == ''" />
        <Error Text="The WebSiteZipFileNameNonConfig property was not passed in correctly." Condition="'$(WebSiteZipFileNameNonConfig)' == ''" />
        <Error Text="The WebSiteZipFileNameConfigFiles property was not passed in correctly." Condition="'$(WebSiteZipFileNameConfigFiles)' == ''" />
        <!--<Error Text="The RevisionNumber property was not passed in correctly." Condition="'$(RevisionNumber)' == ''" />-->
      </Target>
    
        <Target Name="ShowParameters">
    
            <Message Text=" WebSiteFolderFullPath = $(WebSiteFolderFullPath)" />
            <Message Text=" OutputFolderFullPath = $(OutputFolderFullPath)" />
            <Message Text=" WebSiteZipFileNameNonConfig = $(WebSiteZipFileNameNonConfig)" />
            <Message Text=" WebSiteZipFileNameConfigFiles = $(WebSiteZipFileNameConfigFiles)" />
            <Message Text=" IgnoreFolder1 = $(IgnoreFolder1)" />
            <Message Text=" IgnoreFolder2 = $(IgnoreFolder2)" />
            <Message Text=" IgnoreFolder3 = $(IgnoreFolder3)" />
            <Message Text="    " />
            <Message Text="    " />
          </Target>
    
    
        <Target Name="ZipTheWebSite" DependsOnTargets="ValidateParameters">
    
            <ItemGroup>
                <WebSiteExcludeFiles Include="$(WebSiteFolderFullPath)\**\*.sln" />
                <WebSiteExcludeFiles Include="$(WebSiteFolderFullPath)\**\*.vbproj" />
                <WebSiteExcludeFiles Include="$(WebSiteFolderFullPath)\**\*.csproj" />
    
                <WebSiteExcludeFiles Include="$(WebSiteFolderFullPath)\**\*.config" />
    
    
                <WebSiteExcludeFiles Include="$(WebSiteFolderFullPath)\.svn\**\*.*" />
                <WebSiteExcludeFiles Include="$(WebSiteFolderFullPath)\obj\**\*.*" />
    
                <WebSiteExcludeFiles Include="$(WebSiteFolderFullPath)\**\.svn\**" />
                <WebSiteExcludeFiles Include="$(WebSiteFolderFullPath)**\.svn\**\*.*" />
    
                <WebSiteExcludeFiles Include="$(IgnoreFolder1)\**\*.*" Condition="'$(IgnoreFolder1)' != ''" />
                <WebSiteExcludeFiles Include="$(IgnoreFolder2)\**\*.*" Condition="'$(IgnoreFolder2)' != ''" />          
                <WebSiteExcludeFiles Include="$(IgnoreFolder3)\**\*.*" Condition="'$(IgnoreFolder3)' != ''" />              
    
            </ItemGroup>
    
            <ItemGroup>
                <WebSiteNonConfigIncludeFiles Include="$(WebSiteFolderFullPath)\**\*.*" Exclude="@(WebSiteExcludeFiles)">
                </WebSiteNonConfigIncludeFiles>
            </ItemGroup>
    
    
            <MSBuild.Community.Tasks.Zip Files="@(WebSiteNonConfigIncludeFiles)" ZipFileName="$(OutputFolderFullPath)\$(WebSiteZipFileNameNonConfig)" WorkingDirectory="$(WebSiteFolderFullPath)\" />
    
            <ItemGroup>
                <WebSiteConfigIncludeFiles Include="$(WebSiteFolderFullPath)\**\*.config">
                </WebSiteConfigIncludeFiles>
            </ItemGroup>
    
            <MSBuild.Community.Tasks.Zip Files="@(WebSiteConfigIncludeFiles)" ZipFileName="$(OutputFolderFullPath)\$(WebSiteZipFileNameConfigFiles)" WorkingDirectory="$(WebSiteFolderFullPath)\" />
    
            <Message Text="    " />
            <Message Text="    " />
    
        </Target>
    
    
    </Project>
    

    如果您不想将规则封装到单独的文件中,那么您可能正在寻找这个:

    http://sstjean.blogspot.com/2006/09/how-to-get-msbuild-to-run-complete.html

    但是,我发现不断的“条件检查”很烦人,这就是我使用上面描述的“按文件”方法的原因。

    我将在此处复制/粘贴他的示例,以防他的博客出现故障。 还记得“gotdotnet.com”吗?

    <?xml version="1.0" encoding="utf-8"?>
    <Project DefaultTargets="Test" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    
      <ItemGroup>
        <Package Include="CommonWebSetup.ism">
          <PackagerType>IS</PackagerType>
          <SetupProjFolder>CommonWebSetup</SetupProjFolder>
          <ISProductConfig>Server</ISProductConfig>
          <ISReleaseConfig>Release</ISReleaseConfig>
        </Package>
        <Package Include="CommonClientSetup.vdproj">
          <PackagerType>VS</PackagerType>
          <SetupProjFolder>CommonClientSetup</SetupProjFolder>
          <ISProductConfig>Client</ISProductConfig>
          <ISReleaseConfig>Release</ISReleaseConfig>
        </Package>
      </ItemGroup>
    
    
    <Target Name="Test" Outputs="%(Package.Identity)" >
        <Message Text="Removing read-only flag for %(Package.Identity)" Importance="High" />  
    
        <Message Text="Setting Environment variable for %(Package.Identity)" Importance="High" />  
    
        <Message Condition=" '%(Package.PackagerType)' == 'IS' " 
                 Text="Running InstallShield for %(Package.Identity)" Importance="High" />  
    
        <Message Condition=" '%(Package.PackagerType)' == 'VS' " 
                 Text="Running DevEnv.exe for %(Package.Identity)" Importance="High" />  
    </Target>
    

    【讨论】:

    • 感谢您的详细回复,但这不是我要找的。我们有一个类似的设置来压缩我们的构建文件,它都包含在一个 .msbuild 文件中,这是我需要做的。我要做的就是用不同的参数多次调用一个目标,在我遇到 MSBuild 之前,我认为这属于任何编程语言的基础......
    • 我的回复已附加。
    • 使用“身份”或编写一个单独的文件......这些就像你的选择......据我所知。
    • Identity 效果很好,我仍然认为应该有一种更简单的机制来调用 MSBuild 中具有不同参数的目标;无论如何感谢您的输入 GranadaCoder!
    猜你喜欢
    • 2010-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-17
    • 2022-01-04
    • 2011-08-24
    • 1970-01-01
    相关资源
    最近更新 更多