TFS构建未按预期转换web.config

30

目标是在ASP.NET MVC项目中,让TFS构建和部署2个或更多不同的配置,并使web.config变换文件在其输出中包含预期内容。

alt text

Web.Debug.Config - 在PasteBin上查看
Web.Release.Config - 在PasteBin上查看

这两个转换后的配置文件的生成操作设置为无。这是因为所有3个web.*.config文件都被包含在部署中。

TFS已正确配置以构建和部署两个配置。它按预期部署到2个放置位置。在构建定义中未指定任何MSBuild参数。

alt text

问题: 两个已构建和部署的网站具有相同的web.config文件。基本上,就好像转换后的文件不存在一样。 期望: web.config文件中应该存在指定的更改 (xdt:Transform="Replace"xdt:Transform="Remove")。
如何配置您的项目或TFS以确保处理web.config转换并将其输出部署到正确的部署位置?还可以检查/修改什么?
  • 已确认转换是正确的--Vishal's Joshit's教程使用MSBuild命令行输出了正确的转换!
  • 没有对.csproj进行任何后期构建或部署的修改。
  • 是否误用或缺少任何属性?
  • 在生成定义中没有指定任何MSBuild参数。
  • Web.config Build Actions设置正确吗?
  • 我们不使用Web部署包或任何其他东西。只是希望稍后将这些输出复制到它们各自的Web服务器位置。

如果我遗漏了任何重要信息,请留下评论,我会包含任何更相关的信息!

5个回答

23

1
更简单的解决方案!完美地工作,即使将TFS构建设置为构建多个配置(调试和发布都转换得很好)。 - Shawson
正是我所需要的!谢谢你的提示。 - Scope Creep

8
TFS Team Build 2010不会自动转换你的Web.configs。你需要在构建过程模板中添加自定义工作流活动来完成这一点。
Edwald Hofman撰写了一篇很好的博客,解释了如何修改TFS 2010构建过程模板,因此我在此不再详述。 http://www.ewaldhofman.nl/post/2010/04/29/Customize-Team-Build-2010-e28093-Part-4-Create-your-own-activity.aspx 当你找到如何向构建过程模板中添加自定义活动后,请将以下活动添加到工作流中。我将其添加到“将文件放入放置位置”之后。它利用Microsoft.Web.Publishing.Tasks程序集(位于:C:\ Program Files(x86)\ MSBuild \ Microsoft \ VisualStudio \ v10.0 \ Web )来执行转换:
/// <summary>
/// Transforms configuration files using TransformXml
/// </summary>
[BuildActivity(HostEnvironmentOption.All)]
public sealed class WebConfigTransform : CodeActivity
{
    #region Public Properties

    /// <summary>
    /// The binaries folder
    /// </summary>
    [RequiredArgument]
    public InArgument<string> BinariesLocation { get; set; }

    #endregion

    #region Overrides of CodeActivity

    /// <summary>
    /// When implemented in a derived class, performs the execution of the activity.
    /// </summary>
    /// <param name="context">The execution context under which the activity executes.</param>
    protected override void Execute(CodeActivityContext context)
    {
        var binariesFolder = context.GetValue(BinariesLocation);

        foreach (var sourceFolder in Directory.GetDirectories(Path.Combine(binariesFolder, "_PublishedWebsites")))
        {
            var sourceFile = Path.Combine(sourceFolder, "Web.config");
            if (File.Exists(sourceFile))
            {
                var filesToTransform = Directory.GetFiles(sourceFolder, "Web.*.config");


                foreach (var fileToTransform in filesToTransform)
                {

                    var tempSourceFile = Path.GetTempFileName();
                    var tempTransformFile = Path.GetTempFileName();

                    File.Copy(sourceFile, tempSourceFile, true);
                    File.Copy(fileToTransform, tempTransformFile, true);

                    var transformation = new TransformXml
                    {
                        BuildEngine = new BuildEngineStub(),
                        Source = tempSourceFile,
                        Transform = tempTransformFile,
                        Destination = fileToTransform
                    };

                    transformation.Execute();
                }
            }
        }
    }

    #endregion
}

您需要在工作流中传递droplocation。当您将其添加到工作流中时,请右键单击活动,然后转到属性,并将“DropLocation”(VB表达式)粘贴到属性“BinaryLocation”中。

注意:您需要创建一个实现IBuildEngine接口的BuildEngineStub类,以便使用MSBuild任务。这是我使用的代码:

public class BuildEngineStub : IBuildEngine
{
        #region IBuildEngine Members

        public bool BuildProjectFile(string projectFileName, string[] targetNames,
                                     IDictionary globalProperties,
                                     IDictionary targetOutputs)
        {
            throw new NotImplementedException();
        }

        public int ColumnNumberOfTaskNode
        {
            get { return 0; }
        }

        public bool ContinueOnError
        {
            get { return false; }
        }

        public int LineNumberOfTaskNode
        {
            get { return 0; }
        }

        public string ProjectFileOfTaskNode
        {
            get { return ""; }
        }

        public void LogCustomEvent(CustomBuildEventArgs e)
        {
            Console.WriteLine("Custom: {0}", e.Message);
        }

        public void LogErrorEvent(BuildErrorEventArgs e)
        {
            Console.WriteLine("Error: {0}", e.Message);
        }

        public void LogMessageEvent(BuildMessageEventArgs e)
        {
            Console.WriteLine("Message: {0}", e.Message);
        }

        public void LogWarningEvent(BuildWarningEventArgs e)
        {
            Console.WriteLine("Warning: {0}", e.Message);
        }

        #endregion
    }

1
其他选项是更好的选择,而且设置起来要容易得多。 - Allen Rice
5
不同意。我更愿意一次性对我的构建过程模板进行更改(供所有解决方案使用),而不是必须编辑我创建的每个.proj文件或构建定义。 - Danny
1
嗯,说得好,我从没想过那个问题... 诚然,我对通过TFS和构建模板进行构建很新,但这一切似乎非常令人沮丧。似乎我们不得不费力地开发/维护脚本来实现已经存在于msbuild中的功能。 - Allen Rice
有人知道这个是否仍需要为TFS Build 2012完成吗? - Jaans
使用TFS工作令人沮丧,因为这些功能应该是内置的并且易于设置。确实,能够自定义构建工作流程非常棒,并且给您很多灵活性,但事实是,即使对于最简单的项目,TFS的开箱即用功能也几乎不足够。 - Alex
显示剩余3条评论

4

以下是我一直在使用的方法。当前的TransformXml任务存在一个bug,会导致文件无法关闭。详情请参见此处

您可以为每个配置调用此任务并进行部署。

<Target Name="TransformWebConfig">

    <PropertyGroup>
        <_tempSourceFile>$([System.IO.Path]::GetTempFileName())</_tempSourceFile>
        <_tempTransformFile>$([System.IO.Path]::GetTempFileName())</_tempTransformFile>
    </PropertyGroup>

    <Copy SourceFiles="$(_websiteDirectory)\Web.config" DestinationFiles="$(_tempSourceFile)"/>
    <Copy SourceFiles="$(_websiteDirectory)\Web.$(_transformConfiguration).config" DestinationFiles="$(_tempTransformFile)"/>

    <MSBuild.Community.Tasks.Attrib Files="$(_websiteDirectory)\Web.config" ReadOnly="false" />

    <TransformXml Source="$(_tempSourceFile)"
                  Transform="$(_tempTransformFile)"
                  Destination="$(_websiteDirectory)\Web.config"
                  StackTrace="false" />
</Target>

谢谢。我有点困惑,这段XML代码应该放在哪里?还需要修改TFS Build定义吗? - p.campbell
你对MSBuild熟悉吗?你可以将此目标放置在构建定义中,然后从“BeforeDropBuild”目标调用它。 - Danny
1
没错。虽然我认为在我回答时并不是这样的。谁知道呢,我会重新发布适用于TFS 2010的正确答案。 - Danny

0

Drop并不实际进行任何转换。您需要的是在MSBuild参数中添加/p:DeployOnBuild=True

这将创建一个包,可以通过命令行或使用IIS导入应用程序向导安装网站。

如果你想直接发布多个配置,那就是另一回事了,我就是因为这个才看到了这篇文章。


0

尝试不要设置构建平台 - 基本上在 ItemToBuild 中删除 "Any CPU",并选择 MSBuild 平台为 "Auto"


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接