对于Visual Studio 2010基于Web的应用程序,我们有配置转换功能,通过它我们可以为不同的环境维护多个配置文件。但同样的功能不适用于Windows服务/WinForms或控制台应用程序的App.Config文件。
这里有一个可用的解决方案:对App.Config应用XDT魔术。
然而,这并不简单,需要一些步骤。是否有更简单的方法来实现同样的app.config文件?
对于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>
其他回答
只是对现在到处张贴的解决方案做了一点改进:
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
也就是说,除非你打算永远使用当前的VS版本
如果你使用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在线(云)服务器。
这现在可以与本文中处理的Visual Studio AddIn一起工作:SlowCheetah - Web。config转换语法现在适用于任何XML配置文件。
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>
受Oleg和其他人在这个问题上的启发,我进一步采用了解决方案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)
这个解决方案的工作原理是在MSBuild过程中第一次引用app.config之前执行app.config转换。它使用一个外部目标文件,便于跨多个项目进行管理。
产品说明:
步骤与其他解决方案类似。我引用了保持不变的内容,并包括它的完整性和更容易的比较。
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—您只需要首先卸载项目。然后右键单击它并选择Edit .csproj。
3.绑定程序。*。配置文件到主App.config
找到包含所有App.config和App.*的项目文件部分。配置引用和替换如下所示。您将注意到我们使用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。目标" / > 在期末考试之前 > < /项目
插入以下XML文件:
<Import Project="AppConfigTransformation.targets" />
完成了!
这是@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>
它还有一个额外的好处,就是比原来的解决方案要短得多。