使用msbuild,我想使用teamcity中的值更新配置文件 [英] Using msbuild I want to update a config file with values from teamcity

查看:112
本文介绍了使用msbuild,我想使用teamcity中的值更新配置文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些看起来像这样的XML:

I have some XML that looks something like this:

<?xml version="1.0" encoding="utf-8"?>
<XmlConfig instancetype="XmlConfig, Processing, Version=1.0.0.0, Culture=neutral">
  <item>
    <key>IsTestEnvironment</key>
    <value>True</value>
    <encrypted>False</encrypted>
  </item>
  <item>
    <key>HlrFtpPutDir</key>
    <value>C:\DevPath1</value>
    <encrypted>False</encrypted>
  </item>
  <item>
    <key>HlrFtpPutCopyDir</key>
    <value>C:\DevPath2</value>
    <encrypted>False</encrypted>
  </item>

   ....

</Provisioning.Lib.Processing.XmlConfig>

在TeamCity中,我具有许多系统属性:

In TeamCity I have many system properties:

 system.HlrFtpPutDir     H:\ReleasePath1
 system.HlrFtpPutCopyDir H:\ReleasePath2

我可以使用哪种MsBuild魔术将这些值推送到XML文件中?总共有20个左右的项目.

What sort of MsBuild magic can I use to push these values into my XML file? In all there are 20 or so items.

推荐答案

我刚刚对此写了博客(

I just blogged about this (http://sedodream.com/2011/12/29/UpdatingXMLFilesWithMSBuild.aspx) but I'll paste the info here for you as well.

今天,我刚刚在StackOverflow上看到一个问题,询问如何在从Team City执行CI构建期间使用MSBuild更新XML文件.

Today I just saw a question posted on StackOverflow asking how to update an XML file using MSBuild during a CI build executed from Team City.

没有正确的单个答案,在构建期间可以通过几种不同的方式更新XML文件.最值得注意的是:

There is not correct single answer, there are several different ways that you can update an XML file during a build. Most notably:

  1. 使用SlowCheetah为您转换文件
  2. 直接使用TransformXml任务
  3. 使用内置的(MSBuild 4.0)XmlPoke任务
  4. 使用第三方任务库

1使用SlowCheetah为您转换文件

在您开始阅读这篇文章之前,让我先谈谈选项#3,因为我认为这是最简单,最容易维护的方法.您可以下载我的SlowCheetah XML Transforms Visual Studio加载项.完成针对项目的操作后,将看到一个新的菜单命令,用于转换构建中的文件(对于打包/发布中的Web项目).如果您是从命令行或CI服务器构建的,则转换也应运行.

1 Use SlowCheetah to transform the files for you

Before you start reading too far into this post let me go over option #3 first because I think it’s the easiest approach and the most easily maintained. You can download my SlowCheetah XML Transforms Visual Studio add in. Once you do this for your projects you will see a new menu command to transform a file on build (for web projects on package/publish). If you build from the command line or a CI server the transforms should run as well.

如果您想要一种具有主" XML文件的技术,并且希望能够在单独的XML文件中包含对该文件的转换,则可以直接使用TransformXml任务.有关详细信息,请参阅我以前的博客文章,网址为 http://sedodream.com/2010/11/18/XDTWebconfigTransformsInNonwebProjects.aspx

If you want a technique where you have a "main" XML file and you want to be able to contain transformations to that file inside of a separate XML file then you can use the TransformXml task directly. For more info see my previous blog post at http://sedodream.com/2010/11/18/XDTWebconfigTransformsInNonwebProjects.aspx

有时候,用每个XML文件的转换来创建XML文件是没有意义的.例如,如果您有一个XML文件,而您想要修改一个值,但要创建10个不同的文件,那么XML转换方法就无法很好地扩展.在这种情况下,使用XmlPoke任务可能会更容易.请注意,这确实需要MSBuild 4.0.

Sometimes it doesn’t make sense to create an XML file with transformations for each XML file. For example if you have an XML file and you want to modify a single value but to create 10 different files the XML transformation approach doesn’t scale well. In this case it might be easier to use the XmlPoke task. Note this does require MSBuild 4.0.

下面是sample.xml的内容(来自SO问题).

Below are the contents of sample.xml (came from the SO question).

<Provisioning.Lib.Processing.XmlConfig instancetype="XmlConfig, Processing, Version=1.0.0.0, Culture=neutral">
  <item>
    <key>IsTestEnvironment</key>
    <value>True</value>
    <encrypted>False</encrypted>
  </item>
  <item>
    <key>HlrFtpPutDir</key>
    <value>C:\DevPath1</value>
    <encrypted>False</encrypted>
  </item>
  <item
    <key>HlrFtpPutCopyDir</key>
    <value>C:\DevPath2</value>
    <encrypted>False</encrypted>
  </item>
</Provisioning.Lib.Processing.XmlConfig>

因此,在这种情况下,我们要更新value元素的值.因此,我们要做的第一件事是为要更新的所有元素提供正确的XPath.在这种情况下,我们可以为每个值元素使用以下XPath表达式.

So in this case we want to update the values of the value element. So the first thing that we need to do is to come up with the correct XPath for all the elements which we want to update. In this case we can use the following XPath expressions for each value element.

  • /Provisioning.Lib.Processing.XmlConfig/item [key ='HlrFtpPutDir']/value
  • /Provisioning.Lib.Processing.XmlConfig/item [key ='HlrFtpPutCopyDir']/value 我不会再讨论确定正确的XPath所需做的事情,因为这不是本文的目的.互连网上有大量与XPath相关的资源.在资源部分中,我已链接到我一直使用的在线XPath测试器.
  • /Provisioning.Lib.Processing.XmlConfig/item[key='HlrFtpPutDir']/value
  • /Provisioning.Lib.Processing.XmlConfig/item[key='HlrFtpPutCopyDir']/value I’m not going to go over what you need to do to figure out the correct XPath because that’s not the purpose of this post. There are a bunch of XPath related resources on the interwebs. In the resources section I have linked to the online XPath tester which I always use.

现在,我们已经拥有了构造MSBuild元素以更新所有内容所需的XPath表达式.这是整体技术:

Now that we’ve got the required XPath expressions we need to construct our MSBuild elements to get everything updated. Here is the overall technique:

  1. 将所有XML更新的所有信息放入一个项目中
  2. 结合使用XmlPoke和MSBuild批处理来执行所有更新

对于#2,如果您不太熟悉MSBuild批处理,那么我建议您购买我的书,或者您可以看一下我在线上与批处理有关的资源(链接位于资源部分的下面).在下面,您将找到我创建的一个简单的MSBuild文件UpdateXm01.proj.

For #2 if you are not that familiar with MSBuild batching then I would recommend buying my book or you can take a look at the resources I have online relating to batching (the link is below in resources section). Below you will find a simple MSBuild file that I created, UpdateXm01.proj.

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="UpdateXml" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <SourceXmlFile>$(MSBuildProjectDirectory)\sample.xml</SourceXmlFile>
    <DestXmlFiles>$(MSBuildProjectDirectory)\result.xml</DestXmlFiles>
  </PropertyGroup>

  <ItemGroup>
    <!-- Create an item which we can use to bundle all the transformations which are needed -->
    <XmlConfigUpdates Include="ConfigUpdates-SampleXml">
      <XPath>/Provisioning.Lib.Processing.XmlConfig/item[key='HlrFtpPutDir']/value</XPath>
      <NewValue>H:\ReleasePath1</NewValue>
    </XmlConfigUpdates>

    <XmlConfigUpdates Include="ConfigUpdates-SampleXml">
      <XPath>/Provisioning.Lib.Processing.XmlConfig/item[key='HlrFtpPutCopyDir']/value</XPath>
      <NewValue>H:\ReleasePath2</NewValue>
    </XmlConfigUpdates>
  </ItemGroup>

  <Target Name="UpdateXml">
    <Message Text="Updating XML file at $(DestXmlFiles)" />
    <Copy SourceFiles="$(SourceXmlFile)"
          DestinationFiles="$(DestXmlFiles)" />
    <!-- Now let's execute all the XML transformations -->
    <XmlPoke XmlInputPath="$(DestXmlFiles)"
             Query="%(XmlConfigUpdates.XPath)"
             Value="%(XmlConfigUpdates.NewValue)"/>
  </Target>
</Project>

需要密切注意的部分是XmlConfigUpdates项目和UpdateXml任务本身的内容.关于XmlConfigUpdates,该名称是任意的,您可以使用所需的任何名称,您可以看到Include值(通常指向文件)仅保留在ConfigUpdates-SampleXml中.此处未使用Include属性的值.我将为要更新的每个文件的Include属性放置一个唯一值.这只是使人们更容易理解该组值的用途,您以后可以使用它来批处理更新. XmlConfigUpdates项具有以下两个元数据值:

The parts to pay close attention to is the XmlConfigUpdates item and the contents of the UpdateXml task itself. Regarding the XmlConfigUpdates, that name is arbitrary you can use whatever name you want, you can see that the Include value (which typically points to a file) is simply left at ConfigUpdates-SampleXml. The value for the Include attribute is not used here. I would place a unique value for the Include attribute for each file that you are updating. This just makes it easier for people to understand what that group of values is for, and you can use it later to batch updates. The XmlConfigUpdates item has these two metadata values:

  • XPath -包含选择要更新的元素所需的XPath
  • NewValue -包含将要更新的元素的新值 在UpdateXml目标内部,您可以看到我们正在使用XmlPoke任务,并将XPath传递为%(XmlConfigUpdate.XPath),并将值传递为%(XmlConfigUpdates.NewValue).由于我们在项目上使用%(…)语法,因此将开始MSBuild批处理.批处理是对值的批"执行多个操作的地方.在这种情况下,有两个唯一的批次(XmlConfigUpdates中的每个值1个),因此XmlPoke任务将被调用两次.批处理可能会造成混淆,因此,如果您不熟悉批处理,请务必仔细阅读.
  • XPath -- This contains the XPath required to select the element which is going to be updated
  • NewValue -- This contains the new value for the element which is going to be updated Inside of the UpdateXml target you can see that we are using the XmlPoke task and passing the XPath as %(XmlConfigUpdate.XPath) and the value as %(XmlConfigUpdates.NewValue). Since we are using the %(…) syntax on an item this start MSBuild batching. Batching is where more than one operation is performed over a "batch" of values. In this case there are two unique batches (1 for each value in XmlConfigUpdates) so the XmlPoke task will be invoked two times. Batching can be confusing so make sure to read up on it if you are not familiar.

现在,我们可以使用msbuild.exe启动该过程.生成的XML文件为:

Now we can use msbuild.exe to start the process. The resulting XML file is:

<Provisioning.Lib.Processing.XmlConfig instancetype="XmlConfig, Processing, Version=1.0.0.0, Culture=neutral">
  <item>
    <key>IsTestEnvironment</key>
    <value>True</value>
    <encrypted>False</encrypted>
  </item>
  <item>
    <key>HlrFtpPutDir</key>
    <value>H:\ReleasePath1</value>
    <encrypted>False</encrypted>
  </item>
  <item>
    <key>HlrFtpPutCopyDir</key>
    <value>H:\ReleasePath2</value>
    <encrypted>False</encrypted>
  </item>
</Provisioning.Lib.Processing.XmlConfig>

因此,现在我们可以了解使用XmlPoke任务有多么容易.现在,让我们看一下如何扩展该示例,以在其他环境中管理对同一文件的更新.

So now we can see how easy it was to use the XmlPoke task. Let’s now take a look at how we can extend this example to manage updates to the same file for an additional environment.

由于我们创建了一个项目,该项目将保留所有必需的XPath以及新值,因此在管理多个环境方面具有更大的灵活性.在这种情况下,我们有一个要写入的文件,但是我们需要根据目标环境写出不同的值.这样做很容易.看看下面的UpdateXml02.proj的内容.

Since we’ve created an item which will keep all the needed XPath as well as the new values we have a bit more flexibility in managing multiple environments. In this scenario we have the same file that we want to write out, but we need to write out different values based on the target environment. Doing this is pretty easy. Take a look at the contents of UpdateXml02.proj below.

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="UpdateXml" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <PropertyGroup>
    <SourceXmlFile>$(MSBuildProjectDirectory)\sample.xml</SourceXmlFile>
    <DestXmlFiles>$(MSBuildProjectDirectory)\result.xml</DestXmlFiles>
  </PropertyGroup>

  <PropertyGroup>
    <!-- We can set a default value for TargetEnvName -->
    <TargetEnvName>Env01</TargetEnvName>
  </PropertyGroup>

  <ItemGroup Condition=" '$(TargetEnvName)' == 'Env01' ">
    <!-- Create an item which we can use to bundle all the transformations which are needed -->
    <XmlConfigUpdates Include="ConfigUpdates">
      <XPath>/Provisioning.Lib.Processing.XmlConfig/item[key='HlrFtpPutDir']/value</XPath>
      <NewValue>H:\ReleasePath1</NewValue>
    </XmlConfigUpdates>

    <XmlConfigUpdates Include="ConfigUpdates">
      <XPath>/Provisioning.Lib.Processing.XmlConfig/item[key='HlrFtpPutCopyDir']/value</XPath>
      <NewValue>H:\ReleasePath2</NewValue>
    </XmlConfigUpdates>
  </ItemGroup>

  <ItemGroup Condition=" '$(TargetEnvName)' == 'Env02' ">
    <!-- Create an item which we can use to bundle all the transformations which are needed -->
    <XmlConfigUpdates Include="ConfigUpdates">
      <XPath>/Provisioning.Lib.Processing.XmlConfig/item[key='HlrFtpPutDir']/value</XPath>
      <NewValue>G:\SomeOtherPlace\ReleasePath1</NewValue>
    </XmlConfigUpdates>

    <XmlConfigUpdates Include="ConfigUpdates">
      <XPath>/Provisioning.Lib.Processing.XmlConfig/item[key='HlrFtpPutCopyDir']/value</XPath>
      <NewValue>G:\SomeOtherPlace\ReleasePath2</NewValue>
    </XmlConfigUpdates>
  </ItemGroup>

  <Target Name="UpdateXml">
    <Message Text="Updating XML file at $(DestXmlFiles)" />
    <Copy SourceFiles="$(SourceXmlFile)"
          DestinationFiles="$(DestXmlFiles)" />
    <!-- Now let's execute all the XML transformations -->
    <XmlPoke XmlInputPath="$(DestXmlFiles)"
             Query="%(XmlConfigUpdates.XPath)"
             Value="%(XmlConfigUpdates.NewValue)"/>
  </Target>
</Project>

区别非常简单,我引入了一个新属性TargetEnvName,它使我们知道目标环境是什么. (注意:我只是组成了该属性名称,请使用您喜欢的任何名称).您还可以看到有两个ItemGroup元素包含不同的XmlConfigUpdate项.每个ItemGroup都有一个基于TargetEnvName值的条件,因此将仅使用两个ItemGroup值之一.现在,我们有一个MSBuild文件,其中包含两种环境的值.生成时,只需传入属性TargetEnvName,例如msbuild.\ UpdateXml02.proj/p:TargetEnvName = Env02.当我执行此操作时,结果文件包含:

The differences are pretty simple, I introduced a new property, TargetEnvName which lets us know what the target environment is. (note: I just made up that property name, use whatever name you like). Also you can see that there are two ItemGroup elements containing different XmlConfigUpdate items. Each ItemGroup has a condition based on the value of TargetEnvName so only one of the two ItemGroup values will be used. Now we have a single MSBuild file that has the values for both environments. When building just pass in the property TargetEnvName, for example msbuild .\UpdateXml02.proj /p:TargetEnvName=Env02. When I executed this the resulting file contains:

<Provisioning.Lib.Processing.XmlConfig instancetype="XmlConfig, Processing, Version=1.0.0.0, Culture=neutral">
  <item>
    <key>IsTestEnvironment</key>
    <value>True</value>
    <encrypted>False</encrypted>
  </item>
  <item>
    <key>HlrFtpPutDir</key>
    <value>G:\SomeOtherPlace\ReleasePath1</value>
    <encrypted>False</encrypted>
  </item>
  <item>
    <key>HlrFtpPutCopyDir</key>
    <value>G:\SomeOtherPlace\ReleasePath2</value>
    <encrypted>False</encrypted>
  </item>
</Provisioning.Lib.Processing.XmlConfig>

您可以看到文件已使用value元素中的不同路径更新.

You can see that the file has been updated with different paths in the value element.

如果您不使用MSBuild 4,则需要使用第三方任务库,例如MSBuild Extension Pack(资源链接).

If you are not using MSBuild 4 then you will need to use a third party task library like the MSBuild Extension Pack (link in resources).

希望有帮助.

资源

  • MSBuild batching: http://sedotech.com/Resources#Batching
  • SlowCheetah – XML Transforms extension: http://visualstudiogallery.msdn.microsoft.com/69023d00-a4f9-4a34-a6cd-7e854ba318b5
  • MSBuild Extension Pack (has a task to update XML files): http://msbuildextensionpack.codeplex.com/
  • Online XPath tester: http://www.whitebeam.org/library/guide/TechNotes/xpathtestbed.rhtm

这篇关于使用msbuild,我想使用teamcity中的值更新配置文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆