[.NET Conf 2019]のデスクトップアプリケーションでのAzureDevOpsの活用のセッションを日本語訳した（WindowsデスクトップアプリケーションのためのDevOpsとVisual Studio App Centerを始めよう）

この投稿は、[.NET Conf 2019](https://www.dotnetconf.net)（2019/9/23-25）のセッションを日本語訳し文章に起こしたものです。正確なところは、実際のセッションをご確認ください。

Get Started with DevOps for .NET Windows Desktop Apps and Visual Studio App Center
https://www.youtube.com/watch?v=8ioUk4RajpM

<blockquote class="twitter-tweet"><p lang="und" dir="ltr"><a href="https://t.co/dyg610LUxo">https://t.co/dyg610LUxo</a></p>&mdash; tfukumori_qiita (@TfukumoriQ) <a href="https://twitter.com/TfukumoriQ/status/1183333760441311232?ref_src=twsrc%5Etfw">October 13, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 1. TL;DR（要約）

- DevOpsとは何か
- .NET Core デスクトップアプリケーションを展開(Deploy)する方法
- Visual Studio App Centerで確認できること
- ロードマップと関連資料

## 関連スライド: .NET Conf 2019 のデスクトップアプリに関するセッションについて

https://www.slideshare.net/TakuhiroFukumori1/net-conf-2019-182733170

このイベント時に作成

https://kagoshima-dotnet.connpass.com/event/149260/

# 2. DevOpsを行う企業の高いパフォーマンス

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/e79f9c4f-d7d4-7c02-2c14-549b23cf3b0e.png)

DevOpsを行う企業では、コードをより早くリリースすることができ、バグをより少なくすることができ、最終的には、収益と利益をあげることができる。

しかし、デスクトップアプリケーション開発者の中では、DevOpsに対する議論が長らく行われてこなかったように感じる。
Webおよびサーバーアプリケーションの展開、さらにはモバイルアプリでは議論されてきたが、デスクトップアプリケーションでは、議論されてこなかった。
なので、本日はデスクトップアプリケーションのDevOpsについて喋る。

# 3 .NET Core Windows アプリケーションの展開

- 異なる.NET Coreバージョンのアプリケーションの実行（Side-by-side）

- MSIX パッケージングによる自己完結型のアプリケーション

    https://www.itmedia.co.jp/pcuser/articles/1806/07/news110.html
    https://docs.microsoft.com/ja-jp/dotnet/core/whats-new/dotnet-core-3-0#msix-deployment---windows-desktop

- 単一の実行ファイル(.exe)でのコンパイル

今回は、デモをシンプルにするために、単一の実行ファイル(.exe)を使用してデモを行う。

今までなら、例えばUSBメモリでテスト用のアプリケーションを渡されたかもしれない。今回は、その代わりとなる方法を示す。


# 4. 概要

## 4-1. デモで使用するソース、サービス等

GitHub デモで使用したアプリケーション
https://github.com/diverdan92/DotNetConf2019

Azure DevOps
https://dev.azure.com/

Visual Studio App Center
https://appcenter.ms/

## 4-2. 概略図

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/216104d5-59b1-facf-b8dd-bbe501162005.png)

- リポジトリにAzure DevOpsを使用することも可能
- App Centerでビルドすることも可能だが、アプリケーションによってはビルドできないこともある。
- 今回は、デスクトップアプリケーションに関する記述だが、AzureにホストしたWebアプリなら、自動的に[Application Insights](https://www.google.com/search?q=Azure+Application+Insite&ie=&oe=)が組み込まれている。

## 4-3. 費用

### GitHub

https://forest.watch.impress.co.jp/docs/news/1161195.html

無料枠あり。

### Azure DevOps

https://azure.microsoft.com/ja-jp/pricing/details/devops/azure-devops-services/

無料枠あり。

また、Visual Studio Subscription を契約しているなら、無償で Azure DevOps を利用できます。

### Visual Studio App Center

https://azure.microsoft.com/ja-jp/pricing/details/app-center/

無料枠あり。

また、Visual Studio Subscription を契約しているなら、[無償で Azure App Centor を利用](https://docs.microsoft.com/ja-jp/visualstudio/subscriptions/vs-visual-studio-app-center)できます。

# 5. Azure DevOpsでの発行と、App Centerとの連携の組み込み

WPFのアプリケーションだが、友人からクラッシュした、という連絡を受けた、というシナリオでやっていく。

## 5-1. 手順：Azure DevOpsでの発行

1. [GitHub]GitHubを自分のアカウントにフォークする

    https://github.com/diverdan92/DotNetConf2019

2. [AzDevOps]自分のAzure DevOpsでに新規にプロジェクトを作成する
3. [AzDevOps]BuildでNew Pipelineを選択し、GitHubを選択する。既にGitHubと連携済みであれば、認証は自動的に行われる
4. [AzDevOps]新規パイプラインとして、".NET Desktop"を選択する。すると.NET デスクトップアプリケーションをビルドするための設定が開かれる。

    1. triggerとして、ビルドに使用するブランチを選択する
    2. poolは、ビルドに使用するAzure内の仮想マシンのイメージを示す
    3. variablesとして、solutionとbuildplatformを削除し、以下を追加する。ビルドの使用するVMマシンは、ビルドが終わると捨てられるため、キャッシュする処理は不要。

        ```yaml
            DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
        ```

    4. "steps:"の次の行以降を削除する。なぜなら、今回は.NET Core用にゼロから設定するためとなる。

        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/db3156d7-ff47-b1e3-0a52-a91673eeeae9.png)


    5. .NET Core SDKをインストールするステップ

        1. Tasksで`use .net core`を検索し、"Use .NET Core"をクリックして追加する。

            ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/11ff4340-dc31-014d-cce9-4cf008e6d19a.png)

        2. Versionに`3.0.x`を入力する。本日リリースされたので、Include Preview Versionsにチェックする必要はない。

            ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/ded2e127-b4b6-a369-f60c-d74cabc90cbd.png)

        3. Addボタンをクリックすると、追加される。

            ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/7aa78740-02c8-b701-584a-171f7e918122.png)

        この記述で仮想マシンに.NET Core 3.0.xのSDKがインストールされる。

    5. .NET Coreを発行するステップ

        1. ".NET Core"をクリックして追加する。

            ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/bebec244-e295-15fe-a221-44f3af25fc84.png)

        2. Commandとして、`publish`を選択し、Public Web Projectsのチェックを外す。Zip Published Projectsのチェックを外す

            ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/0bf88961-9d69-d0ed-2992-aa8745c7ae4a.png)

        3. Addボタンをクリックすると、追加される。

        4. .NET Core CLIコマンドを使用するためにオプションのパラメーターを追加する

            インターフェイスを介して追加することもできるが、手でコードを追加する方がわかりやすい。ビルドアーティファクトの出力を指定するが、Azure DevOpsに用意された構成変数`Build.ArtifactStagingDirectory`を使用する。

            ```yaml
                arguments: --output $(Build.ArtifactStagingDirectory)
            ```

        この時点でdotnet publishを使用して自己完結型のexeが生成される。


    6. 成果物を発行する

        1. Tasksで`publish pipeline`を検索し、"Publish pipeline artifact"をクリックして追加する。

            ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/e8481e28-c7a2-09bd-b923-bece485b827b.png)

        2. File or directory pathに先ほど入力した出力先を入力する

            ```
            $(Build.ArtifactStagingDirectory)
            ```

        3. nameには、ダウンロードする際に表示する名称を入力する

            ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/730c7a41-2a60-b3f1-555e-29f4145d313b.png)


        4. Addボタンをクリックすると、追加される。

    8. この時点の最終的なyaml

        ```yaml:azure-pipelines.yml
        trigger:
        - master
        
        pool:
          vmImage: 'windows-latest'
        
        variables:
          DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
          buildConfiguration: 'Release'
        
        steps:
        - task: UseDotNet@2
          inputs:
            packageType: 'sdk'
            version: '3.0.x'
        - task: DotNetCoreCLI@2
          inputs:
            command: 'publish'
            publishWebProjects: false
            zipAfterPublish: false
            arguments: --output $(Build.ArtifactStagingDirectory)
        - task: PublishPipelineArtifact@1
          inputs:
            targetPath: '$(Build.ArtifactStagingDirectory)'
            artifact: 'Calculator'
        ```

    9. Save and run を実行する。

        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/80f459f0-d91c-bf8d-1ba0-f2fefb537065.png)

        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/20eaa481-8e2e-5193-b3a9-83a2b3ad98a1.png)

        この処理により、GitHubのリポジトリに、azure-pipelines.ymlファイルが書き込まれる。

    10. Azure DevOpsではビルドと発行が実行される

        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/3a9c6131-2388-e67b-4ca4-210ba0f260e4.png)

        実行結果についてはログ等を確認できる。


## 5-2. 手順：App Centerでの分析と解析の組み込み


1. [AppCenter]アプリケーションを作成する

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/1f3d7b46-d166-560f-be54-ceb741a53baa.png)

    OSにWindows、PlatformにWPFを選択する

2. [VisualStudio]OverViewの説明に従い、MainWindow.xaml.csを書き換える（Overviewの説明では、App.xaml.cs）。

    1. Usingの追加と、コンストラクタメソッドへのコードの追加（サンプルを使用した場合は、既にデモのキーが書き込まれているので、置き換える）

        ```cs:usingステートメント
        using Microsoft.AppCenter;
        using Microsoft.AppCenter.Analytics;
        using Microsoft.AppCenter.Crashes;
        ```

        ```cs:コンストラクタ
        AppCenter.Start("XXXXXXXX-YYYY-ZZZZ-AAAA-99999",
                   typeof(Analytics), typeof(Crashes));
        ```

        これで開発環境で実行して、数秒すると、AppCenterのAnalyticsに起動したことが反映される。
Eventsでは、クラッシュしたことなども確認できる。

        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/9021992e-fe13-10db-1b9b-d7617a2d237a.png)

    2. イベントとクラッシュ情報を書き込むには、以下のコードが必要。サンプルでは、すべて組み込まれている（セッション動画でも、コンストラクタのコード以外は記載済みだった）
        
        以下のコードで、AppCenterのAnalytics - Eventに記載、集計される。

        ```cs:ボタンクリック等に記載
        Analytics.TrackEvent("Pressed Equals");
        ```

        以下のコードをCatchブロックに記載すると、AppCenterのDiagnosticsに記載、集計される。


        ```cs:Catchブロックに記載
	    Crashes.TrackError(e, new Dictionary<string, string>() { { "Equation: ", equation } });
        ```

3. [VisualStudio]ビルドできることを確認後、チームエクスプローラーの変更から「すべてをコミットして同期」を選択し、masterブランチに変更をコミットし、変更をリモートリポジトリと同期する。

    Azure DevOpsのパイプラインでは、自動的にビルドされる。

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/99e2dcb6-5dc8-51eb-8a75-3f9c4a780598.png)

    GitHubのページでは、CI StatusがSucceededになったことが確認できる

# 6. Visual Studio App Centerについて

## 6-1. クライアントデータの収集

重要でエキサイティングなのは、分散しているすべてのクライアントからデータを収集し、それを1か所に集めることができること。USBメモリでの配布をなくしAzure DevOpsでビルドした最新のビルドをWeb上から取り出すことができる！

現在すでにロードマップに上がっている作業項目で、Azure DevOpsのPipelineがApp Centerに接続されるので、後ほど説明する手作業でのリリースの作成は不要となる。

## 6-2. 分析（Analytics）

App Centerでは、アクティブユーザー数、デバイス、国、言語、あらゆる種類の詳細なデバイスの分析を行うことができる。また、特定のイベントにコードを書くことで、そのイベントが発生したことも集計できる。

## 6-3. 診断（Diagnostics）

### 6-3-1. 概略

App Center Diagnosticsでは、アプリケーションがクラッシュしたときの対処方法を検討することができる。通常はアプリがクラッシュした場合、単にクラッシュした、と言うだけで、何が起こったのかわからない。App Centerでは、これらのイベントを受信することができる。

今回の例で言えば、2つのカテゴリの例外に分けられた。

1. 未処理の例外。ゼロ除算エラーと思われる。
2. 情報を検証せずにボタンをクリックしたため、不正なエラーが発生した。

例外は、イベントのクラスごとに、バージョン・ビルド・理由によってグループ化される。どのデバイスにいくつのレポートがあったかに関する一般的な情報と、大まかなスタックトレースを提供する。また、個々のレポートに移動し、正確に何を入力した結果例外となったかを確認できる。

実際に結果を分析してみると、電卓アプリは0で割ったことは認識していたが、その先でエラーとなったことがわかる。

### 6-3-2. 診断結果の添付ファイル

App Centerはモバイルプラットフォームで長い間モバイルサービスを提供してきた。が、これはWindows開発の世界にもたらす価値の一部となる。本当に楽しいのは診断結果の添付ファイルである。

クラッシュが発生した理由と例外時に何が起こっていたかについて他の追加情報を取得したい場合、開発者として私が知りたいことについての詳細の完全なカスタムフォーマットと、何が起こっているのかを理解するのに役立つ、ユーザーのデバイスからSDKが取得した生のクラッシュ情報を実際にダウンロードできる

エラー発生時のマシンの状態、イベントを次の"Download"ボタンからダウンロードできる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/0bc82c5d-8948-6038-f73b-485646b14a90.png)

### 6-3-3. 問題の管理

実際の開発では、10万または100万のユーザーデバイスをデバッグすることは難しい。

しかし、App Centerでは、リモートで結果を収集しグループ化するので、開発者はどの関数でエラーが発生しているかを確認することができる。また、App Centerは、修正する必要があるものと、それができるためにできることを優先順位付けしたリストを作成してくれる。

また、Settingsから、サービス連携することで、Azure DevOpsやGitHubに接続し、Issueを作成できる。クラッシュグループに閾値を設定し、閾値を超えたときにIssueを作成することができる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/f17db521-0cbb-7f1e-2951-6ba961b350bb.png)


## 6-4. Releaseの作成

これは統合されたステップであり、iOS、Android、そしてWindowsはApp Centerプラットフォーム上で同等の扱いとなっている。配布して、関連するアプリストアにアプリを送信し、ベータユーザーやテスターに通知を送ることができる。

6-1で述べたように最終的には連携することができるが、今回は手作業でReleaseを作成する。

1. [AzDevOps]ビルドから成果物(Artifact）ダウンロードする

2. [AppCenter]App Centerで新しい新しいリリースを作成する

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/f4dc6324-1c61-5121-1ba4-12f8cedb338f.png)

    1. ビルドバージョンを指定する。最初のApp Centerバージョンなので"1"を指定する。

        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/7bd9ac11-05a3-2e2e-ac91-d5a1cf5c1e4d.png)

    2. Notesにテスターへの文言を記載する。ここでは「it's Crashing?（クラッシュしていますか？）」と記載した。

        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/331b7fbe-b261-c2c9-8640-d9828419e78c.png)

    3. 配布先を指定する。（ここでは、Collaborators（共同作業者）というビルトイングループを選んだ）

        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/595470ed-2ac0-c12d-3d8f-6e3d8a0d8344.png)

    4. 配布する。

        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/6e902535-d521-6678-c682-b87140e52008.png)

        対象者には、メールで通知が届く。

3. テスト

    メールのリンクを開くと、アプリをダウンロードして使用できる。他の情報は確認できずに、テスターとしてダウンロードできる。

    ダウンロードしたアプリケーションをクラッシュさせると、App Centerにその情報が反映されることを確認できる。GitHub上で、Pull Requestを出すことも可能。（デモでは、メッセージを表示するようなプルリクエストをGitHub上で作成していた）


# 7.  ロードマップ

## App Center Azure DevOps task for Deploy

Azure DevOpsのPipelineがApp Centerに接続される

## Supporting automatic updates with MSIX

MSIXによる自動更新のサポート

## .NET Core 3 CLI cross-platform aps

.NET Core 3 CLIでのクロスプラットフォームアプリケーション

## Better build + test support directly in App Center

App Centerでビルドとテストを直接行えるように

## MBaaS for Desktop + Mobile apps

デスクトップとモバイルアプリ向けのMBaasの提供

## WinAppDriver support for automatic UI testing

WindowsデスクトップアプリケーションのUI自動テスト

## Windows React Native with CodePush

Windows React NativeをCodePush対応に

## Feedback?

https://github.com/microsoft/appcenter

# リソース

Repo for this talk: https://github.com/diverdan92/DotNetConf2019

More advanced talk & repo: https://www.youtube.com/watch?v=vc2edJW34Ps
https://aka.ms/devops4clientapps  

MSIX Packaging:
https://docs.microsoft.com/en-us/windows/msix/overview
https://docs.microsoft.com/en-us/windows/msix/desktop/desktop-to-uwp-packaging-dot-net

Publishing Optimizations:
https://www.hanselman.com/blog/MakingATinyNETCore30EntirelySelfcontainedSingleExecutable.aspx