MSBuild:以常规方式复制多个目录

MSBuild:以常规方式复制多个目录,msbuild,Msbuild,我有一个包含多个web项目(例如WebappA、WebappB、WebappC)的Visual Studio解决方案。TFS生成解决方案时,会将生成结果放入_PublishedWebsites文件夹中。文件夹结构可能如下所示: $(OutDir) | +-- _PublishedWebsites | +-- WebappA | +-- WebappA_Package | +-- WebappB | +-- WebappB_Packa

我有一个包含多个web项目(例如WebappA、WebappB、WebappC)的Visual Studio解决方案。TFS生成解决方案时,会将生成结果放入_PublishedWebsites文件夹中。文件夹结构可能如下所示:

$(OutDir)
|
+-- _PublishedWebsites
    |
    +-- WebappA
    |
    +-- WebappA_Package
    |
    +-- WebappB
    |
    +-- WebappB_Package
    |
    +-- WebappC
    |
    +-- WebappC_Package
我想用zip文件为我们的运营部门构建一个部署包。因此,我让TFS运行一个MSBuild脚本,该脚本将_包文件夹复制到自定义目录结构中,该目录结构将在后续步骤中压缩

$(PackageDirectory)
|
+-- Web
    |
    +-- WebappA
    |
    +-- WebappB
    |
    +-- WebappB
我能够创建一组执行复制操作的MSBuild目标。但我对我的解决方案不满意。我以一种明确的方式引用每个webapp,这就是为什么我最终得到了大量重复代码的原因。更糟糕的是,每次添加新的webapp时,我都必须扩展构建脚本

<Target Name="Pack" DependsOnTargets="Pack-WebappA;Pack-WebappB;Pack-WebappC" />

<Target Name="Pack-WebappA">
    <ItemGroup>
        <WebAppFile Include="$(OutDir)_PublishedWebsites\WebappA_Package\*.*" />
    </ItemGroup>
    <Copy SourceFiles="@(WebAppFile)" DestinationFolder="$(PackageDirectory)Web\WebappA\"  />
</Target>

<Target Name="Pack-WebappB">
    <ItemGroup>
        <WebAppFile Include="$(OutDir)_PublishedWebsites\WebappB_Package\*.*" />
    </ItemGroup>
    <Copy SourceFiles="@(WebAppFile)" DestinationFolder="$(PackageDirectory)Web\WebappB\"  />
</Target>

<Target Name="Pack-WebappC">
    <ItemGroup>
        <WebAppFile Include="$(OutDir)_PublishedWebsites\WebappC_Package\*.*" />
    </ItemGroup>
    <Copy SourceFiles="@(WebAppFile)" DestinationFolder="$(PackageDirectory)Web\WebappC\"  />
</Target>


我正在寻找一种解决方案,它以一种通用的方式完成整个工作,而不需要引用具体的webapps。实际上,MSBuild应该做的就是查看_PublishedWebsites文件夹,并将每个带有_包后缀的子文件夹复制到另一个文件夹中,然后删除后缀。这听起来很简单,但我没能想出一个有效的解决方案。我尝试过批处理,但没有成功。

你说得很对,你对当前的解决方案不满意:自动化这些东西是必须的。我同意MsBuild并不总是让它变得简单;批处理是正确的方法,但您必须添加一些过滤/操作项。不过,使用它并不难:

实际上,MSBuild应该做的所有事情都是查看 _PublishedWebsites文件夹,并将每个带有_包后缀的子文件夹复制到另一个文件夹,然后删除后缀

我们将此转化为:

  • 列出_PublishedWebsites中的所有目录
  • 筛选列表并仅包括以_Package结尾的列表
  • 列出这些目录中的所有文件,并将它们的目标设置为PackageDirectory的子目录,并删除后缀
  • 将每个文件复制到相应的目录
步骤3实际上是两件事(list+specifydir),因为这是典型的msbuild方式。还有其他方法可以做到这一点,但这一种在这里似乎是合适的

<Target Name="BatchIt">
  <PropertyGroup>
    <SourceDir>$(OutDir)_PublishedWebsites\</SourceDir>
    <DestDir>$(PackageDirectory)Web\</DestDir>
    <PackageString>_Package</PackageString>
  </PropertyGroup>

  <ItemGroup>
    <!-- step 1 -->
    <Dirs Include="$([System.IO.Directory]::GetDirectories( `$(SourceDir)`, `*`, System.IO.SearchOption.AllDirectories ) )"/>

    <!-- step 2 -->
    <PackageDirs Include="%(Dirs.Identity)" Condition="$([System.Text.RegularExpressions.Regex]::IsMatch( %(Filename), '.*$(PackageString)' ) )"/>

    <!-- step 3 -->
    <PackageFiles Include="%(PackageDirs.Identity)\*.*">
      <DestDir>$(PackageDirectory)$([System.IO.Path]::GetFilename( %(PackageDirs.Identity) ).Replace( $(PackageString), '' ) )</DestDir>
    </PackageFiles>
  </ItemGroup>

  <!-- step 4 -->
  <Copy SourceFiles="%(PackageFiles.Identity)" DestinationFolder="%(PackageFiles.DestDir)" />
</Target>

$(OutDir)\发布的Web站点\
$(PackageDirectory)Web\
_包装
$(PackageDirectory)$([System.IO.Path]::GetFilename(%(PackageDirs.Identity)).Replace($(PackageString),“”))
编辑一种更有效、更合理的方法是在构建PackageDir列表时直接指定DestDir:

  <ItemGroup>
    <Dirs Include="$([System.IO.Directory]::GetDirectories( `$(SourceDir)`, `*`, System.IO.SearchOption.AllDirectories))"/>
    <PackageDirs Include="%(Dirs.Identity)" Condition="$([System.Text.RegularExpressions.Regex]::IsMatch( %(Filename), '.*$(PackageString)' ))">
      <DestDir>$(DestDir)$([System.IO.Path]::GetFilename( %(Dirs.Identity) ).Replace( $(PackageString), '' ))</DestDir>
    </PackageDirs>
    <PackageFiles Include="%(PackageDirs.Identity)\*.*">
      <DestDir>%(PackageDirs.DestDir)</DestDir>
    </PackageFiles>
  </ItemGroup>

$(DestDir)$([System.IO.Path]::GetFilename(%(Dirs.Identity)).Replace($(PackageString),“”))
%(PackageDirs.DestDir)

斯蒂恩想出了一个很好的答案。这几乎对我起了作用。我只改变了一两件事。至少在我的例子中,这是实现这个技巧的代码

<Target Name="PackWeb">
  <PropertyGroup>
    <SourceDir>$(OutDir.TrimEnd('\'))\_PublishedWebsites\</SourceDir>
    <PackDir>$(PackageDirectory.TrimEnd('\'))\Web\</PackDir>
    <PackageString>_Package</PackageString>
  </PropertyGroup>

  <ItemGroup>
    <Dirs Include="$([System.IO.Directory]::GetDirectories( `$(SourceDir)`, `*` ) )"/>

    <PackageDirs Include="%(Dirs.Identity)" Condition="$([System.Text.RegularExpressions.Regex]::IsMatch( %(FullPath), '.*$(PackageString)' ) )"/>

    <PackageFiles Include="%(PackageDirs.Identity)\*.*">
      <DestDir>$(PackDir)$([System.IO.Path]::GetFilename( %(PackageDirs.Identity) ).Replace( $(PackageString), '' ) )</DestDir>
    </PackageFiles>
  </ItemGroup>

  <Copy SourceFiles="%(PackageFiles.Identity)" DestinationFolder="%(PackageFiles.DestDir)" />
</Target>

$(OutDir.TrimEnd('\')\\您发布的网站\
$(PackageDirectory.TrimEnd('\')\Web\
_包装
$(PackDir)$([System.IO.Path]::GetFilename(%(PackageDirs.Identity)).Replace($(PackageString),“”))