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

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

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


当前回答

我尝试了几种解决方案,下面是我个人发现的最简单的一个。 Dan在评论中指出,原来的帖子属于Oleg sych -谢谢,Oleg!

以下是使用说明:

1. 将每个配置的XML文件添加到项目中。

通常你会有调试和发布配置,所以把你的文件命名为App.Debug.config和App.Release.config。在我的项目中,我为每种环境创建了一个配置,所以您可能想尝试一下。

2. 卸载项目并打开.csproj文件进行编辑

Visual Studio允许您在编辑器中编辑.csproj文件——您只需要首先卸载项目。然后右键单击它并选择Edit <ProjectName>.csproj。

3.绑定程序。*。配置文件到主App.config

找到包含所有App.config和App.*的项目文件部分。配置引用。你会注意到它们的构建动作被设置为None,这是可以的:

<None Include="App.config" />
<None Include="App.Debug.config" />
<None Include="App.Release.config" />

接下来,让所有特定于配置的文件都依赖于主App.config,这样Visual Studio就可以像对设计器和代码隐藏文件一样对它们进行分组。

将上面的XML替换为下面的XML:

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

4. 激活转换魔法(对于VS2019等Visual Studio版本仍然是必要的)

在文件结束后

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

在期末考试之前

</Project>

插入以下XML——请注意,要进行正确的转换需要两个步骤:

  <UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
  <Target Name="BeforeBuild" Condition="Exists('App.$(Configuration).config')">
    <!-- Generate transformed app config and replace it: will get the <runtime> node and assembly bindings properly populated -->
    <TransformXml Source="App.config" Destination="App.config" Transform="App.$(Configuration).config" />
  </Target>
  <Target Name="AfterBuild" Condition="Exists('App.$(Configuration).config')">
    <!-- Generate transformed app config in the intermediate directory: this will transform sections such as appSettings -->
    <TransformXml Source="App.config" Destination="$(IntermediateOutputPath)$(TargetFileName).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>

现在你可以重新加载项目,构建它,享受App.config转换!

FYI

确保你的App.*。配置文件有如下正确的设置:

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
     <!--magic transformations here-->
</configuration>

其他回答

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

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

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

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

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

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

我尝试了几种解决方案,下面是我个人发现的最简单的一个。 Dan在评论中指出,原来的帖子属于Oleg sych -谢谢,Oleg!

以下是使用说明:

1. 将每个配置的XML文件添加到项目中。

通常你会有调试和发布配置,所以把你的文件命名为App.Debug.config和App.Release.config。在我的项目中,我为每种环境创建了一个配置,所以您可能想尝试一下。

2. 卸载项目并打开.csproj文件进行编辑

Visual Studio允许您在编辑器中编辑.csproj文件——您只需要首先卸载项目。然后右键单击它并选择Edit <ProjectName>.csproj。

3.绑定程序。*。配置文件到主App.config

找到包含所有App.config和App.*的项目文件部分。配置引用。你会注意到它们的构建动作被设置为None,这是可以的:

<None Include="App.config" />
<None Include="App.Debug.config" />
<None Include="App.Release.config" />

接下来,让所有特定于配置的文件都依赖于主App.config,这样Visual Studio就可以像对设计器和代码隐藏文件一样对它们进行分组。

将上面的XML替换为下面的XML:

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

4. 激活转换魔法(对于VS2019等Visual Studio版本仍然是必要的)

在文件结束后

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

在期末考试之前

</Project>

插入以下XML——请注意,要进行正确的转换需要两个步骤:

  <UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
  <Target Name="BeforeBuild" Condition="Exists('App.$(Configuration).config')">
    <!-- Generate transformed app config and replace it: will get the <runtime> node and assembly bindings properly populated -->
    <TransformXml Source="App.config" Destination="App.config" Transform="App.$(Configuration).config" />
  </Target>
  <Target Name="AfterBuild" Condition="Exists('App.$(Configuration).config')">
    <!-- Generate transformed app config in the intermediate directory: this will transform sections such as appSettings -->
    <TransformXml Source="App.config" Destination="$(IntermediateOutputPath)$(TargetFileName).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>

现在你可以重新加载项目,构建它,享受App.config转换!

FYI

确保你的App.*。配置文件有如下正确的设置:

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
     <!--magic transformations here-->
</configuration>

注意:由于声誉,我不能评论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. 重建项目。

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

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