为了处理不同部署目标的设置,我将应用程序设置从app.config移动到了自己的文件,并通过configSource将该文件包含在app.config中。我还为每个目标创建了一个设置文件。这是一个例子:
Project A
app.config (references settings.config)
settings.config
settings.Release.config
settings.Debug.config
在构建后,我将相应的设置。{configuration} .config复制到输出目录。到目前为止这工作正常,我可以在项目输出目录中看到包含当前构建配置设置的settings.config文件:Release,Debug等。
但是,我对此项目的安装项目有问题(项目A)。最初,它不包括settings.config文件。所以我将settings.config文件的构建操作设置为Content,并将项目A中的内容文件添加到安装项目中。这确保了settings.config文件包含在设置中。但是,由于安装项目似乎是从项目目录而不是输出目录中选择settings.config文件,因此安装程序中包含的settings.config文件不是它应该的样子。我希望输出目录中的那个包含在安装程序中,因为那个是当前构建配置的正确选项。我尝试了以下方法:
我考虑使用预构建事件来实际修改项目目录中的settings.config文件,然后通过将其“复制到输出目录”设置为始终复制或复制(如果较新)将其复制到输出目录中。这应确保将相应的settings.config复制到输出目录,就像基于构建后的解决方案一样,并且还应确保在安装项目包含之前更新settings.config文件的内容。但是,我不喜欢这个解决方案,因为在我可以进行任何更改之前,我必须确保settings.config文件是可写的,因为它是源代码控制的。如果它是只读的,那么我需要将其翻转为可写,进行更改,然后再将其设置为只读。它增加了额外的复杂性。
我想知道是否有人有更好的想法或知道一个安装项目技巧,允许我在安装程序中包含适用于当前构建配置的settings.config文件。
由于
答案 0 :(得分:1)
如果我不得不解决这个问题,我首先会提出以下问题:
如果settings.Debug.config或settings.Release.config提供相同的信息,为什么settings.config必须受源代码控制?
如果我正确地阅读了您的问题,答案是因为您需要强制settings.config文件作为构建输出的一部分出现。我猜这是因为您的安装项目使用内置的“主输出”选项。
您可以做的是将该文件作为显式文件引用添加到您的安装项目中。右键单击安装项目并选择添加/文件,然后选择要包含的文件。正如您将注意到的那样(除非它已经在VS2008中得到修复,遗憾的是我还不允许在工作中使用),对手动添加的文件存在非常恼人的限制 - 没有办法让路径构建配置知道。您可以通过将相应的settings.config文件复制到公共位置(例如bin / Configuration)并从那里拾取它来解决此问题。这确实限制了您按顺序构建Debug和Release版本,而不是并行构建,但对于许多人而言,这可能不是一个大问题。
如果您不需要使用VS安装项目,我强烈建议您查看WiX(Windows Installer XML - 有关详细信息,请参阅http://wix.sourceforge.net/)。这将很容易让您完成必要的工作,但如果您不熟悉Microsoft Installer的内部工作原理,初始学习曲线可能会有点陡峭。 Microsoft将自己的WiX用于一些非常重要的设置任务(例如Office 2007,SQL Server等)。希望WiX成为Visual Studio的一部分(适用于VS 2010),但遗憾的是,情况已不再如此。
答案 1 :(得分:1)
我决定以不同的方式实现相同的结果(能够为不同的目标环境设置不同的配置)。所以这就是我如何实现它并且它工作得很好。我在这里阅读了一些关于来自MSBuild Community Tasks的XmlMassUpdate任务的帖子,并决定使用它。这是我做的:
1)对于每个需要根据目标环境设置不同的项目,我将一个名为app.config.substitutions.xml或web.config.substitutions.xml的xml文件添加到项目中。所以,该项目看起来像
Project A
app.config
app.config.substitutions.xml
app.config.substitutions.xml文件具有XmlMassUpdate将处理并应用于app.config文件的设置替换。下面是我使用的示例替换文件:
<configuration xmlns:xmu="urn:msbuildcommunitytasks-xmlmassupdate">
<substitutions>
<Development>
<appSettings>
<add xmu:key="key" key="SomeSetting" value="DevValue" />
</appSettings>
</Development>
<Test>
<appSettings>
<add xmu:key="key" key="SomeSetting" value="TestValue" />
</appSettings>
</Test>
<Release>
<appSettings>
<add xmu:key="key" key="SomeSetting" value="ReleaseValue" />
</appSettings>
</Release>
</substitutions>
</configuration>
有关如何指定替换的详细信息,请查看XmlMassUpdate的文档或只是对其进行搜索。
2)现在我需要运行XmlMassUpdate作为构建自动化(TeamBuild / MSBuild)的一部分。因此,在TeamBuild构建定义文件(基本上是一个proj文件)中的BeforeCompile中,我添加了以下内容以在具有相应.substitution.xml文件的配置文件上运行XmlMassUpdate
<PropertyGroup>
<SubstitutionFileExtension>.substitutions.xml</SubstitutionFileExtension>
<TargetEnvironment>Test</TargetEnvironment>
</PropertyGroup>
<Target Name="BeforeCompile" Condition="'$(IsDesktopBuild)'!='true'">
<CreateItem Include="$(SolutionRoot)\**\app.config;$(SolutionRoot)\**\web.config">
<Output ItemName="ConfigurationFiles" TaskParameter="Include"/>
</CreateItem>
<CreateItem Include="@(ConfigurationFiles)" Condition="Exists('%(FullPath)$(SubstitutionFileExtension)')">
<Output ItemName="ConfigFilesWithSubstitutions" TaskParameter="Include"/>
</CreateItem>
<Message Text="Updating configuration files with deployment target specific settings..."/>
<XmlMassUpdate
ContentFile="%(ConfigFilesWithSubstitutions.FullPath)"
SubstitutionsFile="%(ConfigFilesWithSubstitutions.FullPath)$(SubstitutionFileExtension)"
ContentRoot="/configuration"
SubstitutionsRoot="/configuration/substitutions/$(TargetEnvironment)"/>
</Target>
请注意,配置文件在构建期间是只读的,我确保在运行此任务之前将它们设置为可写。我实际上有另一个自定义MSBuild任务,它在XmlMassUpdate之前运行,它处理所有配置文件(如连接字符串)中的常见设置。该任务使配置文件可写。我也不会将修改后的配置文件检查回源代码控制。它们是(安装程序中包含的适当的部署目标配置文件)。