Visual Studio 中非 Web 项目的项目的 App.Config 转换?

发布于 2024-09-04 10:57:39 字数 348 浏览 15 评论 0 原文

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

这里建议有一个解决方法: Applying XDT magic to应用程序配置

但这并不简单,需要执行许多步骤。有没有更简单的方法可以对 app.config 文件实现相同的效果?

For Visual Studio 2010 Web based application we have Config Transformation features by which we can maintain multiple configuration files for different environments. But the same feature is not available for App.Config files for Windows Services/WinForms or Console Application.

There is a workaround available as suggested here: Applying XDT magic to App.Config.

However it is not straightforward and requires a number of steps. Is there an easier way to achieve the same for app.config files?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(16

泛滥成性 2024-09-11 10:57:39

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

以下是说明:

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

通常,您将具有 DebugRelease 配置,因此将文件命名为 App.Debug.config< /code> 和 App.Release.config。在我的项目中,我为每种环境创建了一个配置,因此您可能想尝试一下。

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

Visual Studio 允许您直接在编辑器中编辑 .csproj 文件 - 您只需先卸载项目即可。然后右键单击它并选择编辑.csproj

3.将 App.*.config 文件绑定到主 App.config

查找包含所有 App.configApp.*.config 引用的项目文件部分。您会注意到它们的构建操作设置为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 转换!

仅供参考

确保您的 App.*.config 文件具有正确的设置,如下所示:

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

I tried several solutions and here is the simplest I personally found.
Dan pointed out in the comments that the original post belongs to Oleg Sychthanks, Oleg!

Here are the instructions:

1. Add an XML file for each configuration to the project.

Typically you will have Debug and Release configurations so name your files App.Debug.config and App.Release.config. In my project, I created a configuration for each kind of environment, so you might want to experiment with that.

2. Unload project and open .csproj file for editing

Visual Studio allows you to edit .csproj files right in the editor—you just need to unload the project first. Then right-click on it and select Edit <ProjectName>.csproj.

3. Bind App.*.config files to main App.config

Find the project file section that contains all App.config and App.*.config references. You'll notice their build actions are set to None and that's okay:

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

Next, make all configuration-specific files dependant on the main App.config so Visual Studio groups them like it does designer and code-behind files.

Replace XML above with the one below:

<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. Activate transformations magic (still necessary for Visual Studio versions such as VS2019)

In the end of file after

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

and before final

</Project>

insert the following XML -- please note there are two steps for the proper transformation to occur:

  <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>

Now you can reload the project, build it and enjoy App.config transformations!

FYI

Make sure that your App.*.config files have the right setup like this:

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
     <!--magic transformations here-->
</configuration>
夏至、离别 2024-09-11 10:57:39

现在,这适用于本文中处理的 Visual Studio 插件:SlowCheetah - Web.config 转换语法现在通用为任何 XML 配置文件

您可以右键单击您的 web.config,然后单击“添加配置”
转换。”当你这样做时,你会得到一个 web.debug.config 和一个
web.release.config。如果你愿意,你可以制作一个 web.whatever.config,如下
只要名称与配置文件一致即可。这些文件
只是您想要进行的更改,而不是您的完整副本
网络配置。

您可能认为您想要使用 XSLT 来转换 web.config,但是
虽然他们直觉上感觉正确,但实际上非常冗长。

这里有两种转换,一种使用 XSLT,另一种使用 XML
文档转换语法/命名空间。就像所有的事情一样
XSLT 中有多种方法可以做到这一点,但您已经了解了总体思路。 XSLT
是一种广义的树转换语言,而此部署
其中一个针对常见场景的特定子集进行了优化。但是,
很酷的一点是每个 XDT 转换都是一个 .NET 插件,因此您可以
你自己的。




             
    
  


  
    
    
      NewSetting
      新设置值
    
  


或者通过部署转换实现相同的效果:

<配置 xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
   <应用程序设置>
      
   

This works now with the Visual Studio AddIn treated in this article: SlowCheetah - Web.config Transformation Syntax now generalized for any XML configuration file.

You can right-click on your web.config and click "Add Config
Transforms." When you do this, you'll get a web.debug.config and a
web.release.config. You can make a web.whatever.config if you like, as
long as the name lines up with a configuration profile. These files
are just the changes you want made, not a complete copy of your
web.config.

You might think you'd want to use XSLT to transform a web.config, but
while they feels intuitively right it's actually very verbose.

Here's two transforms, one using XSLT and the same one using the XML
Document Transform syntax/namespace. As with all things there's
multiple ways in XSLT to do this, but you get the general idea. XSLT
is a generalized tree transformation language, while this deployment
one is optimized for a specific subset of common scenarios. But, the
cool part is that each XDT transform is a .NET plugin, so you can make
your own.

<?xml version="1.0" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="@*|node()">
  <xsl:copy>           
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>
<xsl:template match="/configuration/appSettings">
  <xsl:copy>
    <xsl:apply-templates select="node()|@*"/>
    <xsl:element name="add">
      <xsl:attribute name="key">NewSetting</xsl:attribute>
      <xsl:attribute name="value">New Setting Value</xsl:attribute>
    </xsl:element>
  </xsl:copy>
</xsl:template>
</xsl:stylesheet>

Or the same thing via the deployment transform:

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
   <appSettings>
      <add name="NewSetting" value="New Setting Value" xdt:Transform="Insert"/>
   </appSettings>
</configuration>
Spring初心 2024-09-11 10:57:39

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

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

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

Another solution I've found is NOT to use the transformations but just have a separate config file, e.g. app.Release.config. Then add this line to your csproj file.

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

This will not only generate the right myprogram.exe.config file but if you're using Setup and Deployment Project in Visual Studio to generate MSI, it'll force the deployment project to use the correct config file when packaging.

无声情话 2024-09-11 10:57:39

受到 Oleg 和其他人在这个问题中的启发,我采取了解决方案< a href="https://stackoverflow.com/a/5109530/2286801">https://stackoverflow.com/a/5109530/2286801 进一步启用以下功能。

  • 适用于 ClickOnce
  • 适用于 VS 2010 中的安装和部署项目
  • 适用于 VS2010、2013、2015(未测试 2012,尽管应该也可以)。
  • 与团队构建一起使用。 (您必须安装 A)Visual Studio 或 B)Microsoft.Web.Publishing.targets 和 Microsoft.Web.Publishing.Tasks.dll)

此解决方案的工作原理是在第一次引用 app.config 之前执行 app.config 转换MSBuild 进程中的时间。它使用外部目标文件来更轻松地跨多个项目进行管理。

说明:

与其他解决方案类似的步骤。我引用了保持不变的内容,并将其包含在内,以保持完整性和更容易进行比较。

<强>0。将一个名为 AppConfigTransformation.targets 的新文件添加到您的项目中

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!-- Transform the app config per project configuration.-->
  <PropertyGroup>
    <!-- This ensures compatibility across multiple versions of Visual Studio when using a solution file.
         However, when using MSBuild directly you may need to override this property to 11.0 or 12.0 
         accordingly as part of the MSBuild script, ie /p:VisualStudioVersion=11.0;
         See http://blogs.msdn.com/b/webdev/archive/2012/08/22/visual-studio-project-compatability-and-visualstudioversion.aspx -->
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
  </PropertyGroup>

  <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.targets" />

  <Target Name="SetTransformAppConfigDestination" BeforeTargets="PrepareForBuild" 
          Condition="exists('app.$(Configuration).config')">
    <PropertyGroup>
      <!-- Force build process to use the transformed configuration file from now on. -->
      <AppConfig>$(IntermediateOutputPath)$(TargetFileName).config</AppConfig>
    </PropertyGroup>
    <Message Text="AppConfig transformation destination: = $(AppConfig)" />
  </Target>

  <!-- Transform the app.config after the prepare for build completes. -->
  <Target Name="TransformAppConfig" AfterTargets="PrepareForBuild" Condition="exists('app.$(Configuration).config')">
    <!-- Generate transformed app config in the intermediate directory -->
    <TransformXml Source="app.config" Destination="$(AppConfig)" Transform="app.$(Configuration).config" />
  </Target>

</Project>

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

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

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

Visual Studio 允许您直接在编辑器中编辑 .csproj - 您只需先卸载项目即可。然后右键单击它并选择编辑 .csproj。

3.将 App.*.config 文件绑定到主 App.config

找到包含所有 App.config 和 App.*.config 引用的项目文件部分,并按如下方式替换。您会注意到我们使用 None 而不是 Content。

<ItemGroup>
  <None Include="app.config"/>
  <None Include="app.Production.config">
    <DependentUpon>app.config</DependentUpon>
  </None>
  <None Include="app.QA.config">
    <DependentUpon>app.config</DependentUpon>
  </None>
  <None Include="app.Development.config">
    <DependentUpon>app.config</DependentUpon>
  </None>
</ItemGroup>

<强>4。激活变形魔法

在文件末尾之后

<导入项目="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

决赛前


以下 XML:

<Import Project="AppConfigTransformation.targets" />

完成!

Inspired by Oleg and others in this question, I took the solution https://stackoverflow.com/a/5109530/2286801 a step further to enable the following.

  • Works with ClickOnce
  • Works with Setup and Deployment projects in VS 2010
  • Works with VS2010, 2013, 2015 (didn't test 2012 although should work as well).
  • Works with Team Build. (You must install either A) Visual Studio or B) Microsoft.Web.Publishing.targets and Microsoft.Web.Publishing.Tasks.dll)

This solution works by performing the app.config transformation before the app.config is referenced for the first time in the MSBuild process. It uses an external targets file for easier management across multiple projects.

Instructions:

Similar steps to the other solution. I've quoted what remains the same and included it for completeness and easier comparison.

0. Add a new file to your project called AppConfigTransformation.targets

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!-- Transform the app config per project configuration.-->
  <PropertyGroup>
    <!-- This ensures compatibility across multiple versions of Visual Studio when using a solution file.
         However, when using MSBuild directly you may need to override this property to 11.0 or 12.0 
         accordingly as part of the MSBuild script, ie /p:VisualStudioVersion=11.0;
         See http://blogs.msdn.com/b/webdev/archive/2012/08/22/visual-studio-project-compatability-and-visualstudioversion.aspx -->
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
  </PropertyGroup>

  <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.targets" />

  <Target Name="SetTransformAppConfigDestination" BeforeTargets="PrepareForBuild" 
          Condition="exists('app.$(Configuration).config')">
    <PropertyGroup>
      <!-- Force build process to use the transformed configuration file from now on. -->
      <AppConfig>$(IntermediateOutputPath)$(TargetFileName).config</AppConfig>
    </PropertyGroup>
    <Message Text="AppConfig transformation destination: = $(AppConfig)" />
  </Target>

  <!-- Transform the app.config after the prepare for build completes. -->
  <Target Name="TransformAppConfig" AfterTargets="PrepareForBuild" Condition="exists('app.$(Configuration).config')">
    <!-- Generate transformed app config in the intermediate directory -->
    <TransformXml Source="app.config" Destination="$(AppConfig)" Transform="app.$(Configuration).config" />
  </Target>

</Project>

1. Add an XML file for each configuration to the project.

Typically you will have Debug and Release configurations so name your files App.Debug.config and App.Release.config. In my project, I created a configuration for each kind of enironment so you might want to experiment with that.

2. Unload project and open .csproj file for editing

Visual Studio allows you to edit .csproj right in the editor—you just need to unload the project first. Then right-click on it and select Edit .csproj.

3. Bind App.*.config files to main App.config

Find the project file section that contains all App.config and App.*.config references and replace as follows. You'll notice we use None instead of Content.

<ItemGroup>
  <None Include="app.config"/>
  <None Include="app.Production.config">
    <DependentUpon>app.config</DependentUpon>
  </None>
  <None Include="app.QA.config">
    <DependentUpon>app.config</DependentUpon>
  </None>
  <None Include="app.Development.config">
    <DependentUpon>app.config</DependentUpon>
  </None>
</ItemGroup>

4. Activate transformations magic

In the end of file after

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

and before final

</Project>

insert the following XML:

<Import Project="AppConfigTransformation.targets" />

Done!

不一样的天空 2024-09-11 10:57:39

根据我的经验,我需要针对特定​​环境进行设置,例如连接字符串、应用程序设置以及通常的 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)。

In my experience, the things I need to make environment-specific are things like connection strings, appsettings and often smpt settings. The config system allows to specify these things in separate files. So you can use this in your app.config/web.config:

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

What I typically do is to put these config-specific sections in separate files, in a subfolder called ConfigFiles (either in the solution root or at the project level, depends). I define a file per configuration, e.g. smtp.config.Debug and smtp.config.Release.

Then you can define a pre-build event like so:

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

In team development, you can tweak this further by including the %COMPUTERNAME% and/or %USERNAME% in the convention.

Of course, this implies that the target files (x.config) should NOT be put in source control (since they are generated). You should still add them to the project file and set their output type property to 'copy always' or 'copy if newer' though.

Simple, extensible, and it works for all types of Visual Studio projects (console, winforms, wpf, web).

夜司空 2024-09-11 10:57:39

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

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

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

You can use a separate config file per configuration, e.g. app.Debug.config, app.Release.config and then use the configuration variable in your project file:

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

This will then create the correct ProjectName.exe.config file depending on the configuration you are building in.

我不吻晚风 2024-09-11 10:57:39

我编写了一个很好的扩展来自动执行 app.config 转换,就像 Web 应用程序项目中内置的扩展 Configuration Transform

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

I wrote nice extension to automate app.config transformation like the one built in Web Application Project Configuration Transform

The biggest advantage of this extension is that you don’t need to install it on all build machines

漫雪独思 2024-09-11 10:57:39

从 Marketplace 在 Visual Studio 中安装“配置转换工具”并重新启动 VS。您还可以看到 app.config 的菜单预览转换。

https://marketplace.visualstudio.com/items?itemName=GolanAvraham.ConfigurationTransform

Install "Configuration Transform Tool" in Visual Studio from Marketplace and restart VS. You will be able to see menu preview transform for app.config as well.

https://marketplace.visualstudio.com/items?itemName=GolanAvraham.ConfigurationTransform

歌枕肩 2024-09-11 10:57:39

只是对现在似乎随处发布的解决方案进行了一点改进:

<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
  • 也就是说,除非您打算永远使用当前的 VS 版本

Just a little improvement to the solution that seems to be posted everywhere now:

<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
  • that is, unless you are planning to stay with your current VS version forever
断爱 2024-09-11 10:57:39

所以我最终采取了稍微不同的方法。我按照 Dan 的步骤完成第 3 步,但添加了另一个文件:App.Base.Config。该文件包含您在每个生成的 App.Config 中所需的配置设置。然后我使用 BeforeBuild(Yuri 添加到 TransformXml)将当前配置与 Base 配置转换为 App.config。然后,构建过程会正常使用转换后的 App.config。然而,一个烦恼是您想随后将不断变化的 App.config 从源代码管理中排除,但其他配置文件现在依赖于它。

  <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>

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>
江城子 2024-09-11 10:57:39

@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>

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

Yet another variation on @bdeem's answer using Visual Studio 2019 and 2022. My issue was that using that solution, App.config was getting overwritten, and since it's in source control that's not really an option.

The solution for me was to transform the config file directly into the output directory.

  <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>

It has the added benefit of being quite a bit shorter than the original solution.

善良天后 2024-09-11 10:57:39

我创建了 Vishal Joshi 发布的另一种替代方案,其中删除了将构建操作更改为 内容 的要求,并且还实现了对 ClickOnce 部署的基本支持。我说基本,因为我没有彻底测试它,但它应该可以在典型的 ClickOnce 部署场景中工作。

该解决方案由单个 MSBuild 项目组成,一旦导入到现有的 Windows 应用程序项目 (*.csproj),该项目就会扩展构建过程以考虑 app.config 转换。

您可以在 Visual 阅读更详细的说明Studio App.config XML 转换和 MSBuild 项目文件可以从 GitHub 下载

I have created another alternative to the one posted by Vishal Joshi where the requirement to change the build action to Content is removed and also implemented basic support for ClickOnce deployment. I say basic, because I didn't test it thoroughly but it should work in the typical ClickOnce deployment scenario.

The solution consists of a single MSBuild project that once imported to an existent windows application project (*.csproj) extends the build process to contemplate app.config transformation.

You can read a more detailed explanation at Visual Studio App.config XML Transformation and the MSBuild project file can be downloaded from GitHub.

倒带 2024-09-11 10:57:39

如果您使用TFS在线版(云版),并且想要改造项目中的App.Config,您可以执行以下操作,而无需安装任何额外的工具。
来自 VS =>卸载项目=>编辑项目文件=>转到文件底部并添加以下内容:

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

AssemblyFile 和 Destination 适用于本地使用和 TFS 在线(云)服务器。

If you use a TFS online(Cloud version) and you want to transform the App.Config in a project, you can do the following without installing any extra tools.
From VS => Unload the project => Edit project file => Go to the bottom of the file and add the following:

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

AssemblyFile and Destination works for local use and TFS online(Cloud) server.

小草泠泠 2024-09-11 10:57:39

当从另一个项目(在我的例子中是 Azure 工作项目库)引用具有配置文件的类库时,建议的解决方案将不起作用。它不会将正确的转换文件从 obj 文件夹复制到 bin\##configuration-name## 文件夹中。为了使其以最小的更改工作,您需要将 AfterCompile 目标更改为 BeforeCompile

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

proposed solution will not work when a class library with config file is referenced from another project (in my case it was Azure worker project library). It will not copy correct transformed file from obj folder into bin\##configuration-name## folder. To make it work with minimal changes, you need to change AfterCompile target to BeforeCompile:

<Target Name="BeforeCompile" Condition="exists('app.$(Configuration).config')">
握住我的手 2024-09-11 10:57:39

注意:由于声誉,我无法评论 bdeem帖子。我将我的发现作为答案发布。

bdeem帖子< /a>,我执行了以下操作(按顺序):

1。我修改了 [project].csproj 文件。将 标记添加到不同 config 文件的 ItemGroup 中,并使它们依赖于原始 < code>config 文件。

注意:使用 不适用于转换。

<!-- 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.在 [project].csproj 文件的底部(在结束 标记之前),我导入了 ${MSBuildToolsPath\Microsoft.CSharp .targets 文件,添加 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.config 文件下分组。

注意:确保 App.*.config 文件具有正确的 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.重新构建项目。

Note: Due to reputation I cannot comment on bdeem's post. I'm posting my findings as an answer instead.

Following bdeem's post, I did the following (in order):

1. I modified the [project].csproj file. Added the <Content Include="" /> tags to the ItemGroup for the different config files and made them dependent on the original config file.

Note: Using <None Include="" /> will not work with the transformation.

<!-- 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. At the bottom of the [project].csproj file (before the closing </Project> tag), I imported the ${MSBuildToolsPath\Microsoft.CSharp.targets file, added the UsingTask to transform the XML and added the Target to copy the transformed App.config file to the output location.

Note: The Target will also overwrite the App.Config in the local directory to see immediate changes working locally. The Target also uses the Name="Afterbuild" property to ensure the config files can be transformed after the executables are generated. For reasons I do not understand, when using WCF endpoints, if I use Name="CoreCompile", I will get warnings about the service attributes. Name="Afterbuild" resolved this.

  <!-- 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. Went back into Visual Studio and reloaded the modified files.

4. Manually added the App.*.config files to the project. This allowed them to group under the original App.config file.

Note: Make sure the App.*.config files have the proper XML structure.

<?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. Re-built the project.

ㄖ落Θ余辉 2024-09-11 10:57:39

我通过从未来回答来作弊,但 slow-cheetah 似乎是现在最好的解决方案。目前(从 2024 年开始)由 Microsoft 在 https://github.com/microsoft/slow-cheetah 维护

NuGet 包含原始的、不再维护的版本(也是由 MS 作者编写的)和这个新版本。您的项目中需要 NuGet 包来提供构建和运行支持。

对于完整的 VS 集成(例如,在右键单击菜单选项上自动添加转换文件),还可以从上面的链接安装适合您的 Visual Studio 版本的 .vsix

I am cheating by answering from the future, but slow-cheetah seems like the best solution now. It is currently (start 2024) maintained by Microsoft at https://github.com/microsoft/slow-cheetah.

NuGet contains the original, no-longer-maintained version (also by an MS author), and this new version. The NuGet package is required in your project for build and run support.

For full VS integration (e.g. auto-add transform files on right-click menu option), also install the appropriate .vsix for your edition of Visual Studio, from the link above.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文