对于Visual Studio 2010基于Web的应用程序,我们有配置转换功能,通过它我们可以为不同的环境维护多个配置文件。但同样的功能不适用于Windows服务/WinForms或控制台应用程序的App.Config文件。

这里有一个可用的解决方案:对App.Config应用XDT魔术。

然而,这并不简单,需要一些步骤。是否有更简单的方法来实现同样的app.config文件?


当前回答

So I ended up taking a slightly different approach. I followed Dan's steps through step 3, but added another file: App.Base.Config. This file contains the configuration settings you want in every generated App.Config. Then I use BeforeBuild (with Yuri's addition to TransformXml) to transform the current configuration with the Base config into the App.config. The build process then uses the transformed App.config as normal. However, one annoyance is you kind of want to exclude the ever-changing App.config from source control afterwards, but the other config files are now dependent upon it.

  <UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
  <Target Name="BeforeBuild" Condition="exists('app.$(Configuration).config')">
    <TransformXml Source="App.Base.config" Transform="App.$(Configuration).config" Destination="App.config" />
  </Target>

其他回答

我写了一个很好的扩展来自动化app.config转换,就像在Web应用程序项目配置转换中构建的那样

这个扩展的最大优势是,你不需要在所有的构建机器上安装它

So I ended up taking a slightly different approach. I followed Dan's steps through step 3, but added another file: App.Base.Config. This file contains the configuration settings you want in every generated App.Config. Then I use BeforeBuild (with Yuri's addition to TransformXml) to transform the current configuration with the Base config into the App.config. The build process then uses the transformed App.config as normal. However, one annoyance is you kind of want to exclude the ever-changing App.config from source control afterwards, but the other config files are now dependent upon it.

  <UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
  <Target Name="BeforeBuild" Condition="exists('app.$(Configuration).config')">
    <TransformXml Source="App.Base.config" Transform="App.$(Configuration).config" Destination="App.config" />
  </Target>

我发现的另一个解决方案是不使用转换,而只是有一个单独的配置文件,例如app.Release.config。然后将这一行添加到csproj文件中。

  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
    <AppConfig>App.Release.config</AppConfig>
  </PropertyGroup>

这不仅会生成正确的myprogram.exe.config文件,而且如果你在Visual Studio中使用安装和部署项目来生成MSI,它会强制部署项目在打包时使用正确的配置文件。

根据我的经验,我需要使环境特定的东西是像连接字符串、appsettings和通常的smpt设置。配置系统允许在单独的文件中指定这些内容。所以你可以在app.config/web.config中使用这个:

 <appSettings configSource="appsettings.config" />
 <connectionStrings configSource="connection.config" />
 <system.net>
    <mailSettings>
       <smtp configSource="smtp.config"/>
    </mailSettings>
 </system.net>

我通常所做的是将这些特定于配置的部分放在单独的文件中,放在名为ConfigFiles的子文件夹中(取决于是在解决方案根目录中还是在项目级别中)。我为每个配置定义一个文件,例如smtp.config.Debug和smtp.config.Release。

然后你可以像这样定义一个预构建事件:

copy $(ProjectDir)ConfigFiles\smtp.config.$(ConfigurationName) $(TargetDir)smtp.config

在团队开发中,您可以通过在约定中包含%COMPUTERNAME%和/或%USERNAME%来进一步调整。

当然,这意味着目标文件(x.config)不应该放在源代码控制中(因为它们是生成的)。你仍然应该将它们添加到项目文件中,并将它们的输出类型属性设置为“始终复制”或“如果更新则复制”。

简单,可扩展,适用于所有类型的Visual Studio项目(控制台,winforms, wpf, web)。

这是@bdeem使用Visual Studio 2019年和2022年回答的另一个变体。我的问题是,使用这个解决方案,App.config会被覆盖,因为它在源代码控制中,这不是一个真正的选项。

我的解决方案是将配置文件直接转换到输出目录中。

  <UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
  <Target Name="AfterBuild" Condition="Exists('App.$(Configuration).config')">
    <!-- Generate transformed app config to the output directory -->
    <TransformXml Source="App.config" Destination="$(OutDir)\$(TargetFileName).config" Transform="App.$(Configuration).config" />
  </Target>

它还有一个额外的好处,就是比原来的解决方案要短得多。