App.Config转换的项目不是Web项目在Visual Studio?

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

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

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

250731 次浏览

我已经创建了Vishal Joshi发布的另一个替代方案,其中将构建动作更改为< em > < / em >内容的需求被删除,并实现了对ClickOnce部署的基本支持。我说基本,是因为我没有彻底测试它,但它应该在典型的ClickOnce部署场景中工作。

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

你可以在Visual Studio App.config XML转换上阅读更详细的解释,MSBuild项目文件可以是从GitHub下载

根据我的经验,我需要使环境特定的东西是像连接字符串、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)。

我尝试了几种解决方案,这里是我个人发现的最简单的一个。
在评论中指出原文属于奥列格Sych - 谢谢,奥列格!

以下是使用说明:

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

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

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

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

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

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

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

接下来,将所有configuration-specific文件依赖放在主文件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. 激活转换魔法(仍然需要Visual Studio版本,如VS2019)

在文件结束后

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

现在,本文处理的Visual Studio AddIn也可以使用SlowCheetah - Web。config转换语法现在适用于任何XML配置文件

你可以右键点击你的网页。单击“Add config” 转换。”当你这样做时,你会得到一个web.debug.config和一个 web.release.config。如果你喜欢,你可以创建一个web.whatever.config 只要名字和配置文件一致就行。这些文件 是否只是您想要的更改,而不是您的更改的完整副本 . config . < / p > 您可能认为您想要使用XSLT来转换web。配置,但 虽然他们直觉上觉得是对的,但实际上非常啰嗦 这里有两个转换,一个使用XSLT,另一个使用XML 文档转换语法/命名空间。就像所有的事情一样 在XSLT中有多种方法可以做到这一点,但您已经了解了总体思想。XSLT 是广义树转换语言,而这种部署呢 一种是针对常见场景的特定子集进行优化。但是, 很酷的一点是,每个XDT转换都是一个。net插件,因此您可以创建 你自己的。< / p >
<?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>

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

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

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

我写了一个很好的扩展来自动化app.config转换,就像在Web应用程序项目配置转换中构建的那样

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

你可以为每个配置使用一个单独的配置文件,例如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版本

受到奥列格和其他问题的启发,我进一步采用了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. 激活转换魔法

在文件结束后

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

在期末考试之前

</Project>

插入以下XML文件:

<Import Project="AppConfigTransformation.targets" />

完成了!

所以我最终采取了一种稍微不同的方法。我按照Dan的步骤完成了第3步,但添加了另一个文件:App.Base.Config。这个文件包含在每个生成的App.Config中需要的配置设置。然后我使用BeforeBuild (Yuri添加到TransformXml)将当前配置与基本配置转换为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>
如果你使用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在线(云)服务器。

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

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

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

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

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

按照bdeem帖子,我做了以下(按顺序):

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

注意:使用<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. 在[project].csproj文件的底部(在结束的</Project>标记之前),我导入了${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. 重建项目。

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

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