问题
Need some help with this MSBuild code.
I want to generate 4 app.config files with different settings and create 2 setup files for QA and production.
Each setup file will have 2 physical installations (Production lines).
So QA setup should include 2 app.configs with qa settings for production line 1 and 2, the same for production setup.
Here is a extract of the msbuild I have so far.
<ItemGroup>
<BuildEnvironment Include="QA">
<Server>qa-server</Server>
<BuildEnvironment/>
<BuildEnvironment Include="Prod">
<Server>prod-server</Server>
<BuildEnvironment/>
<Line Include="1">
<Setting>A</Setting>
</Line>
<Line Include="2">
<Setting>B</Setting>
</Line>
<ItemGroup>
<Target Name="PublishSetup" Inputs="@(BuildEnvironment)" Outputs="%(BuildEnvironment.Identity)">
<!-- Doesn't work at all -->
<ItemGroup>
<AppConfig Include="@(BuildEnvironment);@(Line)">
<Path>$(MyOutDir)\App.Config-%(Identity)</Path>
</AppConfig>
</ItemGroup>
<!-- Copy app.config to the four new files -->
<Copy SourceFiles="$(AppConfigFile)" DestinationFiles="%(AppConfig.Path)" />
<!-- Update each new app.config with XmlUpdate (community task), something like the following -->
<XmlUpdate XmlFileName="%(AppConfig.Path)" XPath=".." Value="%(AppConfig.Server)" />
<XmlUpdate XmlFileName="%(AppConfig.Path)" XPath=".." Value="%(AppConfig.Setting)" />
<!-- Build 2 setup.exe, one for qa and one prod using a Exec-task passing in qa and prod as command line argument -->
<Exec Command="setupcompiler.exe /d%(BuildEnvironment.Identity)" />
</Target>
The 4 resulting app.configs should be like this
app.config-QA-1
<connectionstring datasource="qa-server" ../>
<applicationSetting name="aName" value="A" />
app.config-QA-2
<connectionstring datasource="qa-server" ../>
<applicationSetting name="aName" value="B" />
app.config-Prod-1
<connectionstring datasource="prod-server" ../>
<applicationSetting name="aName" value="A" />
app.config-Prod-2
<connectionstring datasource="prod-server" ../>
<applicationSetting name="aName" value="B" />
回答1:
The idea is to first build a 'cross-product', an ItemGroup containing the 4 combinations. Can be done by combining @ and % for the two groups, as shown here. Then in a second step populate the ItemGroup with extra metadata based on existing metadata (adding metadata is just declaring the group again and adding metadata). It's a bit tricky here, because from Line you both want Identity and Setting - I don't know a nice msbuild way of doing this so I resorted to building a string with Identity|Setting, then splitting on the | later on.
<Target Name="PublishSetup">
<ItemGroup>
<AppConfig Include="@(BuildEnvironment)">
<Mod>%(Line.Identity)|%(Line.Setting)</Mod>
</AppConfig>
<AppConfig>
<Line>$([System.String]::Copy('%(Mod)').Split('|')[0])</Line>
<Setting>$([System.String]::Copy('%(Mod)').Split('|')[1])</Setting>
</AppConfig>
<AppConfig>
<Path>app.config-%(Identity)-%(Line)</Path>
</AppConfig>
</ItemGroup>
<Message Text="Path=%(AppConfig.Path) Server=%(AppConfig.Server) Setting=%(AppConfig.Setting)" />
</Target>
Output:
Path=app.config-QA-1 Server=qa-server Setting=A
Path=app.config-Prod-1 Server=prod-server Setting=A
Path=app.config-QA-2 Server=qa-server Setting=B
Path=app.config-Prod-2 Server=prod-server Setting=B
来源:https://stackoverflow.com/questions/37186867/msbuild-merge-item-groups