如何使用MSBuild的“afterbuild”任务来编辑.config文件?

4
我有一个目标项目中的.config文件,我需要通过MSBuild任务以编程方式向其中添加一行。
伪操作如下:
- 查找目标.config文件 - 确定新节点的属性值(例如“包”节点的“id”和“version”) - 在正确的父节点中插入新节点 - 保存更改 $TargetProjectDir\Config\packages.config中的.config文件:
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="ABC" version="1.1.0.4" />
  <package id="XYZ" version="2.0.0.0" />
</packages>

翻译后应该像这样:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="ABC" version="1.1.0.4" />
  <package id="XYZ" version="2.0.0.0" />
  <package id="CarDataWidget" version="3.0.0.0" />
</packages>

到目前为止,我考虑使用“内联任务”、“EXEC”任务和“XmlPoke”任务,但是还没有成功实现其中任何一个。
以下是我使用XmlPoke和XmlPeek的尝试:
我使用了以下文章作为如何向packages.config文件中添加节点的启示: http://weblogs.asp.net/bsimser/appending-nodes-in-xml-files-with-xmlpeek-and-xmlpoke-using-nant
  <Target Name="AfterBuild" DependsOnTargets="AddPackage">
  </Target>
  <Target Name="AddPackage">
    <!-- Load existing nodes into a Property -->
    <XmlPeek XmlInputPath="config/packages.config" Query="/packages/package" >
      <Output TaskParameter="Result" PropertyName="Peeked" />
    </XmlPeek>
    <Message Text="From Peek: $(Peeked)"></Message>

    <!-- Load new node into Property -->
    <PropertyGroup>
      <WidgetName>CarDataWidget</WidgetName>
      <WidgetVersion>2.0.0.0</WidgetVersion>
      <NewNode>&lt;package id&#61;&quot;$(WidgetName)&quot; version&#61;&quot;$(WidgetVersion)&quot; /&gt;</NewNode>

    <!-- Concatenate existing and new node into a Property -->
      <ConcatenatedNodes>$(Peeked)$(NewNode)</ConcatenatedNodes>
    </PropertyGroup>
    <Message Text="New pacakges: $(ConcatenatedNodes)"></Message>

    <!-- Replace existing nodes with concatenated nodes -->
    <XmlPoke Value="$(ConcatenatedNodes)" XmlInputPath="config/packages.config" Query="/packages">
    </XmlPoke>
  </Target>

上面构建的输出如下:
1>AddPackage:
1>  From Peek: <package id="ABC" version="1.1.0.4" />;<package id="XYZ" version="2.0.0.0" />
1>  New pacakges: <package id="ABC" version="1.1.0.4" />;<package id="XYZ" version="2.0.0.0" /><package id="CarDataWidget" version="2.0.0.0" />
1>  C:\_dev\CarDataWidget.csproj(184,14): 
    error MSB4094: "<package id="ABC" version="1.1.0.4" />;<package id="XYZ" version="2.0.0.0" /><package id="CarDataWidget" version="2.0.0.0" />" 
    is an invalid value for the "Value" parameter of the "XmlPoke" task. 
    Multiple items cannot be passed into a parameter of type "Microsoft.Build.Framework.ITaskItem".
1>
1>Build FAILED.

问题: 如何将内容添加到已有包节点的.config文件中?


2
好奇问一下:您是否考虑使用SlowCheetah扩展和简单的配置转换?http://visualstudiogallery.msdn.microsoft.com/69023d00-a4f9-4a34-a6cd-7e854ba318b5 如果您仍需要手动完成此操作(例如,如果基于简单配置的转换对您不起作用),则XmlPoke是一个可行的选择,但您应该共享用于XmlPoke使用尝试的代码,以便人们可以帮助您使其正常工作。 - Isantipov
4个回答

6

我曾经遇到同样的问题,我在这里找到了解决办法。

问题在于XmlPoke将分号视为值分隔符。

应该将这个进行替换:

<NewNode>&lt;package id&#61;&quot;$(WidgetName)&quot; version&#61;&quot;$(WidgetVersion)&quot; /&gt;</NewNode>

随着:

<NewNode>&lt%3Bpackage id&#61%3B&quot%3B$(WidgetName)&quot%3B version&#61%3&quot%3$(WidgetVersion)&quot%3 /&gt%3</NewNode>

必须将每个分号替换为序列%3B


1
这是对OP问题的解决方案 - 用%3B替换分号;可以解决此问题。 - Peter

3

以下是使用MSBuild Extension Pack实现的方法。

在NewPackage项目组中设置包和版本,它会将它们添加到XML文件中。

<Project 
    ToolsVersion="4.0" 
    xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <Import Project="$(MSBuildExtensionsPath)\ExtensionPack\4.0\MSBuild.ExtensionPack.tasks" />

  <Target Name="Test" DependsOnTargets="AddPackage">
  </Target>

  <ItemGroup>
    <NewPackage Include="CarDataWidget">
        <Version>3.0.0.0</Version>
    </NewPackage>
    <NewPackage Include="FooBarWidget">
        <Version>1.2.3.4</Version>
    </NewPackage>
  </ItemGroup>

  <Target Name="AddPackage">

    <PropertyGroup>
        <InputFile>in.xml</InputFile>
        <OutputFile>out.xml</OutputFile>
    </PropertyGroup>

    <Copy SourceFiles="$(InputFile)" DestinationFiles="$(OutputFile)" />

    <MSBuild.ExtensionPack.Xml.XmlFile
      TaskAction="AddElement"
      File="$(OutputFile)"
      XPath="//packages"
      Element="package"
      Key="id"
      Value="%(NewPackage.Identity)" />

    <MSBuild.ExtensionPack.Xml.XmlFile
      TaskAction="AddAttribute"
      File="$(OutputFile)"
      XPath="//packages/package[@id='%(NewPackage.Identity)']"
      Key="version"
      Value="%(NewPackage.Version)" />
  </Target>
</Project>

1

不希望唤醒旧线程。我有一个确切的情况,需要向web.config的appsettings部分添加新键。我从OP的代码开始,并陷入了相同的问题,即在查看的值中使用;阻止编写新的连接值。我通过使用Replace函数来删除;来解决了这个问题。

          <ConcatenatedNodes>$(Peeked)$(NewNode)</ConcatenatedNodes>          
          <!--in the concatenatednode, remove semicolon-->
          <ChangedPeek>$(ConcatenatedNodes.Replace(";",""))</ChangedPeek>
          <!-- Replace existing nodes with concatenated nodes-->
          <XmlPoke XmlInputPath="%(WebConfigFilesSolutionDir.FullPath)" Query="//appSettings" Value="$(ChangedPeek)" />

如何使用MSBuild在webconfig的appsetting部分添加新键的完整答案,请参考https://stackoverflow.com/a/56760009/6664129


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接