2009-05-27 65 views
4

为了处理不同部署目标的设置,我将应用程序设置从app.config移到了它自己的文件中,并通过configSource将该文件包含在app.config中。我还创建用于每个target.Here一个设置文件是一个例证:多个.NET配置文件和安装项目问题

Project A 
    app.config (references settings.config) 
    settings.config 
    settings.Release.config 
    settings.Debug.config 

在生成后,我复制适当的设置{配置}的.config到输出目录。目前为止工作正常,我可以在项目输出目录中看到settings.config文件,其中包含当前版本配置的设置:发布,调试等。

但是,我遇到了安装项目的问题,有这个项目(项目A)。最初,它不包括settings.config文件。因此,我将settings.config文件的构建操作设置为内容,并将项目A的内容文件添加到安装项目中。这确保了setup.config文件包含在设置中。但是,由于安装项目似乎是从项目目录而不是输出目录中选取settings.config文件,因此设置中包含的settings.config文件不是它应该包含的内容。我希望输出目录中的那个包含在安装程序中,因为那一个对于当前的构建配置是正确的。我尝试了以下方法:

  • 将settings.config添加为安装项目的文件。但是,似乎我只能指定绝对路径。因此,当我从特定构建配置(..bin \ debug \ settings.config)的输出目录中添加它时,它在其他构建配置中不起作用,因为(..bin \ debug \ settings.config)确实存在于指定的目录。我研究了在安装项目中使用相对路径或动态路径,其中构建配置可以被指定为路径的一部分,但我找不到任何东西。

我认为使用预生成事件实际修改在项目目录的settings.config文件,然后把它复制了输出目录通过其“复制到输出目录”设置为始终复制或是否有更新的复制。这应该确保将相应的settings.config复制到输出目录,就像基于后构建的解决方案一样,并且还应该确保settings.config文件的内容在安装项目包含之前已更新。但是,我不喜欢这个解决方案,因为我必须确保settings.config文件是可写的,然后才能进行任何更改,因为它是源代码管理的。如果它是只读的,那么我需要将其翻转为可写,进行更改,然后将其设置为只读。这增加了额外的复杂性。

我想知道是否有人有一个更好的主意或知道一个安装项目的技巧,允许我包括settings.config文件适合当前生成配置在安装程序。

感谢

+0

我不知道这可能对你有多大帮助,但是你可以试试MSBuild脚本,在编译projet之前实现你的配置文件“开关”。 2年前,我看到了类似这样的东西,但是它嵌入了Pearl的几条线中,以达到目前为止我所见过的最复杂的构建脚本之一。但是你应该能够为你的项目做更简单的事情。 – 2009-05-27 17:03:25

回答

1

如果我必须解决这个问题,我会通过问以下的问题开始:

为什么的settings.config必须要进行源代码控制,如果settings.Debug.config或settings.Release.config提供相同的信息?

答案是,如果我正确地读你的问题,是因为你需要强制一个settings.config文件作为生成输出的一部分出现。我猜这是因为你的设置项目正在使用内置的“主输出”选项。

您可以改为将该文件添加到安装项目中作为显式文件引用。右键单击安装项目并选择添加/文件,然后选择要包含的文件。正如你会注意到的(除非它在VS2008中被修复,遗憾的是我还没有被允许在工作中使用),对手动添加的文件存在一个非常恼人的限制 - 没有办法让路径构建配置知道。您可以通过将相应的settings.config文件复制到一个公共位置(例如bin/Configuration)并从中选择它来解决此问题。这确实会限制您按顺序构建Debug和Release版本,而不是并行执行,但对于许多人来说,这可能不是一个大问题。

如果你不使用VS安装项目所需要的,我强烈建议你看看维克斯(Windows安装XML - 见http://wix.sourceforge.net/获取更多信息)。这很容易让你完成必要的任务,但如果你不熟悉Microsoft Installer的内部工作,初始学习曲线可能会有点陡峭。 Microsoft使用WiX自己进行一些非常重要的设置任务(例如Office 2007,SQL Server等)。人们一直希望WiX能够成为Visual Studio的一部分(VS 2010),但遗憾的是不再是这种情况。

+0

感谢您的回答。 settings.config不需要在源代码控制之下。我将它包含在内,以便它成为输出的一部分,并且可以作为资源包含在安装程序中。将它作为文件引用从公共位置添加的问题是文件的路径在安装程序中是绝对路径(C:\ MyWorkspace \ Solution \ ProjectA \ Config \ settings.config)。但是,开发人员拥有不同的工作空间,并且构建计算机(TeamBuild)具有自己的目录结构。因此,除非亲属会这样,否则这就是我遇到的问题。任何方式使它相对? – 2009-06-11 16:35:20

1

我决定以不同的方式实现相同的结果(能够针对不同的目标环境进行不同的配置设置)。所以这里是我如何实现它,它运作良好。我在SO上阅读了一些关于从MSBuild Community Tasks开始的XmlMassUpdate任务的帖子,并决定使用它。下面是我做的:

1)对于需要根据各自的目标环境不同的设置每一个项目,我添加了一个XML文件名为app.config.substitutions.xml或web.config.substitutions.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)的一部分。因此,在BeforeCompile在TeamBuild构建定义文件(基本上是PROJ文件),我增加了以下内容上有一个相应的.substitution.xml文件

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

注意,配置文件是只读的,在配置文件运行XmlMassUpdate构建,我确保在运行此任务之前将它们设置为可写。我实际上有另一个自定义的MSBuild任务,它在XmlMassUpdate之前运行,可处理所有配置文件(如连接字符串)中的常见设置。该任务使配置文件可写。我也不检查修改的配置文件回到源代码管理。它们是安装程序中包含的(适用于部署目标的适当配置文件)。