对于基于Visual Studio 2010 Web的应用程序,我们具有“配置转换”功能,通过这些功能,我们可以为不同的环境维护多个配置文件。但是该功能不适用于Windows Services / WinForms或控制台应用程序的App.Config文件。
这里有建议的解决方法:将XDT magic应用于App.Config。
但是,这并不简单,需要很多步骤。有没有更简单的方法来实现相同的app.config文件?
对于基于Visual Studio 2010 Web的应用程序,我们具有“配置转换”功能,通过这些功能,我们可以为不同的环境维护多个配置文件。但是该功能不适用于Windows Services / WinForms或控制台应用程序的App.Config文件。
这里有建议的解决方法:将XDT magic应用于App.Config。
但是,这并不简单,需要很多步骤。有没有更简单的方法来实现相同的app.config文件?
Answers:
现在,该功能可以与本文中介绍的Visual Studio 插件一起使用:SlowCheetah-Web.config转换语法现在可用于任何XML配置文件。
您可以右键单击web.config,然后单击“添加配置转换”。执行此操作时,将获得一个web.debug.config和一个web.release.config。您可以根据需要创建一个web.whatever.config,只要该名称与配置配置文件对齐即可。这些文件只是您要进行的更改,而不是web.config的完整副本。
您可能会认为您想使用XSLT来转换web.config,但是尽管他们直观地感觉很对,但实际上却很冗长。
这是两种转换,一种使用XSLT,另一种使用XML Document Transform语法/命名空间。与所有事物一样,XSLT中有多种方法可以执行此操作,但是您可以大致了解。XSLT是一种通用的树转换语言,而此部署语言是针对常见方案的特定子集进行了优化的。但是,最酷的部分是每个XDT转换都是.NET插件,因此您可以自己制作。
<?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>
或通过部署转换进行相同的操作:
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> <appSettings> <add name="NewSetting" value="New Setting Value" xdt:Transform="Insert"/> </appSettings> </configuration>
我尝试了几种解决方案,这是我个人发现的最简单的解决方案。
丹在评论中指出,原来的职位属于奥列格Sych发表 - 感谢,奥列格!
以下是说明:
1.将每个配置的XML文件添加到项目中。
通常情况下,您将具有Debug
和Release
配置,因此请命名文件App.Debug.config
和App.Release.config
。在我的项目中,我为每种环境创建了一个配置,因此您可能需要尝试一下。
2.卸载项目并打开.csproj文件进行编辑
Visual Studio允许您直接在编辑器中编辑.csproj文件-您只需要先卸载项目即可。然后右键单击它,然后选择Edit <ProjectName> .csproj。
3.将App。*。config文件绑定到主App.config
找到包含全部App.config
和App.*.config
引用的项目文件部分。您会注意到他们的构建操作设置为None
:
<None Include="App.config" />
<None Include="App.Debug.config" />
<None Include="App.Release.config" />
首先,将所有人的构建动作设置为Content
。
接下来,使所有特定于配置的文件都依赖于主文件,App.config
以便Visual Studio像设计器文件和代码隐藏文件一样对它们进行分组。
将以下XML替换为以下XML:
<Content Include="App.config" />
<Content Include="App.Debug.config" >
<DependentUpon>App.config</DependentUpon>
</Content>
<Content Include="App.Release.config" >
<DependentUpon>App.config</DependentUpon>
</Content>
4.激活转换魔术(仅适用于VS2017之前的Visual Studio版本)
在文件末尾之后
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
在决赛之前
</Project>
插入以下XML:
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="CoreCompile" Condition="exists('app.$(Configuration).config')">
<!-- Generate transformed app config in the intermediate directory -->
<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>
v10.0
为v$(VisualStudioVersion)
,以确保您的项目可用于所有更高版本的VS。
我发现的另一个解决方案是不使用转换,而只是使用一个单独的配置文件,例如app.Release.config。然后将此行添加到您的csproj文件。
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<AppConfig>App.Release.config</AppConfig>
</PropertyGroup>
这不仅会生成正确的myprogram.exe.config文件,而且如果您正在Visual Studio中使用安装和部署项目来生成MSI,它将在打包时强制部署项目使用正确的配置文件。
<AppConfig>App.Release.config</AppConfig>
行粘贴到<PropertyGroup
了Release
配置的现有条件中,IDE在<AppConfig>
... 行下方显示了一个弯曲的行,表示该行不在架构等中,但是我还是保存了文件并重新加载了项目文件并进行了构建在Release
配置中,它的工作!
以我的经验,我需要使特定于环境的事情是诸如连接字符串,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)。
<?xml version="1.0"?> <smtp deliveryMethod="SpecifiedPickupDirectory"> <specifiedPickupDirectory pickupDirectoryLocation="C:\mail"/> <network host="localhost"/> </smtp>
转换:<?xml version="1.0"?> <smtp xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform" xdt:Transform="Replace" from="user@email.com" deliveryMethod="Network"> <network .../> </smtp>
受奥列格(Oleg)和其他人在这个问题上的启发,我将解决方案https://stackoverflow.com/a/5109530/2286801进一步推进了以下工作。
此解决方案通过在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文件添加到项目中。
通常,您将具有Debug和Release配置,因此将文件命名为App.Debug.config和App.Release.config。在我的项目中,我为每种环境创建了一个配置,因此您可能需要尝试一下。
2.卸载项目并打开.csproj文件进行编辑
Visual Studio允许您直接在编辑器中编辑.csproj -您只需要先卸载项目即可。然后右键单击它,然后选择Edit .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.激活转换魔术
在文件末尾之后
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
在决赛之前
</Project>
插入以下XML:
<Import Project="AppConfigTransformation.targets" />
做完了!
您可以为每个配置使用单独的配置文件,例如app.Debug.config,app.Release.config,然后在项目文件中使用配置变量:
<PropertyGroup>
<AppConfig>App.$(Configuration).config</AppConfig>
</PropertyGroup>
然后,这将根据您正在构建的配置来创建正确的ProjectName.exe.config文件。
我编写了不错的扩展程序来自动化app.config转换,例如内置的Web应用程序项目配置转换
此扩展程序的最大优点是您无需在所有构建计算机上都安装它
从Marketplace在Visual Studio中安装“配置转换工具”,然后重新启动VS。您还将能够看到app.config的菜单预览转换。
https://marketplace.visualstudio.com/items?itemName=GolanAvraham.ConfigurationTransform
所以我最终采取了稍微不同的方法。我按照Dan的步骤进行了第3步,但添加了另一个文件:App.Base.Config。此文件包含每个生成的App.Config中所需的配置设置。然后,我使用BeforeBuild(Yuri在TransformXml中添加了)将具有Base config的当前配置转换为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>
现在似乎已在各地发布的解决方案有了一点改进:
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
$(VisualStudioVersion)
直接使用MSBuild时看起来好像没有设置。
我创建了Vishal Joshi发布的另一种替代方法,其中删除了将生成操作更改为Content的要求,并且还实现了对ClickOnce部署的基本支持。我说基本是因为我没有对其进行彻底的测试,但是它应该可以在典型的ClickOnce部署方案中使用。
该解决方案由单个MSBuild项目组成,该项目一旦导入到现有的Windows应用程序项目(* .csproj)中,便会将构建过程扩展为考虑app.config转换。
您可以在Visual Studio App.config XML Transformation中阅读更详细的说明,并且可以从GitHub下载 MSBuild项目文件。
如果您在线使用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在线(云)服务器。