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

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

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


当前回答

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

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

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

其他回答

建议的解决方案将不工作时,类库配置文件引用从另一个项目(在我的情况下,它是Azure工作项目库)。它不会将正确转换后的文件从obj文件夹复制到bin\##configuration-name##文件夹。为了使它在最小的变化下工作,你需要将AfterCompile target改为BeforeCompile:

<Target Name="BeforeCompile" Condition="exists('app.$(Configuration).config')">

只是对现在到处张贴的解决方案做了一点改进:

<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />

也就是说,除非你打算永远使用当前的VS版本

你可以为每个配置使用一个单独的配置文件,例如app.Debug。config, app.Release.config,然后在项目文件中使用配置变量:

<PropertyGroup>
    <AppConfig>App.$(Configuration).config</AppConfig>
</PropertyGroup>

这将根据您正在构建的配置创建正确的ProjectName.exe.config文件。

注意:由于声誉,我不能评论bdeem的帖子。我将把我的发现作为答案发表出来。

根据bdeem的帖子,我做了以下(按顺序):

1. 我修改了[项目]。csproj文件。为不同的配置文件添加<Content Include="" />标签到ItemGroup,并使它们依赖于原始配置文件。

注意:使用<None Include="" />对转换无效。

<!-- App.config Settings -->
<!-- Create App.($Configuration).config files here. -->
<Content Include="App.config" />
<Content Include="App.Debug.config">
  <DependentUpon>App.config</DependentUpon>
</Content>
<Content Include="App.Release.config">
  <DependentUpon>App.config</DependentUpon>
</Content>

2. 在[项目]的底部。csproj文件(在关闭</Project>标记之前),我导入了${MSBuildToolsPath\Microsoft.CSharp。添加UsingTask来转换XML,并添加Target来将转换后的App.config文件复制到输出位置。

注意:Target还将覆盖本地目录中的App.Config,以查看本地工作的即时更改。Target还使用Name="Afterbuild"属性来确保在生成可执行文件之后可以转换配置文件。出于我不理解的原因,当使用WCF端点时,如果我使用Name="CoreCompile",我会得到关于服务属性的警告。Name="Afterbuild"解决了这个问题。

  <!-- Task to transform the App.config using the App.($Configuration).config file. -->
  <UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />

  <!-- Only compile the App.config if the App.($Configuration).config file exists. -->
  <!-- Make sure to use the AfterBuild name instead of CoreCompile to avoid first time build errors and WCF endpoint errors. -->
  <Target Name="AfterBuild" Condition="exists('App.$(Configuration).config')">
    <!-- Generate transformed App.config in the intermediate output directory -->    
    <TransformXml Source="App.config" Destination="$(IntermediateOutputPath)$(TargetFileName).config" Transform="App.$(Configuration).config" />
    
    <!-- Modify the original App.config file with the transformed version. -->
    <TransformXml Source="App.config" Destination="App.config" Transform="App.$(Configuration).config" />

    <!-- Force build process to use the transformed configuration file from now on. -->
    <ItemGroup>
      <AppConfigWithTargetPath Remove="App.config" />
      <AppConfigWithTargetPath Include="$(IntermediateOutputPath)$(TargetFileName).config">
        <TargetPath>$(TargetFileName).config</TargetPath>
      </AppConfigWithTargetPath>
    </ItemGroup>
  </Target>
</Project>

3.回到Visual Studio,重新加载修改过的文件。

4. 手动添加应用。配置文件到项目。这允许它们在原始App.config文件下进行分组。

注:确保App.*.;配置文件具有适当的XML结构。

<?xml version="1.0" encoding="utf-8"?>

<!-- For more information on using web.config transformation visit https://go.microsoft.com/fwlink/?LinkId=125889 -->

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <connectionStrings>
    <add name="myConn" connectionString=""; Initial Catalog=; User ID=; Password=;" xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
  </connectionStrings>
</configuration>

5. 重建项目。

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>