App.Config Transformation สำหรับโครงการที่ไม่ใช่โครงการ Web ใน Visual Studio?


546

สำหรับแอปพลิเคชันที่ทำงานบนเว็บ Visual Studio 2010 เรามีคุณสมบัติการแปลงค่าซึ่งเราสามารถบำรุงรักษาไฟล์กำหนดค่าหลายไฟล์สำหรับสภาพแวดล้อมที่แตกต่าง แต่คุณสมบัติเดียวกันนี้ไม่สามารถใช้ได้กับไฟล์ App.Config สำหรับ Windows Services / WinForms หรือ Console Application

มีวิธีแก้ปัญหาที่มีอยู่ตามที่แนะนำที่นี่: การใช้เวทมนตร์ XDT เพื่อ App.Config

อย่างไรก็ตามมันไม่ตรงไปตรงมาและต้องใช้หลายขั้นตอน มีวิธีที่ง่ายกว่าในการทำเช่นเดียวกันกับไฟล์ app.config หรือไม่?


ฉันเจอบทความต่อไปนี้ซึ่งดูเรียบง่ายขึ้น แต่ฉันไม่ได้ลองเอง fknut.blogspot.com/2009/11/…นอกจากนี้ยังมีการร้องขอคุณสมบัติใน MS Connect ซึ่งอาจคุ้มค่าที่จะลงคะแนนดังนั้นนี่จะรวมอยู่ในบอร์ดใน SP หรือเวอร์ชั่นถัดไป connect.microsoft.com/VisualStudio/feedback/details/564414
Kim R

คำตอบ:


413

นี้ทำงานตอนนี้กับ Visual Studio AddIn รับการรักษาในบทความนี้: SlowCheetah - Web.config การเปลี่ยนแปลงในขณะนี้ไวยากรณ์ทั่วไปสำหรับการตั้งค่าไฟล์

คุณสามารถคลิกขวาที่ web.config แล้วคลิก "Add Config Transforms" เมื่อคุณทำเช่นนี้คุณจะได้รับ web.debug.config และ web.release.config คุณสามารถสร้างเว็บได้ตามต้องการถ้าคุณต้องการตราบใดที่ชื่อนั้นสอดคล้องกับโปรไฟล์การกำหนดค่า ไฟล์เหล่านี้เป็นเพียงการเปลี่ยนแปลงที่คุณต้องการไม่ใช่สำเนาที่สมบูรณ์ของ web.config

คุณอาจคิดว่าคุณต้องการใช้ XSLT เพื่อแปลง web.config แต่ในขณะที่พวกเขารู้สึกว่าสัญชาตญาณถูกต้องมันเป็นเรื่องจริงมาก

นี่คือการแปลงสองรายการโดยใช้ XSLT และอีกอันใช้การแปลงเอกสาร XML ของไวยากรณ์ / เนมสเปซ เช่นเดียวกับทุกสิ่ง 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>

โอ้นั่นหวาน! มีแอปที่มีไฟล์ปรับแต่งมากมาย (log4net, nHibernate, web.config) และการจำการเปลี่ยนแปลงทั้งหมดนั้นเป็นเรื่องที่เจ็บปวด ฉันไม่ได้รอคอยที่จะย้ายรหัสไปที่ CruiseControl.NET เช่นกัน แต่ดูเหมือนว่าเป็นเรื่องง่าย
DilbertDave

10
FYI, SlowCheetah เป็นส่วนขยายที่ยอดเยี่ยมที่จะได้รับการสนับสนุนหลังจาก VS 2014 ต่อผู้เขียน Sayed อิบราฮิมฮาชิ, sedodream.com/2014/08/11/...
bdeem

5
@ andrewb ฉันอ่านมันที่นี่ ; อย่างไรก็ตามนั่นเป็นปีที่แล้ว หลังจาก revisiting ด้ายและการอ่านความคิดเห็นที่ดูเหมือนว่ามีคนได้จัดให้มีรุ่นที่ทำงานร่วมกับ VS2015 นี่
Anil Natha

2
ทำงานอย่างสมบูรณ์แบบด้วย Visual Studio 2017 และ Visual Studio 2019
Guilherme de Jesus Santos

1
มันนี่ตอนนี้
ฮิวโก้ Freitas

573

ฉันลองวิธีแก้ปัญหาหลายอย่างแล้วและนี่เป็นวิธีที่ง่ายที่สุดที่ฉันค้นพบเป็นการส่วนตัว
แดนชี้ให้เห็นในความคิดเห็นที่โพสต์ต้นฉบับเป็นของOleg Sych - ขอบคุณ Oleg!

นี่คือคำแนะนำ:

1. เพิ่มไฟล์ XML สำหรับแต่ละการกำหนดค่าให้กับโครงการ

โดยปกติคุณจะมีDebugและReleaseการกำหนดค่าเพื่อให้ชื่อไฟล์ของคุณและApp.Debug.config App.Release.configในโครงการของฉันฉันสร้างการกำหนดค่าสำหรับสภาพแวดล้อมแต่ละประเภทดังนั้นคุณอาจต้องการทดลองกับสิ่งนั้น

2. ยกเลิกการโหลดโครงการและเปิดไฟล์. csproj เพื่อแก้ไข

Visual Studio ช่วยให้คุณสามารถแก้ไขไฟล์. csproj ได้ในตัวแก้ไข - คุณเพียงแค่ต้องยกเลิกการโหลดโครงการก่อน แล้วคลิกขวาที่มันและเลือกแก้ไข <ProjectName>

3. ผูกแอพ. *. 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 จึงจัดกลุ่มไฟล์เหล่านั้นเช่นเดียวกับไฟล์ออกแบบและไฟล์ behind รหัส

แทนที่ 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. เปิดใช้งานการแปลงเวทย์มนตร์ (เฉพาะที่จำเป็นสำหรับ Visual Studio รุ่นก่อนVS2017 )

ในตอนท้ายของไฟล์หลังจาก

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

4
ขอบคุณสำหรับสิ่งนี้! One note, ถ้าคุณเพิ่มไฟล์. config ใหม่ลงในโปรเจ็กต์หลังจากที่คุณแก้ไข csproj พวกเขาจะแสดงการจัดกลุ่มตาม App.config ฉันเพิ่มหนึ่งก่อนที่จะแก้ไข csproj และจบลงด้วยลิงก์สองลิงก์หนึ่งกลุ่มและหนึ่งโซโล
Jeff Swensen

8
ปัญหาอย่างหนึ่งของวิธีนี้คือเมื่อคุณมองไปที่แท็บ "เผยแพร่" ในคุณสมบัติโครงการแล้วคลิกที่ปุ่ม "ไฟล์แอปพลิเคชัน" ... คุณจะสังเกตเห็นว่า app.config, app.Debug.config app.Release.config ถูกบังคับให้นำไปใช้เป็นส่วนหนึ่งของกระบวนการเผยแพร่ แน่นอนว่าคุณจะได้รับไฟล์ MyApp.exe.config ที่ถูกต้องเช่นกัน แต่ฉันไม่ต้องการให้นำสัมภาระเพิ่มเติมไปใช้งาน จำเป็นต้องมีวิธีในการเก็บแอป *. ไฟล์ config ในโครงการเป็น <ไม่มี> แทนที่จะเป็น <Content>
Lee Grissom

6
ปัญหาหนึ่งที่ทำให้เกิดการทิ้งไว้สำหรับบางคนคือคำตอบแรกเริ่มจาก Oleg Sych ทำให้ชิ้นส่วนสำคัญออกมา หากในแอปแต่ละรายการของคุณ (env) .configs คุณไม่ได้แสดงรายการ '<configuration xmlns: xdt = " schemas.microsoft.com/XML-Document-Transform ">' และสิ่งต่าง ๆ เช่น <appSettings xdt: Transform = "แทนที่"> หรือคุณลักษณะที่ทำสิ่งที่คล้ายกันในบรรทัดการตั้งค่ามันจะไม่ทำงาน ข้อมูลบิตสุดท้ายนี้เป็นกุญแจสำคัญและเมื่อฉันเพิ่มข้อมูลแล้วมันก็เริ่มทำงาน
djangojazz

24
คุณสามารถแทนที่v10.0ด้วยv$(VisualStudioVersion)เพื่อให้แน่ใจว่าโครงการของคุณจะทำงานกับ VS เวอร์ชันที่ใหม่กว่าทั้งหมด
Thibault D.

14
ฉันมีข้อผิดพลาด MSBuild ข้อผิดพลาด MSB3021: ไม่สามารถคัดลอกไฟล์ ไม่พบไฟล์ 'obj \ Release \ ConsoleApp.exe' ในระหว่างการสร้าง ดังนั้นฉันจึงเปลี่ยนวิธีแก้ปัญหาเล็กน้อยเพื่อนำเป้าหมาย <Target Name = "AfterBuild"> มาใช้แทนการสร้างสิ่งใหม่ในโซลูชัน
asidis

137

วิธีแก้ปัญหาอื่นที่ฉันพบคือไม่ใช้การแปลง แต่มีไฟล์กำหนดค่าแยกต่างหากเช่น app.Release.config จากนั้นเพิ่มบรรทัดนี้ในไฟล์ csproj ของคุณ

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

สิ่งนี้จะไม่เพียงสร้างไฟล์ myprogram.exe.config ที่ถูกต้องเท่านั้น แต่หากคุณใช้ Setup และ Deployment Project ใน Visual Studio เพื่อสร้าง MSI มันจะบังคับให้โครงการปรับใช้นั้นใช้ไฟล์ config ที่ถูกต้องเมื่อทำการบรรจุ


6
สิ่งมหัศจรรย์ที่ไม่ได้บอกเล่าของ MSBuild ตอนนี้ฉันสงสัยว่าอะไรเป็นไปได้ Btw วิธีนี้ใช้ได้กับการปรับใช้ Clickonce โดยตรงจาก VS (ตรงกันข้ามกับคำตอบที่ได้รับคะแนนสูงกว่า)
Boris B.

4
การเปลี่ยนแปลงอาจกลายเป็นภาระและเกิดข้อผิดพลาดได้ง่ายหากการกำหนดค่ามีหลายรายการที่เป็น SAME สำหรับบิลด์ทั้งหมด การจัดการกับปัญหาในขณะนี้ที่. config ของสภาพแวดล้อมหนึ่งพลาดการเปลี่ยนแปลงและแน่นอนว่าเป็นการผลิต
jeepwran

1
การมีไฟล์ปรับแต่งสองชุดนั้นไม่ใช่ปัญหาตราบใดที่นักพัฒนาไม่ใช่คนที่ดูแลด้วยตนเอง
anIBMer

1
นี่เป็นงานที่สวยงามและมีเสน่ห์! ฉันวางเพียงแค่<AppConfig>App.Release.config</AppConfig>บรรทัดภายใน<PropertyGroupสภาพที่มีอยู่สำหรับการReleaseกำหนดค่าและ IDE แสดงให้เห็นเส้นด้านล่าง<AppConfig>... บรรทัดที่บอกว่ามันไม่ได้อยู่ในสคีมาหรืออะไรบางอย่าง แต่ฉันบันทึกไฟล์ต่อไปและโหลดไฟล์โครงการและทำการสร้างใหม่ ในการกำหนดค่าReleaseและใช้งานได้!
พระอิศวร

1
ด้วยสิ่งนี้คุณจะสูญเสียฟังก์ชันการทำงานของตัวออกแบบการตั้งค่า
Ondřej

33

จากประสบการณ์ของฉันสิ่งที่ฉันต้องการเพื่อสร้างสภาพแวดล้อมเฉพาะคือสิ่งต่างๆเช่นสตริงการเชื่อมต่อการตั้งค่าและการตั้งค่า 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)


ฉันมีการกำหนดค่าเดียวกับที่คุณมี แต่ฉันมีปัญหาในการแปลงไฟล์ smtp คุณสามารถรวมเอาต้นฉบับและการเปลี่ยนโฉมหน้าได้หรือไม่? นี่คือของฉัน: ไฟล์พื้นฐาน: <?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>
jgarza

ฉันไม่แน่ใจว่าฉันเข้าใจ ในการกำหนดค่านี้ผมไม่ได้เปลี่ยนอะไรมันเป็นเพียงแค่การคัดลอกไฟล์ ...
jeroenh

โอ้ฉันไม่เห็นส่วนสำเนา ฉันเปลี่ยนการตั้งค่าแทนการคัดลอก ขอบคุณอยู่ดี
jgarza

ฉันชอบวิธีนี้ หนึ่งข้อเสนอแนะเล็ก ๆ : ในตัวอย่างการคัดลอกเหนืออาร์กิวเมนต์ต้นทางและเป้าหมายสำหรับการคัดลอกควรล้อมรอบด้วยเครื่องหมายคำพูด มิฉะนั้น Pre-รูปร่างจะล้มเหลวสำหรับไดเรกทอรีที่มีช่องว่างในชื่อของพวกเขา
Vandre

32

ได้รับแรงบันดาลใจจาก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)

โซลูชันนี้ทำงานโดยดำเนินการแปลง 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 สำหรับแต่ละการกำหนดค่าให้กับโครงการ

โดยทั่วไปคุณจะมีการกำหนดค่า Debug และ Release ดังนั้นตั้งชื่อไฟล์ของคุณ App.Debug.config และ App.Release.config ในโครงการของฉันฉันได้สร้างการกำหนดค่าสำหรับสภาพแวดล้อมแต่ละประเภทดังนั้นคุณอาจต้องการทดสอบกับสิ่งนั้น

2. ยกเลิกการโหลดโครงการและเปิดไฟล์. csproj เพื่อแก้ไข

Visual Studio ช่วยให้คุณสามารถแก้ไข. csproj ได้ในตัวแก้ไข - คุณเพียงแค่ต้องยกเลิกการโหลดโครงการก่อน จากนั้นคลิกขวาที่มันแล้วเลือกแก้ไข. csproj

3. ผูกแอพ. *. config ไฟล์ไปที่ App.config หลัก

ค้นหาส่วนไฟล์โครงการที่มี App.config และ App. *. config ทั้งหมดอ้างอิงและแทนที่ดังนี้ คุณจะสังเกตเห็นว่าเราใช้ไม่มีแทนเนื้อหา

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

ทำ!


1
พยายามใน VS Community 2015 RC และไม่สนใจไฟล์ app.Debug.config ที่ฉันมี
Khainestar

ฉันใช้คำตอบที่ได้รับการยอมรับในโครงการ WinForms หนึ่งสำเร็จ แต่ด้วยเหตุผลบางอย่างที่ทำให้งงงวยไม่สามารถใช้คำตอบที่ยอมรับได้ ไปยังโครงการ WinForms อื่น (ทั้งหมดในโซลูชันเดียวกัน) คำตอบจาก @bdeem นี้เป็น fave ใหม่ของฉันเพราะมันทำงานร่วมกันอย่างถูกต้องกับโครงการ MSI ของฉัน - ขอบคุณมาก!
bkwdesign

ดูเหมือนจะไม่ทำงานใน VS 2015 ฉันได้อัปเดต VisualStudioVersion จาก 10 เป็น 12 แต่ไม่มีลูกเต๋า ความคิดใด ๆ
Sinaesthetic

@Sinaesthetic คุณช่วยให้รายละเอียดเพิ่มเติมกับเราได้ไหม? VS 2015 Ultimate ชุมชน ฯลฯ VB.NET, C #, มีข้อผิดพลาดใด ๆ
bdeem

องค์กร VS2015 ไม่มีข้อผิดพลาด แต่อย่างใด มันไม่ได้ทำอะไรเลย
Sinaesthetic

27

คุณสามารถใช้ไฟล์กำหนดค่าแยกต่างหากสำหรับแต่ละการกำหนดค่าเช่น app.Debug.config, app.Release.config จากนั้นใช้ตัวแปรการกำหนดค่าในไฟล์โครงการของคุณ:

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

สิ่งนี้จะสร้างไฟล์ ProjectName.exe.config ที่ถูกต้องขึ้นอยู่กับการกำหนดค่าที่คุณกำลังสร้าง


ขอบคุณฉันไม่ได้ใช้ตัวอย่างที่ถูกต้องของคุณเพื่อแก้ปัญหาที่ฉันมี แต่ตัวอย่างของคุณทำให้ฉันคิดและนำฉันไปสู่จิตวิญญาณที่คล้ายกันมากโดยใช้งานการคัดลอก
jpierson

พยายามทำสิ่งนี้ภายใต้ VS 2015 Community RC และสร้างขึ้น แต่ไม่สนใจเนื้อหาของแอพ *. config ที่ฉันเพิ่ม
Khainestar

14

ฉันเขียนส่วนขยายที่ดีเพื่อทำให้การแปลง app.config เป็นแบบอัตโนมัติเช่นเดียวกับที่สร้างใน Web Application Project Configuration Transform

ข้อได้เปรียบที่ใหญ่ที่สุดของส่วนขยายนี้คือคุณไม่จำเป็นต้องติดตั้งในส่วนต่อสร้างทั้งหมด


1
ส่วนขยายที่มีประโยชน์มากโดยเฉพาะอย่างยิ่งตอนนี้เสือชีต้าช้ากำลังเข้าสู่โหมดบำรุงรักษาและอาจไม่รองรับในอนาคต
dthrasher

ใช่คนควรหยุดเสือชีต้าช้าลงเป็นวิธีแก้ปัญหานี้เมื่อฟังก์ชั่นนี้ได้รับการสนับสนุนโดยงาน transformxml msbuild สถาปนิก sw ในทีมของฉันแนะนำเสือชีตาห์ที่ช้าในแบบสุดเหวี่ยงในโครงการของเราและสร้าง debug, stage, และ release transforms ของ configs ทั้งหมดของเราซึ่งส่วนใหญ่ไม่ต้องการการเปลี่ยนแปลง ไม่จำเป็นต้องบอกว่าช่วงเวลาที่เขาจากไปฉันดึงเสือชีตาห์ออกช้าและตอนนี้เราเพิ่งใช้งาน transformxml ชิ้นเดียวบน web.config Ahhhhh เรียบง่าย อย่าบอกว่าเสือชีต้าช้าไม่มีเวลาและสถานที่
HarryTuttle

5

ติดตั้ง "เครื่องมือแปลงการกำหนดค่า" ใน Visual Studio จาก Marketplace และเริ่ม VS ใหม่ คุณจะสามารถเห็นการแปลงตัวอย่างเมนูสำหรับ app.config ได้เช่นกัน

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


1
สิ่งนี้ทำงานได้อย่างสมบูรณ์และต้องการความพยายามหรือความคิดน้อยมาก ชื่นชมมาก ขอบคุณ ('การแปลงตัวอย่าง' ไม่ทำงาน แต่ 'เพิ่มการแปลง' ทำงานได้อย่างสมบูรณ์แบบโดยไม่มีปัญหาใน VS 2017) ดูเหมือนว่าจะได้รับการปรับปรุงบ่อยครั้ง
adudley

1
ขอบคุณมากสำหรับการแก้ปัญหาเบื้องหลังฉากนี้มันทำสิ่งที่ Dan Abramov อธิบายไว้ข้างต้นโดยไม่ทำให้มือสกปรก
Mohammed Dawood Ansari

นี่คือทางออกที่ดีที่สุด ตัวอย่างนี้ทำงานได้ดีกับ VS 2019
Kyle Champion

1
ฉันชอบมาก แต่พบว่ามันไม่รองรับไฟล์ app.config อื่น ๆ ที่ไม่มีการแก้ไข csproj ยังดีแม้ว่าจะดูตัวอย่างว่า
Ian1971

4

ดังนั้นฉันจึงเลือกวิธีที่แตกต่างออกไปเล็กน้อย ฉันทำตามขั้นตอนของ Dan ถึงขั้นตอนที่ 3 แต่เพิ่มไฟล์อื่น: App.Base.Config ไฟล์นี้มีการตั้งค่าที่คุณต้องการใน App.Config ที่สร้างขึ้นทุกครั้ง จากนั้นฉันใช้ BeforeBuild (ด้วยการเพิ่มของ Yuri to TransformXml) เพื่อแปลงการกำหนดค่าปัจจุบันด้วยการกำหนดค่าฐานเป็น App.config กระบวนการสร้างนั้นใช้ App.config transformed เป็นปกติ อย่างไรก็ตามสิ่งที่น่ารำคาญอย่างหนึ่งก็คือคุณต้องการที่จะแยก 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>

3

เพียงเล็กน้อยปรับปรุงโซลูชันที่ดูเหมือนว่าจะโพสต์ทุกที่ในขณะนี้:

<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
  • นั่นคือยกเว้นว่าคุณวางแผนที่จะอยู่กับเวอร์ชัน VS ปัจจุบันของคุณตลอดไป

คุณช่วยอธิบายให้คุณตอบหน่อยหรือให้แหล่งที่มาอธิบายได้ไหม
roydukkey

4
ดูเหมือนจะไม่ได้$(VisualStudioVersion)รับการตั้งค่าเมื่อใช้ MSBuild โดยตรง
Jeremy Smith

นี่ควรเป็นความเห็นของstackoverflow.com/a/5109530/2003763 (ฉันเพิ่งเพิ่มข้อมูลเดียวกับความคิดเห็นที่นั่น)
Thibault D.

2

ฉันได้สร้างทางเลือกอื่นให้กับ Vishal Joshi ที่ต้องการเปลี่ยนการดำเนินการสร้างเป็นเนื้อหาและนำการสนับสนุนพื้นฐานสำหรับการปรับใช้ ClickOnce ไปใช้ ฉันพูดแบบพื้นฐานเพราะฉันไม่ได้ทดสอบอย่างละเอียด แต่ควรทำงานในสถานการณ์การปรับใช้ ClickOnce ทั่วไป

การแก้ปัญหาประกอบด้วยโครงการ MSBuild เดียวที่ครั้งหนึ่งนำเข้าสู่โครงการแอปพลิเคชัน windows ที่มีอยู่ (* .csproj) จะขยายกระบวนการสร้างเพื่อพิจารณาการเปลี่ยนรูป app.config

คุณสามารถอ่านคำอธิบายรายละเอียดเพิ่มเติมได้ที่Visual Studio App.config XML การเปลี่ยนแปลงและแฟ้มโครงการ MSBuild สามารถดาวน์โหลดได้จาก GitHub


1

หากคุณใช้ 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 และปลายทางใช้งานได้กับการใช้งานในท้องถิ่นและเซิร์ฟเวอร์ TFS ออนไลน์ (Cloud)


0

โซลูชันที่นำเสนอจะไม่ทำงานเมื่อไลบรารีคลาสที่มีไฟล์กำหนดค่าอ้างอิงจากโครงการอื่น (ในกรณีของฉันคือไลบรารีโครงการ Azure คนงาน) มันจะไม่คัดลอกไฟล์ที่ถูกแปลงจากobjโฟลเดอร์ไปยังbin\##configuration-name##โฟลเดอร์ หากต้องการให้การทำงานมีการเปลี่ยนแปลงน้อยที่สุดคุณต้องเปลี่ยนAfterCompileเป้าหมายเป็นBeforeCompile:

<Target Name="BeforeCompile" Condition="exists('app.$(Configuration).config')">
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.