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

时间:2010-06-09 08:38:02

标签: visual-studio .net-4.0 app-config slowcheetah web-config-transform

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

此处提供了一种解决方法:Applying XDT magic to App.Config

然而,这并不简单,需要许多步骤。有没有更简单的方法来实现相同的app.config文件?

15 个答案:

答案 0 :(得分:527)

我尝试了几种解决方案,这是我个人发现的最简单的方法 Dan在评论中指出the original post属于Oleg Sych - 谢谢,Oleg!

以下是说明:

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

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

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

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

第3。将App。*。配置文件绑定到主App.config

查找包含所有App.configApp.*.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。激活变换魔法

之后的文件末尾
<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转换!

<强> FYI

确保您的App.*.config文件具有正确的设置:

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

答案 1 :(得分:402)

现在使用本文中处理的Visual Studio AddIn:SlowCheetah - Web.config Transformation Syntax now generalized for any XML configuration file

  

您可以右键单击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>

答案 2 :(得分:126)

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

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

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

答案 3 :(得分:33)

根据我的经验,我需要制作特定于环境的内容包括连接字符串,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)。

答案 4 :(得分:28)

Oleg以及此问题中的其他人的启发,我进一步采取了解决方案https://stackoverflow.com/a/5109530/2286801以启用以下内容。

  • 适用于ClickOnce
  • 与VS 2010中的安装和部署项目一起使用
  • 与VS2010,2013年,2015年合作(尽管应该也能正常运行,但未测试2012年)。
  • 与Team Build一起使用。 (您必须安装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。*。配置文件绑定到主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" />

完成!

答案 5 :(得分:27)

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

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

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

答案 6 :(得分:13)

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

中一样

此扩展程序的最大优点是您无需在所有构建计算机上安装它

答案 7 :(得分:4)

所以我最终采取了略微不同的方法。我按照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>

答案 8 :(得分:3)

我使用此工具http://ctt.codeplex.com/解决了这个问题。我将它与CCNet / nAnt脚本一起用于制作包。

答案 9 :(得分:3)

现在似乎在各处发布的解决方案稍有改进:

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

答案 10 :(得分:2)

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

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

您可以在Visual Studio App.config XML Transformation阅读更详细的说明,MSBuild项目文件可以是downloaded from GitHub

答案 11 :(得分:2)

安装&#34;配置变换工具&#34;在Marketplace中的Visual Studio中重启VS.您还可以看到app.config的菜单预览转换。

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

答案 12 :(得分:1)

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

<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在线(云)服务器。

答案 13 :(得分:0)

当从另一个项目引用具有配置文件的类库时,提议的解决方案将不起作用(在我的情况下,它是Azure工作项目库)。它不会将正确的已转换文件从 PRINT 'TEST ' ++ 'TEST' 文件夹复制到obj文件夹中。要使其最少的更改,您需要将bin\##configuration-name##目标更改为AfterCompile

BeforeCompile

答案 14 :(得分:0)

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

bdeempost之后,我按顺序进行了以下操作:

1。我修改了[project].csproj文件。为不同的<Content Include="" />文件添加了ItemGroup标签到config,并使它们依赖于原始的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,并添加了{{1 }},将转换后的Target文件复制到输出位置。

注意:App.config还将覆盖本地目录中的Target,以查看即时更改在本地生效。 App.Config还使用Target属性,以确保在生成可执行文件后 后可以转换配置文件。由于我不明白的原因,在使用WCF端点时,如果使用Name="Afterbuild",则会收到有关服务属性的警告。 Name="CoreCompile"解决了这个问题。

Name="Afterbuild"

3。回到Visual Studio,然后重新加载修改后的文件。

4。手动将 <!-- 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> 文件添加到项目中。这使他们可以分组到原始App.*.config文件下。

注意:确保App.config文件具有正确的XML结构。

App.*.config

5。重建项目。