使用Visual Studio Team Foundation Service构建Windows应用商店应用程序的完整指南

2025-03-23 07:05:16

TFS

本文使用团队构建和验证应用程序商店应用程序

自2012年10月发布最终版本以来,Team(TFS)的云版本提供了许多功能来帮助您提供高质量的软件。开发8个软件的愿望将不再遥不可及。

您可能想知道是否可以将两种产品组合在一起,即使用团队来构建App Store应用程序。不幸的是,由于某些限制,目前无法直接实施这一点,并且将在本文后面介绍。但是,我还将介绍避免此问题所需的步骤,并帮助您在构建过程中验证商店应用程序。

首先,让我们快速看一下团队​​。

团队概述

作为基于云的服务,团队允许开发人员访问TFS提供的功能,而不必麻烦安装和管理TF。只需在bit.ly/上注册(免费!),就可以去了。

在该产品提供的服务中,您可以专注于使用三个主要功能来开发和提供高质量的软件:

源代码管理您可以使用源代码管理功能,而当前工具和首选语言保持不变。源代码管理器几乎可以处理任何类型的文件(C#,C ++,HTML,PHP,Java等)。如果使用IDE(例如OR),则可以继续使用它来开发应用程序并将文件检查到源控件中。

源代码管理器架构提供了一个本地工作区,以存储源代码的本地副本。在连接断开模式下,所有修改都可以在此工作区中执行。重新连接后,只需检查代码并将其推到服务器以保留所有版本的完整历史记录,以便您可以跟踪和回滚更改。

与团队的合作,开发人员可以通过称为任务板的工具更好地共同努力。可以从允许创建自定义仪表板的任何当前浏览器访问任务板。您可以使用任务板来管理有关工作项目,构建状态,测试结果等的信息,如图1所示。

Sample Dashboard for Team Foundation Service

图1团队的样品仪表板

在写作时构建服务,构建服务仍处于预览阶段,根据TFS 2010的团队构建,可以通过云提供自动生成功能。

团队构建的所有标准功能均可用于发电服务,包括连续集成,夜间构建和门户入住式构建。此外,它使用的生成模板是完全可自定义的。您甚至可以使用“现成”模板在Azure上连续部署(您可以将代码检查到源控件中,然后在Azure网站上查看其更新)。

该构建服务托管在由2008 R2,Team Build,2010年或更晚的构建服务器上托管(请参阅此页面底部所需的软件和选项的完整列表:bit.ly/)。默认配置适用于大多数应用程序,除了App Store App。如图2所示,存储应用程序需要在8(或2012年)上构建,并且不安装在构建服务器上。

图2无法直接在团队上构建App Store应用程序

好吧,如前所述,我们无法使用团队直接构建App Store应用程序。但是,如您所见,可以以一种方式解决此问题。实际上,解决方法涉及安装8台计算机,该计算机将成为一个新的构建代理,致力于通过团队构建商店应用程序。我将解释如何实现此方法。

与团队建立应用程序商店应用程序

下面,让我们看一下使用团队构建App Store应用程序所需的步骤。

首先安装生成​​服务,您需要运行8的计算机。它可以是物理机器或虚拟机(VM);只要可以从计算机访问。然后,在该计算机上安装TFS 2012。请注意,安装TFS并不意味着它已配置和可用。安装的唯一原因是能够配置构建服务。您不需要获得团队,这是因为团队已经可用。

安装构建服务后,可以使用专用的团队项目集合进行配置。在这种情况下,由于没有设置其他TFS组件并要使用团队,因此您需要指定可用于团队帐户的团队项目的集合,然后完成配置,如图3所示。

Installing the Team Foundation Build Service in a Dedicated Team Projects Collection

图3在专门的团队项目集合中安装团队生成服务

在下一节中配置生成服务,您需要了解有关TFS及其生成体系结构的一些基本知识。

每个TFS都有一组专用的发电机控制器。生成控制器是一个端点,它将接收生成请求并使用专用的生成代理执行请求。生成代理中最重要的工作是执行生成:它从源代码控制,编译代码,执行单元测试等。

团队配备了专用的构建控制器,这是一个托管构建控制器,因此您可以考虑仅创建使用此控制器运行的新代理。不幸的是,您不能将内部构建代理附加到托管构建控制器上。您需要选择另一个构建控制器或创建新的构建控制器。

为简单起见,我们创建了一个新的发电机控制器,如图4所示。

Creating a New Build Controller

图4创建一个新的发电机控制器

控制器启动并运行后,下一步是创建一个专门用于构建商店应用程序的新代理。创建新生成的代理非常简单。只需单击“新代理”链接并填写相应的字段。在真实的生产环境中,可能有多种代理来生成控制器。为了确保存储应用程序仅由在8上运行的代理构建,请添加一个专用标签,如图5所示。这不是必需的,但是稍后创建构建定义时,您需要指定此标签以确保仅使用该代理仅执行构建过程。

Creating a New Build Agent

图5创建新一代代理

在继续下一步之前,您需要转到生成服务属性并将其设置为交互。如果您只想构建App Store应用程序,则不需要此步骤。但是,如果要验证应用程序,则需要在构建机器上安装并启动它们以使用团队和构建服务;如果不配置为交互性运行,则无法实现这一点。

在团队资源管理器的构建页面上,单击操作,然后单击“管理构建控制器”以打开已安装的所有构建控制器(及其专用代理)的窗口。如果配置成功,您可以看到新的控制器和代理。

准备生成代理以运行单元测试,如果将生成代理的计算机用于执行单元测试,则需要两个其他步骤。首先,必须在该计算机上安装8个开发人员许可证。开发人员许可证可以免费获得,但需要每30天续订每30天(如果您有App Store帐户,则需要90天);如果您已经有一个帐户,则可以根据需要获得多个此类许可证。有两种获得开发人员许可证的方法。在构建计算机上,只需创建一个App Store应用程序即可打开一个对话框,您可以从中获得有效的许可证。如果您不想在发电机计算机上创建假应用程序,则可以运行以下命令以显示对话框:

C:\PS> Show-WindowsDeveloperLicenseRegistration

获得开发人员许可证后,您需要在发电机上生成和安装单元测试证书(来自包含要运行的单元测试的代码项目)。在此步骤中,需要在开发人员的计算机上生成应用程序包。在,单击应用商店|创建应用程序包。这将创建一个包含存储应用程序(带有扩展名.APPX的文件中)及其证书的文件夹。

要在生成的计算机上安装证书,请以管理员的身份打开命令提示符,然后输入以下命令:

certutil -addstore root certificate_file

请注意,这是证书文件的途径。

在运行控制器和代理后,构建App Store应用程序,构建App Store应用程序,该应用程序与构建其他类型的应用程序相同。您只需要创建一个新的构建定义并指定要使用刚刚设置的新构建控制器。为了确保构建过程使用“生成定义”选项卡中运行的构建代理,请在创建构建代理时选择指定的标记(请参见图6)。

Creating the Build Process Using the Specified Tag

图6使用指定标签创建一个生成过程

完成此操作后,将新构建与您刚刚创建的构建定义排队并开始。由于有一个指定的标签,因此您可以确保使用正确的代理执行新构建,因此不会失败。

如您所见,使用团队构建应用程序商店的过程非常简单,但是它非常强大,您可以完全自定义构建过程。但是,仍然存在问题。即使这一代人成功,也不意味着该应用程序将正确运行,甚至可以通过所有基本验证步骤。接下来,我将说明如何验证应用程序以及如何向用户指示(通过生成报告)是否传递或失败。

在团队项目生成期间验证应用商店应用程序

您可能知道要发布到App Store,必须验证该应用程序。也就是说,应用程序必须通过所需的验证步骤。您可以在生成过程中验证应用程序。只需添加一个后生成事件即可轻松验证,该事件将启动应用程序身份验证软件包(ACK)以验证应用程序。但是,验证完成后,将不会通知用户结果。我将解释如何扩展生成过程以包括此步骤。

要在构建过程中包括ACK执行,只需修改项目文件即可添加以下内容:

          

执行后,代码创建文件.html,其中包含ACK执行的验证结果。如果执行构建时连接到构建服务器,则可以看到将启动应用程序以进行ACK验证。这是正常的;测试完成后,将安装,验证,然后自动删除该应用程序。请注意,构建服务配置为交互式运行,因此可以安装和执行应用程序。如果没有这样的配置,则会在构建过程中出现错误。

生成过程本身不受验证结果的影响,因此用户需要检查测试结果以查看应用程序是否有验证错误。幸运的是,您可以改进报告的生成,以便让用户知道验证中是否有任何错误。让我们看一下如何自定义生成报告以包括ACK工具的验证结果。

自定义生成报告ACK创建HTML文件和XML文件,然后将其保存在所选文件夹中。您可以使用此XML文件来创建自定义工作流活动,该活动将修改生成的报告以通知用户验证结果。

创建此活动的代码非常简单。该代码寻找XML文件(包括验证结果),读取文件以找到“”属性的值并返回值。图7显示了创建活动性viity的代码。

图7 vity

[BuildActivity(HostEnvironmentOption.All)] public sealed class CheckWackResultsActivity : CodeActivity {   [RequiredArgument]   public InArgument DropLocation { get; set; }   [RequiredArgument]   public InArgument WackResultsFilename { get; set; }   [RequiredArgument]   public InArgument WackReportFilename { get; set; }   public OutArgument WackReportFilePath { get; set; }   // If your activity returns a value, derive from CodeActivity   // and return the value from the Execute method.
protected override bool Execute(CodeActivityContext context)   {     string dropLocation = context.GetValue(this.DropLocation);     string wackResultsFilename =       context.GetValue(this.WackResultsFilename);     string wackReportFilename = context.GetValue(this.WackReportFilename);     var dropLocationFiles = Directory.GetFiles(dropLocation, "*.*",       SearchOption.AllDirectories);     if (dropLocationFiles.Any())     {       var resultFile = dropLocationFiles.FirstOrDefault(         f => Path.GetFileName(f).ToLowerInvariant() ==           wackResultsFilename.ToLowerInvariant());       if (!string.IsNullOrWhiteSpace(resultFile))       {         var xDocument = XDocument.Load(resultFile);         var reportElement = xDocument.Element("REPORT");         if (reportElement != null)         {           var resultAttribute = reportElement.Attribute("OVERALL_RESULT");           if (resultAttribute != null)           {             context.SetValue(this.WackReportFilePath,               Path.GetDirectoryName(resultFile));             var validationResult = resultAttribute.Value;             // Fail or Pass             if (validationResult.ToLowerInvariant() == "fail")             {               return false;             }             return true;           }         }       }       throw new InvalidOperationException(         "Unable to find the Windows App Certification Kit results file!");     }     else     {       throw new InvalidOperationException(         "There are no files in the drop location!");     }     throw new InvalidOperationException(       "Unknow error while checking the content of the Windows App       Certification Kit results file!");   } }

默认情况下,构建活动在构建代理上运行。但是在某些情况下,您可能希望该活动尽早将其作为第一步执行,甚至在构建启动之前,或者您可能希望将活动作为构建结束之前的最后一步执行。为了实现此灵活性,您需要在控制器上而不是代理上运行活动。因此,应使用特征TE,以将枚举值n作为参数(如图7所示)。请注意,如果未使用正确的主机选项,则在构建过程中会收到错误。

类Vity从代码继承,因此可以使用其结果值在生成的报告中显示正确的消息。要显示此消息,您可以使用TFS 2012:FO中提供的新活动。此活动对于在生成的报告中添加消息很有用,因为它允许您在生成的报告中添加专用类别,而不是添加简单的文本。

您必须指定以下属性:

因此,通过使用新的活动FO,可以修改生成过程以检查验证结果,并可以将新部分添加到生成报告中。图8显示了修改生成过程的XAML代码。

图8修改后的生成过程

                                                             Foundation.Build.Client.BuildPhaseStatus.Failed]"           DisplayName="Set Status and CompilationStatus to Failed"           sap2010:WorkflowViewState.IdRef="SetBuildProperties_1"           mtbwt:BuildTrackingParticipant.Importance=             "Low" PropertiesToSet="CompilationStatus" />                                 

如图8所示,如果验证失败,则将汇编状态设置为“失败”,以防止生成过程继续执行。这不是必需的,如果您想始终完成生成过程,无论验证结果如何,都可以删除。

现在,每次发生触发器时,生成的报告都会显示一个专用于8的新部分,该部分显示了验证的结果(见图9)。

The New Section in the Build Report Showing Validation Results

图9。生成一个新部分,显示验证在报告中导致

使用FO时,您只能使用文本和链接来改善报告的生成。如果需要进行更复杂的修改(例如,添加图像),仍然可以应用TFS 2010中使用的方法。

有很多方法可以自定义App Store应用程序的生成过程模板,很高兴这些自定义方法与团队和内部TFS基本相同。

它是法国合作伙伴的技术负责人,该公司致力于开发包括8/电话,团队等的技术。他已经在模型视图模型模型上写了两本法国书籍,他也经常在法国举行的活动中讲话。您可以访问他的博客或关注他/。

感谢以下技术专家审查本文:Chris()

标签: Foundation
首页
欧意注册
欧意下载
联系