如何使用MSBuild';后建';要编辑.config文件的任务?

如何使用MSBuild';后建';要编辑.config文件的任务?,msbuild,msbuild-task,xmlpoke,Msbuild,Msbuild Task,Xmlpoke,我在目标项目中有一个.config,需要通过MSBuild任务以编程方式向其添加一行 PSEDOO操作,如: 查找目标.config文件 确定新节点的属性值(例如,“包”节点的“id”和“版本”) 在正确的父节点中插入新节点 保存更改 $TargetProjectDir\config\packages.config中的.config文件: <?xml version="1.0" encoding="utf-8"?> <packages> <package i

我在目标项目中有一个.config,需要通过MSBuild任务以编程方式向其添加一行

PSEDOO操作,如:

  • 查找目标.config文件
  • 确定新节点的属性值(例如,“包”节点的“id”和“版本”)
  • 在正确的父节点中插入新节点
  • 保存更改
$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文件,我使用了以下文章作为灵感:


卡片小部件
2.0.0.0
包id=;“$(WidgetName)”版本=;“$(WidgetVersion)”/
$(偷看)$(新节点)
上述构建的输出为:

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.
1>添加包:
1> 来自Peek:;
1> 新包装:;
1> C:\\u dev\CarDataWidget.csproj(184,14):
错误MSB4094:“;”
是“XmlPoke”任务的“value”参数的无效值。
无法将多个项传递到类型为“Microsoft.Build.Framework.ITaskItem”的参数中。
1>
1> 生成失败。
问题:
如何使用现有的包节点将其添加到.config文件中?

下面是一种使用的方法

在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>

3.0.0.0
1.2.3.4
in.xml
out.xml

看看我的博客文章,其中比较了以下方法

  • 使用SlowCheetah为您转换文件
  • 直接使用TransformXml任务
  • 使用内置(MSBuild 4.0)XmlPoke任务
  • 使用第三方任务库

  • 我也有同样的问题。我找到了解决办法

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

    应取代这一点:

    <NewNode>&lt;package id&#61;&quot;$(WidgetName)&quot; version&#61;&quot;$(WidgetVersion)&quot; /&gt;</NewNode>
    
    package-id=;“$(WidgetName)”版本=;“$(WidgetVersion)”/
    
    与:

    “lt%3B包id=%3B"%3B$(WidgetName)"%3B版本=%3"%3$(WidgetVersion)"%3/>%3”
    

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

    而不希望唤醒旧线程。我有一个确切的场景,那就是我必须向web.config的appsettings部分添加新键。我从OPs代码开始,也遇到了同样的问题;在Peek值中,阻止写入新的连接值。我用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部分添加新键的完整答案,请参阅

    好奇的是:您是否考虑过使用SlowCheetah扩展和简单配置转换?如果您仍然需要手动执行此操作(例如,如果简单的基于配置的转换不适合您),XmlPoke是一个可行的选项,但您可能应该为XmlPoke的使用尝试共享您的代码,以便Peppe可以帮助您使其工作。这是OPs问题的解决方案-替换分号;使用%3B修复了该问题
    <NewNode>&lt%3Bpackage id&#61%3B&quot%3B$(WidgetName)&quot%3B version&#61%3&quot%3$(WidgetVersion)&quot%3 /&gt%3</NewNode>
    
              <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)" />