msbuild - 使用 MSBuild 批量重命名

标签 msbuild continuous-integration batch-rename

我刚刚加入了一个没有 CI 流程(甚至没有通宵构建)和一些粗略的开发实践的团队。人们希望改变这种状况,所以我现在的任务是创建一个通宵构建。我跟随了 this series文章:创建一个包含我们所有项目的主解决方案(一些 Web 应用程序、Web 服务、一些 Windows 服务,以及编译为命令行可执行文件的耦合工具);创建了一个 MSBuild 脚本来自动构建、打包和部署我们的产品;并创建了一个 .cmd 文件来一键完成所有操作。作为这一切的一部分,这是我现在要完成的任务:

该团队目前的做法是将 web.config 和 app.config 文件置于源代码控制之外,并将其放入名为 web.template.config 和 app.template.config 的源代码控制文件中。目的是开发人员将 .template.config 文件复制到 .config 以获得所有标准配置值,然后能够将 .config 文件中的值编辑为本地开发/测试所需的任何值.出于明显的原因,我想自动执行将 .template.config 文件重命名为 .config 的过程。执行此操作的最佳方法是什么?

是否可以在构建脚本本身中执行此操作,而不必在脚本中规定每个需要重命名的文件(这将需要在任何时候将新项目添加到解决方案时维护脚本)?或者我可能必须编写一些批处理文件,我只需从脚本运行即可?

此外,是否有更好的开发解决方案可供我建议,从而使整个过程变得不必要?

最佳答案

在阅读了大量有关项目组、目标和复制任务的资料后,我已经弄清楚了如何做我需要做的事情。

<ItemGroup>
    <FilesToCopy Include="..\**\app.template.config">
        <NewFilename>app.config</NewFilename>
    </FilesToCopy>
    <FilesToCopy Include="..\**\web.template.config">
        <NewFilename>web.config</NewFilename>
    </FilesToCopy>
    <FilesToCopy Include"..\Hibernate\hibernate.cfg.template.xml">
        <NewFilename>hibernate.cfg.xml</NewFilename>
    </FilesToCopy>
</ItemGroup>

<Target Name="CopyFiles"
        Inputs="@(FilesToCopy)"
        Outputs="@(FilesToCopy->'%(RootDir)%(Directory)%(NewFilename)')">
    <Message Text="Copying *.template.config files to *.config"/>
<Copy SourceFiles="@(FilesToCopy)"
      DestinationFiles="@(FilesToCopy->'%(RootDir)%(Directory)%(NewFilename)')"/>



我创建了一个项目组,其中包含我要复制的文件。 ** 运算符告诉它递归遍历整个目录树以查找具有指定名称的每个文件。然后,我将一个元数据添加到每个名为“NewFilename”的文件中。这就是我将每个文件重命名的内容。

此代码段将每个文件添加到名为 app.template.config 的目录结构中,并指定我将命名新文件 app.config:

<FilesToCopy Include="..\**\app.template.config">
    <NewFilename>app.config</NewFilename>
</FilesToCopy>

然后我创建一个目标来复制所有文件。这个目标最初非常简单,只是为了始终复制和覆盖文件而调用 Copy 任务。我将 FilesToCopy 项目组作为复制操作的来源。我用 transforms为了指定输出文件名,以及我的 NewFilename 元数据和众所周知的项目元数据。

以下代码段将例如将文件 c:\Project\Subdir\app.template.config 转换为 c:\Project\Subdir\app.config 并将前者复制到后者:

<Target Name="CopyFiles">
    <Copy SourceFiles="@(FilesToCopy)"
          DestinationFiles="@(FilesToCopy->'%(RootDir)%(Directory)%(NewFileName)')"/>
</Target>

但后来我注意到,开发人员可能不喜欢在每次运行脚本时都覆盖他的自定义 web.config 文件。但是,如果存储库的 web.template.config 已被修改,开发人员可能应该覆盖他的本地文件,并且现在其中有代码需要的新值。我尝试了多种不同的方法——使用“Exist()”函数将 Copy 属性“SkipUnchangedFiles”设置为 true——但无济于事。

解决方案是 building incrementally .这确保文件只会在 app.template.config 较新时被覆盖。我将文件名作为目标输入传递,并将新文件名指定为目标输出:

<Target Name="CopyFiles"
        Input="@(FilesToCopy)"
        Output="@(FilesToCopy->'%(RootDir)%(Directory)%(NewFileName)')">
      ...
</Target>

这具有目标检查以查看当前输出是否相对于输入是最新的。如果不是,即特定的 .template.config 文件比其相应的 .config 文件有更新的更改,那么它将复制 web.template.config 覆盖现有的 web.config。否则,它将单独保留开发人员的 web.config 文件且不进行修改。如果不需要复制任何指定的文件,则将完全跳过目标。在干净的存储库克隆之后,将立即复制每个文件。

以上结果证明是一个令人满意的解决方案,因为我才刚刚开始使用 MSBuild,我对其强大的功能感到惊讶。我唯一不喜欢的是我不得不在两个地方重复完全相同的转换。我讨厌复制任何类型的代码,但我不知道如何避免这种情况。如果有人有小费,将不胜感激。此外,虽然我认为需要这样做的开发实践非常糟糕,但这确实有助于减轻这种糟糕的因素。

关于msbuild - 使用 MSBuild 批量重命名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12959349/

相关文章:

visual-studio-2010 - 构建失败-TFS2008上的VS2010解决方案

windows - 如何重命名子目录中的文件?

linux - 通过在 linux 中删除 url 参数来重命名文件

c# - 如何在构建使用包的 C# 代码期间从 NuGet 包复制文本文件?

c++ - 使用 MsBuild 构建 Visual Studio Code

svn - 我们应该在每次成功构建 CI 后标记我们的 SVN 存储库吗?

java - junit:forkMode ="once"对测试正确性的影响

regex - PowerShell/Regex : Rename all files, 修改数字序列

c# - 我必须在源代码管理中包含 class.feature.cs 文件吗?

jenkins - 在 Jenkins 声明式管道中,如何根据方法设置环境变量?