为 3 个不同的环境转换 app.config

Posted

技术标签:

【中文标题】为 3 个不同的环境转换 app.config【英文标题】:Transform app.config for 3 different environment 【发布时间】:2014-01-08 12:55:13 【问题描述】:

我需要能够使用 msbuild 转换我的 app.config 文件。如果文件名为 app.DEBUG.config 或 app.Release.config,我可以转换文件,但如果我添加一个名为 app.PROD.config 的文件,则不能。

如果我选择不同的 PublishProfile,使用常规 XDT 转换 msbuild 会识别不同的 web.config 文件

 msbuild path.to.project.csproj Configuration=Release PublishProfile=DEV

显然 app.config 不适用于相同的设置。我总是可以为 DEV.config 设置创建特定的构建配置,但为一个应用程序单独构建确认似乎没用。这样做的一个 hacky 方法是在每个环境 POST-BUILD 中复制正确的 app.config。

我尝试使用 SlowCheetah 插件,但这似乎只转换默认的 DEBUG 和 RELEASE 配置文件,这是不合适的,因为我有两个以上的环境。如果我确实使用了这个错误,请让我知道我应该将什么参数传递给 msbuild 以选择我的 app.DEV.config。

预期结果是 msbuild 将根据自定义的名为 app.DEV.config 的转换或为 app.PROD.config 自定义的转换来转换 app.config。我希望有一个参数可以传递给 msbuild,它允许我使用 Release 配置,但每个环境使用不同名称的转换。

【问题讨论】:

【参考方案1】:

这是我在这个场景中使用的:

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

  <!-- This target will run right before you run your app in Visual Studio -->
  <Target Name="UpdateWebConfigBeforeRun" BeforeTargets="Build">
    <Message Text="Configuration: $(Configuration) update from web.template.$(Configuration).config"/>
    <TransformXml Source="web.template.config"
              Transform="web.template.$(Configuration).config"
              Destination="web.config" />
    </Target>

  <!-- Exclude the config template files from the created package -->
  <Target Name="ExcludeCustomConfigTransformFiles" BeforeTargets="ExcludeFilesFromPackage">
    <ItemGroup>
      <ExcludeFromPackageFiles Include="web.template.config;web.template.*.config"/>
    </ItemGroup>
    <Message Text="ExcludeFromPackageFiles: @(ExcludeFromPackageFiles)" Importance="high"/>
  </Target>
</Project>

我有以下设置:

web.template.config
    - web.template.debug.config
    - web.template.production.config
    - web.template.release.config etc

应该可以跨电脑工作,不需要额外的插件等。在你的场景中,你需要编辑内容说app.而不是web.

【讨论】:

它的工作方式应该是首先在 web.template.config 之上转换 Release,然后在其之上转换 Production。这就是你的构建文件的作用吗? 我必须在项目文件中包含正常的 Web 应用程序导入,并且我必须将 Condition 设置为 true,然后才能使用 &lt;Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.targets" Condition="true" /&gt;(请参阅 @Nirav Mehta 对其他导入的回答) 【参考方案2】:

我认为令人困惑的是,我们有能力进行编译时配置转换,然后我们有部署时配置转换

通常,您使用编译时配置转换来更改本地默认配置文件,以便它适合 DEBUG 或 RELEASE 配置(或您定义的任何自定义配置)。对于 web.config,工具是内置的。对于 app.config,SlowCheetah Visual Studio extension 为 app.config 带来了与 web.config 相同的功能。 RELEASE 配置的配置转换示例是删除 system.web 编译时的 debug 属性。

部署时配置转换是在部署到特定环境(例如 QA、PROD)时对配置文件的操作。数据库连接字符串需要更改、服务端点更改等...对于 web.config,MSDEPLOY 是首选的 IIS 工具。对于 app.config,我们似乎需要依赖安装程序技术。为此有不同的工具,例如WIX。

无论如何,我希望对编译时和部署时配置转换之间区别的简短解释有助于解释为什么工具集是碎片化的。更深入的分析可以参考我在这个主题上的一篇博文:http://philippetruche.wordpress.com/2012/07/11/deploying-web-applications-to-multiple-environments-using-microsoft-web-deploy/

如果选择使用 WIX 工具集生成安装程序,请参阅 Creating Multi-Environment Windows Installers with Visual Studio 2012 and Wix。

【讨论】:

【参考方案3】:

App.config 转换

要测试转换是否有效,您必须使用真正的转换。带有 appSettings 块的插入转换可能是最简单的一种。我使用以下配置文件进行了测试。

App.config:

<?xml version="1.0" encoding="utf-8" ?><configuration>  <appSettings>    <add key="FirstName" value="Gunnar"/>  </appSettings></configuration>

App.Release.config

<?xml version="1.0"?><configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">  <appSettings>    <add key="LastName" value="Peipman" xdt:Transform="Insert"/>  </appSettings></configuration>

改造后的配置文件:

<?xml version="1.0" encoding="utf-8" ?><configuration>  <appSettings>    <add key="FirstName" value="Gunnar"/>    <add key="LastName" value="Peipman"/>  </appSettings></configuration>

使 App.config 转换工作

让我们看看如何使用控制台应用程序来做到这一点。

    将 App.config 和 App.Release.config 添加到您的项目中,并用上面给出的内容填充它们.. 卸载控制台应用程序项目。 右键单击项目名称并选择“编辑”。 项目文件作为 XML 文件打开,你可以看到里面有什么 它。

    在第一个属性组的结束标记之前添加以下行:

    <ProjectConfigFileName>App.Config</ProjectConfigFileName>
    

    找到定义 App.Config 的&lt;ItemGroup&gt; (<None Include="App.Config" />) 并在后面添加以下块 App.Config 节点:

    <None Include="App.Release.config"> 
        <DependentUpon>App.Config</DependentUpon>
    </None>
    

    找到第一个 &lt;Import Project= 节点并将以下导入添加为 最后一个列出:

    <Import Project="$(VSToolsPath)\Web\Microsoft.Web.Publishing.targets" Condition="'$(VSToolsPath)' != ''" />
    <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.targets" Condition="false" />
    

    到文件末尾,标签之前,粘贴以下内容 代码块:

    <UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
    <Target Name="AfterCompile" Condition="exists('app.$(Configuration).config')">
      <TransformXml Source="app.config" Destination="$(IntermediateOutputPath)$(TargetFileName).config" Transform="app.$(Configuration).config" />
      <ItemGroup>
        <AppConfigWithTargetPath Remove="app.config" />
        <AppConfigWithTargetPath Include="$(IntermediateOutputPath)$(TargetFileName).config">
          <TargetPath>$(TargetFileName).config</TargetPath>
        </AppConfigWithTargetPath>
        <AppConfigWithTargetPath Include="$(IntermediateOutputPath)$(TargetFileName).config">
          <TargetPath>$(TargetName).vshost$(TargetExt).config</TargetPath>
        </AppConfigWithTargetPath>
      </ItemGroup>
    </Target>
    

    保存项目文件,关闭并重新加载。

当再次加载项目时,Visual Studio 可能会询问您对文件的一些修改,因此从 Visual Studio 2010 到当前的所有版本都可以使用您的项目文件而无需对其进行修改。同意它,因为这样您就不会依赖于 Visual Studio 版本。

【讨论】:

今天仍然有效吗?还是 vs2015.3 能正确处理这个问题? 我上周只在 VS 2015 中做了这个,它对我有用 转换语法的参考,感兴趣的人可以参考:msdn.microsoft.com/library/dd465326.aspx 这个答案是从哪里偷来的,任何人都想知道。 gunnarpeipman.com/…Dude 甚至无法稍微改变措辞。【参考方案4】:

您可以像转换 web.config 一样转换 app.config。 使用位于此处的这个 nuget 包https://github.com/acottais/msbuild.xdt

还有其他几个 Nuget 包可以让您执行此操作。我前几天用过这个,效果很好。

安装后就像在 VS 窗口中添加转换一样简单。

【讨论】:

以上是关于为 3 个不同的环境转换 app.config的主要内容,如果未能解决你的问题,请参考以下文章

C#项目 App.config 配置文件不同使用环境配置

将 RGB 图像转换为 3 个 HSI 输出

在 C# 中将 3 个字节转换为有符号整数

如何在SQL Server 2012中的10个不同节点中转换此字符串?

在页面js 中,怎么将中文字符串转换成2个字节长度16进制数;并在js 环境下解码16进

需要使用一个 AWS CloudFormation 模板为不同的环境启动多个实例