本文章是由機器翻譯。

TFS

使用 Team Foundation Service 構建和驗證 Windows 應用商店應用程式

Thomas LeBrun

 

自 2012 年 10 月推出最終版本以來,Visual Studio Team Foundation Server (TFS) 的雲版本 Team Foundation Service 提供了大量功能,可説明你提供高品質的軟體。開發出面向 Windows 8 的軟體這一願望將不再遙不可及。

你可能想知道兩個產品是否可以強強聯合,即使用 Team Foundation Service 來構建 Windows 應用商店應用程式。很遺憾,由於存在一些限制,目前這一點還無法直接實現,本文後面將進行介紹。不過,我也會介紹避開這一問題所需要的步驟,説明你在構建過程中驗證 Windows 應用商店應用程式。

首先,讓我們快速瞭解一下 Team Foundation Service。

Overview of Team Foundation Service

作為一項基於雲的服務,Team Foundation Service 允許開發者訪問 TFS 提供的功能,而不必費力地安裝和管理 TFS。只需在 bit.ly/ZusqUY 註冊(免費!),你就可以開始了。

在該產品提供的服務中,你可能將重點使用三個主要功能來開發和提供高品質的軟體:

原始程式碼管理你可以在當前工具和首選語言保持不變的情況下使用原始程式碼管理功能,原始程式碼管理器可處理幾乎任何種類的檔(C#、C++、HTML、PHP、JAVA 等)。如果使用 IDE(如 Visual Studio 或 Eclipse),可以繼續使用它來開發應用程式以及將檔簽入原始程式碼控制。

原始程式碼管理器體系結構提供本地工作區來存儲原始程式碼的本機複本。在連接斷開模式下,可以在此工作區中執行所有修改。重新連接後,只需簽入代碼,將其推送到伺服器,即可保留所有版本的完整歷史記錄,因此你可以跟蹤和回滾更改。

協作借助 Team Foundation Service,開發者可以更好地協同工作,主要通過一個稱為任務板的工具實現。可以從任何允許創建自訂儀表板的當前瀏覽器訪問任務板。你可以使用任務板管理有關工作項的資訊、構建狀態、測試結果等,如圖 1 所示。


圖 1 Team Foundation Service 的示例儀表板

生成服務在撰寫本文時,生成服務仍處於預覽階段,它基於屬於 TFS 2010 的 Team Build,通過雲提供自動生成功能。

Team Build 的所有標準功能都可供生成服務使用,其中包括連續集成、每夜構建和閘道簽入構建。此外,它使用的生成範本可完全自訂。甚至可利用一個「現成的」範本在 Windows Azure 上進行連續部署(你可以將代碼簽入原始程式碼管理,然後在 Windows Azure 網站上查看其更新)。

生成服務承載于使用 Windows Server 2008 R2、Team Build、Visual Studio 2010 或更高版本部署的生成伺服器上(請參見本頁底部的必需軟體和選項的完整清單:bit.ly/12Sf99Z)。預設配置適合大部分應用程式,但 Windows 應用商店應用程式除外。如圖 2 所示,Windows 應用商店應用程式需要在 Windows 8(或 Windows Server 2012)上構建,它們並未安裝在生成伺服器上。


圖 2 無法直接使用 Team Foundation Service 上構建 Windows 應用商店應用程式

那麼,如前文所述,我們無法直接使用 Team Foundation Service 構建 Windows 應用商店應用程式。但是,正如你將看到的那樣,這個問題可以通過一個方法得到解決。實際上,該解決方法包括安裝 Windows 8 電腦,這台電腦將成為新的生成代理,專用於通過 Team Foundation Service 構建 Windows 應用商店應用程式。我將說明如何實現該方法。

使用 Team Foundation Service 構建 Windows 應用商店應用程式

下面,我們來看一下使用 Team Foundation Service 構建 Windows 應用商店應用程式所需的步驟。

安裝生成服務首先,你需要一台運行 Windows 8 的電腦。它可以是物理機或虛擬機器 (VM);只要可從 Internet 訪問該電腦就行。然後,在該電腦上安裝 TFS 2012。請注意,安裝 TFS 並不意味著它已配置好且可供使用。需要安裝的唯一原因是要能夠配置生成服務。你無需獲取 Team Foundation Application Server,這是因為 Team Foundation Service 已提供。

在生成服務安裝完成後,可以使用專用團隊專案集合對其進行配置。這種情況下,因為不設置其他 TFS 元件並且要使用 Team Foundation Service,所以需要指定可用於 Team Foundation Service 帳戶的團隊專案集合,然後完成配置,如圖 3 所示。


圖 3 在專用團隊專案集合中安裝 Team Foundation 生成服務

配置生成服務在下一部分中,你需要瞭解有關 TFS 及其生成體系結構的一些基本知識。

每個 TFS 都有一組專用組建控制器。組建控制器是將使用專用生成代理接收生成請求並執行請求的端點。生成代理執行生成中最重要的工作:它從原始程式碼控制獲取檔、編譯代碼、執行單元測試等等。

Team Foundation Service 附帶專用組建控制器 — 託管組建控制器,因此,你可以考慮只創建新代理來使用此控制器運行。很遺憾,你不能將內部生成代理附加到託管組建控制器。你需要選擇其他組建控制器或創建新的組建控制器。

為簡單起見,我們創建一個新的組建控制器,如圖 4 所示。


圖 4 創建新的組建控制器

在控制器啟動並運行後,下一步是創建專門用於構建 Windows 應用商店應用程式的新代理。創建新生成代理十分簡單,只需按一下「新建代理」連結並填寫相應欄位。在實際生產環境中,可能有多個代理用於組建控制器;為了確保 Windows 應用商店應用程式僅由 Windows 8 上運行的代理構建,請添加一個專用標記,如圖 5 所示。這不是必需的,但在之後創建組建定義時,將需要指定此標記以確保只使用此代理執行生成過程。


圖 5 創建新的生成代理

在進行下一環節之前,需要轉至生成服務屬性並將其設置為以對話模式運行。如果只想構建 Windows 應用商店應用程式,則此步驟並不是必需的。但是,如果要驗證應用程式,需要將這些應用程式安裝在生成電腦上並啟動才能使用 Team Foundation Service 和生成服務;如果生成服務未配置為以對話模式運行,則無法實現這一點。

在 Visual Studio Team 總管的「生成」頁上,依次按一下「操作」和「管理組建控制器」以打開一個視窗,其中列出了已安裝的所有組建控制器(及其專用代理)。If the configuration was successful, you should see your new controller and agent.

準備生成代理以運行單元測試如果承載生成代理的電腦將用於執行單元測試,則還需要執行另外兩個步驟。首先,必須在該電腦上安裝 Windows 8 開發者許可證。開發者許可證免費獲取,但需要每 30 天(如果有 Windows 應用商店帳戶,則為 90 天)續訂一次;如果已有 Microsoft 帳戶,可根據需要獲取多個這樣的許可證。有兩種方法可獲取開發者許可證。在生成電腦上,只需創建 Windows 應用商店應用程式即可打開一個對話方塊,可以從中獲取有效的許可證。如果不想在生成電腦上創建一個虛假應用程式,可以運行以下 Windows PowerShell 命令以顯示該對話方塊:

C:\PS> Show-WindowsDeveloperLicenseRegistration

在獲得開發者許可證後,需要在生成代理上生成並安裝一個單元測試證書(從包含要運行的單元測試的代碼專案中)。 在這一步驟中,需要在開發者電腦上生成一個應用程式包。 在 Visual Studio 中,按一下「應用商店」|「創建應用程式包」。 這會創建一個資料夾,其中包含 Windows 應用商店應用程式(位於副檔名為 .appx 的檔中)及其證書。

要在生成電腦上安裝該證書,請以管理員身份打開命令提示符,輸入以下命令:

certutil -addstore root certificate_file

請注意,certificate_file 是證書檔的路徑。

構建 Windows 應用商店應用程式在運行控制器和代理後,構建 Windows 應用商店應用程式,這與構建其他種類的應用程式一樣。你只需創建一個新組建定義並指定要使用剛設置好的新組建控制器。為確保生成過程使用在 Windows 8 上運行的生成代理,請在組建定義的「過程」選項卡中,選擇在創建生成代理時所指定的標記(參見圖 6)。


圖 6 使用指定標記創建生成過程

完成此操作後,使用剛創建的組建定義對新生成進行排隊,然後啟動它;因為有指定的標記,可以確保新生成是使用正確代理執行的,因而不會失敗。

可以看到,使用 Team Foundation Service 構建 Windows 應用商店應用程式的過程極其簡單,但其功能十分強大,你可以完全自訂生成過程。不過,仍存在一個問題。即使生成成功,也並不意味著應用程式將正常運行,甚至也不意味著它將通過所有基本驗證步驟。接下來,我將說明如何驗證應用程式以及如何向使用者指示(通過生成報告)驗證是通過還是失敗。

團隊專案生成期間驗證 Windows 應用商店應用程式

你可能知道,若要發佈到 Windows 應用商店,必須驗證應用程式。也就是說,應用程式必須通過必需的驗證步驟。你可以在生成過程中驗證應用程式。只需添加生成後事件即可輕鬆地驗證,該事件將啟動 Windows 應用程式認證包 (ACK) 來驗證應用程式。但是驗證完成時,並不會向使用者通知結果。我將說明如何擴展生成過程以包含此步驟。

要在生成過程中包含 ACK 執行,只需修改專案檔案添加以下 PostPackageEvent:

<Target Name="PostPackageEvent" AfterTargets="_GenerateAppxPackage">
  <Exec Command="'$(TargetPlatformSdkPath)App Certification Kit\appcert.exe' reset"/>
  <Exec Command="'$(TargetPlatformSdkPath)\App Certification Kit\appcert.exe' test -apptype windowsstoreapp -AppxPackagePath '$(FinalAppxPackage)' –reportoutputpath '$(outdir)\ValidationResult.xml'" />
  <Exec Command="copy '$(userprofile)\appdata\Local\Microsoft\appcertkit\ValidationResult.htm' '$(outdir)\ValidationResult.htm'"/>
</Target>

執行時,代碼將創建檔 ValidationResult.html,該檔包含 ACK 所執行驗證的結果。 如果在生成執行時連接到生成伺服器,可以看到將啟動應用程式以供 ACK 驗證。 這是正常現象;將安裝、驗證應用程式,然後在測試完成後自動將其刪除。 請注意,生成服務已配置為以對話模式運行,因此可以安裝和執行應用程式。 如果尚未這樣配置,則在生成期間會出現錯誤。

生成過程本身不會受驗證結果的影響,因此使用者需要檢查測試結果才能瞭解應用程式是否出現驗證錯誤。 幸運的是,你可以改進生成報告,讓使用者瞭解驗證是否出現任何錯誤。 讓我們看一下如何自訂生成報告,以包含 ACK 工具的驗證結果。

自訂生成報告 ACK 創建一個 HTML 檔案和一個 XML 檔,將它們保存在所選的資料夾中。 你可以使用此 XML 檔創建一個將修改生成報告的自訂工作流活動,以向使用者通知驗證結果。

創建此活動的代碼十分簡單。 該代碼會查找 XML 檔(包含驗證結果)、讀取該檔以查找「OVERALL_RESULT」特性的值,然後返回該值。 圖 7 顯示了創建活動 CheckWackResultsActivity 的代碼。

圖 7 CheckWackResultsActivity

[BuildActivity(HostEnvironmentOption.All)]
public sealed class CheckWackResultsActivity : CodeActivity<bool>
{
  [RequiredArgument]
  public InArgument<string> DropLocation { get; set; }
  [RequiredArgument]
  public InArgument<string> WackResultsFilename { get; set; }
  [RequiredArgument]
  public InArgument<string> WackReportFilename { get; set; }
  public OutArgument<string> WackReportFilePath { get; set; }
  // If your activity returns a value, derive from CodeActivity<TResult>
  // 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!");
  }
}

預設情況下,組建活動在生成代理上運行。但是在某些情況下,你可能希望該活動作為第一步儘早執行,甚至在生成開始之前執行,或者希望該活動作為生成結束之前的最後一步執行。為了實現這種靈活性,你需要讓活動在控制器而不是代理上運行。因此,應使用特性 BuildActivityAttribute,它將枚舉值 HostEnvironmentOption.All 作為參數(如圖 7 所示)。請注意,如果未使用正確的 Host­EnvironmentOption 選項,在生成過程中會收到錯誤。

類 CheckWackResultsActivity 從 Code­Activity<bool> 繼承,以便其結果值可用於在生成報告中顯示正確的消息。要顯示此消息,可以使用 TFS 2012 中提供的一個新活動: WriteCustomSummaryInfo.要向生成報告添加消息,則此活動十分有用,因為通過它可以在生成報告中添加專用類別,而不是添加簡單的文本。

你必須指定以下屬性:

  • Message,它是要顯示在報告中的文本
  • SectionDisplayName,它與節標題相對應
  • SectionKey,它是節的唯一值
  • SectionPriority,它定義新節在報告中的位置(0 表示最高優先順序,標準節從 100 開始)

因此,通過使用新活動 WriteCustomSummaryInfo,可以修改生成過程以檢查驗證結果,並在生成報告中添加一個新節。圖 8 顯示了修改後的生成過程的 XAML 代碼。

圖 8 修改後的生成過程

<Sequence DisplayName="Windows 8" sap2010:WorkflowViewState.IdRef="Sequence_4">
  <Sequence.Variables>
    <Variable x:TypeArguments="x:Boolean" Name="WackToolRanSuccessfully" />
    <Variable x:TypeArguments="x:String" Name="WackReportFilePath" />
  </Sequence.Variables>
  <c:CheckWackResultsActivity DropLocation="[DropLocation]"
    sap2010:WorkflowViewState.IdRef="CheckWackResultsActivity_3"
    Result="[WackToolRanSuccessfully]"
    WackReportFilePath="[WackReportFilePath]"
    WackReportFilename="ValidationResult.html"
    WackResultsFilename="ValidationResult.xml" />
  <If Condition="[Not WackToolRanSuccessfully]"
    sap2010:WorkflowViewState.IdRef="If_4">
    <If.Then>
      <Sequence sap2010:WorkflowViewState.IdRef="Sequence_6">
        <mtbwa:WriteCustomSummaryInformation
          sap2010:WorkflowViewState.IdRef=
            "WriteCustomSummaryInformation_2"
          Message="['Windows App Certification Kit ran with errors.
Click [here](' &amp; WackReportFilePath &amp; ') to
          access the folder containing the report.']"
          SectionDisplayName="Windows 8" SectionKey="Windows8"
            SectionPriority="75"
          mva:VisualBasic.Settings=
            "Assembly references and imported namespaces
            serialized as XML namespaces" />
        <mtbwa:WriteBuildError
          sap2010:WorkflowViewState.IdRef="WriteBuildError_1"
          Message="Windows App Certification Kit ran with errors." />
        <mtbwa:SetBuildProperties
          CompilationStatus=
            "[Microsoft.TeamFoundation.Build.Client.BuildPhaseStatus.Failed]"
          DisplayName="Set Status and CompilationStatus to Failed"
          sap2010:WorkflowViewState.IdRef="SetBuildProperties_1"
          mtbwt:BuildTrackingParticipant.Importance=
            "Low" PropertiesToSet="CompilationStatus" />
      </Sequence>
    </If.Then>
    <If.Else>
      <mtbwa:WriteCustomSummaryInformation
        sap2010:WorkflowViewState.IdRef="WriteCustomSummaryInformation_1"
        Message="['Windows App Certification Kit ran with success.
Click [here](' &amp; WackReportFilePath &amp; ') to
        access the folder containing the report.']"
        SectionDisplayName="Windows 8" SectionKey="Windows8"
          SectionPriority="75"
        mva:VisualBasic.Settings=
          "Assembly references and imported namespaces
          serialized as XML namespaces" />
    </If.Else>
  </If>
</Sequence>

圖 8 中可以看到,如果驗證失敗,則編譯狀態設置為「失敗」以防止生成過程繼續執行。這不是必需的,如果希望無論驗證結果如何都始終完成生成過程,可以將其刪除。

現在,每次觸發生成時,生成報告都會顯示一個專用於 Windows 8 的新節,該節顯示驗證的結果(請參見圖 9)。


圖 9 生成報告中顯示驗證結果的新節

使用 WriteCustomSummaryInfo 時,只能用文本和連結改進生成報告。如果需要進行更複雜的修改(例如,添加圖像),仍可以應用 TFS 2010 中使用的方法。

有許多方法可以為 Windows 應用商店應用程式自訂生成過程範本,值得高興的是,這些自訂方法與用於 Team Foundation Service 和內部 TFS 的基本相同。

Thomas Lebrun 是 Microsoft 法國合作夥伴 Infinite Square 的技術主管,該公司致力於開發包括 Windows 8/Windows Phone、Team Foundation Server、SharePoint 等在內的技術。Lebrun 編寫了兩本 Windows Presentation Foundation 和模型-視圖-視圖模型模式方面的法文書籍,他也經常在法國舉辦的活動中發表演講。你可以在 blog.thomaslebrun.net 上訪問他的博客,也可在 Twitter twitter.com/thomas_lebrun 關注他。

衷心感謝以下技術專家對本文的審閱:Chris Patterson (Microsoft)