WPFアプリのmsixによるweb配布、自動更新方法

# 前書き
ClickOnceによる配布方法が一番楽だと思うんですが、IEのサポートが終了し、
WebからClickOnce起動することが難しくなった(EdgeもClickOnceを許可する設定をすればできる)
のでこの際msix形式の配布方法に変更しました。
今回はストアは利用しません、webサーバーに配置して配布します。


# msixとは
ここをみるのが一番ですが、[What is msix](https://docs.microsoft.com/en-us/windows/msix/overview)
要約するとWindowsにインストールできるパッケージの形式ですかね。
で、このmsixと[アプリインストーラー](https://docs.microsoft.com/en-us/windows/msix/app-installer/app-installer-root)を利用すると自動更新が実現できます。
どちらもvisual studioで自動生成できます。

# 開発環境
visual studio 2019
ASP.NET Core(ここはmsixの配置場所)

# 手順
適当なWPFプロジェクトを作成します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/a36ae375-9ce0-ed82-effa-3cdd773786e1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/fd63a0c6-caab-d04c-18d3-c31c7d93e0e7.png)

ちょっとわかりやすいようにMainWindows.xamlをいじります

```C#
<Window
    x:Class="MSIX_Test.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:MSIX_Test"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="800"
    Height="450"
    mc:Ignorable="d">
    <Grid>
        <TextBlock
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            FontSize="50"
            Text="Version 1" />
    </Grid>
</Window>

```
起動するとこんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/96598386-16ec-50ec-b892-3180b567cc2d.png)

次にこのアプリのmsixパッケージを作成していきます。
まずソリューションを右クリック＞追加＞新規プロジェクト
検索窓に「パッケージ」と入力すると、「Windows アプリケーション　パッケージ　プロジェクト」が出てくるので、追加します。

### ※でてこない方（表示できてる方は読み飛ばしてください）
Visual Studio Installerを起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/b106da59-6521-3d78-5233-12140f241d17.png)
変更をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/c975a332-c2b6-0780-eeeb-0560e0600028.png)
.Netデスクトップ開発のチェックと右側のMSIX Packaging Toolsのチェックを入れてインストールしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/068df0e7-3bbc-95bd-db14-b36123def312.png)

以上でプロジェクトの追加に表示されます。

### プロジェクトの追加の続き
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/1983c625-ca25-6685-9d46-25d3641665c3.png)
名前を適当に決めて
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/e5e9e79c-6e8d-f092-7f4e-94da776be726.png)
ターゲットは1903に合わせてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/7aa97ca7-2c4c-ddb1-d766-81731fa4adb4.png)

プロジェクトが追加されたらパッケージに含めるプロジェクトを選択します。
パッケージプロジェクト下のアプリケーションを右クリック＞参照の追加
プロジェクトを選択してOKを押します（依存関係があるプロジェクトは一番上のプロジェクトのみチェックすればいいです。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/e424f2e7-0975-af06-3409-7352e8a9940a.png)
次にパッケージプロジェクトを右クリック＞公開＞アプリパッケージの公開
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/2fccb102-d0a3-19a4-b637-ff484266795c.png)
自動更新にチェック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/71da456f-553f-27e4-6fa7-f873b6e8ca77.png)
証明書を使用するので、適当な証明書を作成します。（もうすでにある方はそれを使ってもらって）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/7d48b16d-8b9b-9ffd-0de3-ab8d1bb0ddc2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/6d345bc2-19b3-1a67-3286-c441c67cfcaf.png)
こんな感じになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/a9cc4126-21ba-8fcd-d4ff-dae0bd6227e8.png)

x86を選択します（後で設定いじるのでとりあえず）
一番上の出力場所をパスを次使うのでコピーしておいてください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/06914dce-3b01-4450-0ec9-d11d4f1d9b7d.png)
インストーラーの場所に貼り付けます。
本来ここは実際のインストーラーを置くサーバーのURIになります。
アプリケーションが実行するたびに更新チェックにします。
作成を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/b0e2bfa5-dbca-1cb8-8dbb-d3daa5aa1233.png)
で、何かエラーが出ると思うので、設定を直します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/9446407c-8fa9-07c4-c526-e6c28826f64b.png)
ソリューションを右クリック＞構成マネージャー
プラットフォームがAny CPUになっているので、すべてx86に変更します。
新規追加でx86があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/76960be2-1c92-9427-65c6-49250d9b23f3.png)


そしたらもう一回公開する際にDebug(x86)を選択して公開します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/57f22b04-8a96-712e-5da7-2ba527784087.png)
完成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/a7e44907-814e-b70c-fbb9-882e60e53273.png)

イントーラーの場所に選択したフォルダに移動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/e779405e-8ef0-6619-c260-0ed747a82be8.png)
index.htmlを開きます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/9e3063e8-cf00-9e3d-ef6a-b28564e4b29a.png)

アプリを取得するを押すと、ダイヤログがでてくるので、開きます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/4281b6aa-a05d-8bb0-d99a-6bee4e9a6c77.png)
インストールを押しますが、失敗します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/155c2e78-0818-0a20-4dc2-14ea680fd0a7.png)
インストールするために、先ほど設定した証明書の公開鍵をPCにインストールします。
index.htmlのほかに出力されたフォルダ内に配置されているので、開いて、ダイアログを設定していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/209ca58b-eb30-126d-d73c-24e71d0f88d6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/1759f6e8-4e88-7aec-9941-53de2014a8b4.png)
証明書のインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/d032ee50-7422-b839-d586-cb09146f4c49.png)
ローカルコンピューター
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/04dc0756-92c0-745f-4a83-6d45e5480b0f.png)
証明書ストアを指定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/39144efc-6152-4b77-04e2-b197a36bdf34.png)
信頼されたルート証明機関
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/ef02b698-b896-00d6-74cb-e58df578d5fc.png)
するとインストールできるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/57f56c9f-9e69-b603-a8a0-1ca980ef1f8c.png)
インストールして無事起動できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/2cd6549f-bbb4-a78e-83c7-95136121c5a0.png)

###バージョンの更新
MainWindow.xamlのVersionを2に書き換えました。

```C#
<Window
    x:Class="MSIX_Test.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:MSIX_Test"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="800"
    Height="450"
    mc:Ignorable="d">
    <Grid>
        <TextBlock
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            FontSize="50"
            Text="Version 2" />
    </Grid>
</Window>
```
再度パッケージングします。
バージョンはデフォルトでautoincrementされてます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/10fdd830-62f0-0b44-f85b-3f74c910849c.png)
発行完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/7fedd07e-c10b-9eb8-e9f3-567b931e721d.png)

自動更新にチェックを入れているので、あとはVersion1アプリを起動するだけでいいです。
Windowsの検索窓から探して起動します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/2f60ca0d-0a7a-eb8d-4fa5-9048de4f522a.png)
(アプリ名Pakageって誤字ってた。。)

あれ！？起動してもVersion1になってる？？、けど挙動としては正しいのです。。(説明します)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/bf521ced-24ea-5624-7961-75484f99fc9a.png)

一度アプリを閉じて再起動します
Version2になっていると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/0b3c1d03-bce6-b742-b135-eb8bed1afabb.png)
msixのインストーラーはデフォルトだとアプリを終了したときに更新が入るそうです。
ただそれだと私の場合困るので、調べたので説明します。

### 自動更新のタイミングの設定
先に進む前に更新の確認でwindows versionが1903以上になっていることを確認してください。
この機能は1903が必要らしいです。

次にPackageプロジェクトを右クリック＞追加＞新しい項目
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/8bf1d771-5cb7-84fb-95bc-ced282307818.png)
アプリインストーラーというファイルを探して追加します。
（名前はいじらないでください）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/148e90ea-60f5-d1cd-a909-aafeefffb7a5.png)
この追加したファイルがこれから出力するappinstallerのテンプレートファイルになります。
中を編集します。

```diff:Package.appinstaller

<?xml version="1.0" encoding="utf-8"?>

<AppInstaller Uri="{AppInstallerUri}"
              Version="{Version}"
-             xmlns="http://schemas.microsoft.com/appx/appinstaller/2017/2">
+             xmlns="http://schemas.microsoft.com/appx/appinstaller/2018">

  <MainBundle Name="{Name}"
              Version="{Version}"
              Publisher="{Publisher}"
              Uri="{MainPackageUri}"/>

  <UpdateSettings>
    <OnLaunch HoursBetweenUpdateChecks="0"
+              UpdateBlocksActivation="true"
+              ShowPrompt="true"/>
  </UpdateSettings>

</AppInstaller>
```

UpdateBlocksActivationこれが更新の強制で、ShowPromptが更新ダイアログの表示です。
この二つを使うために2018に書き換えています。

この状態でMainWindow.xamlをVersion3に書き換えて発行し、Version2のアプリを起動します。
まだVersion2の設定が活かされるので、アプリを閉じたタイミングでVerion3に更新されます。
再起動するとVersion3になるかと思います
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/a53e8670-ce90-0826-6e07-6b524bc1555a.png)

次にMainWindow.xamlをVersion4に書き換えて、発行します。
その状態でVersion3のアプリを起動すると、このような更新確認画面になると思います。
これで更新の強制は成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/01b98dfc-d77d-aa37-48bc-a0d1d23e2a1e.png)
ただ更新が終わった後の起動までかなり時間かかるのは何だろう、20秒近くかかる気がします。
原因はちょっとわからないので、どこかで調べたいと思います。

### インストーラーをサーバーに配置
ちょっとここもハマりポイントがあるのですが、記事が長すぎなので、
ポイントだけ書きます。
更新するときって.appinstollerと.msixbundleファイルをクライアントがアクセス＆ダウンロードできる必要があるので（index.htmlもだけど）
サーバーで許可する必要があります。
ASP.Net Coreの設定だけ書いておきます。

```C#:Startup.cs
 public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
            var provider = new FileExtensionContentTypeProvider();
            // Add new mappings
            provider.Mappings[".appinstaller"] = "application/xml";
            provider.Mappings[".msixbundle"] = "application/vns.ms-appx";
            provider.Mappings[".appx"] = "application/vns.ms-appx";
            app.UseStaticFiles(new StaticFileOptions
            {
                FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "App")),
                RequestPath = "/App",
                ContentTypeProvider = provider
            });
}
```
こんな感じです。.appxはどこかのサイトにあったので追加してます。

この設定で、以下のファイル配置が動きます。
ーサーバーRoot
　ーApp
  　ーMSIX_Text_Pakage_1.0.10.0_Debug_Test
　　ーindex.html
　　ーMSIX_Text_Pakage.appinstaller

# 終わりに
長くなってしまいましたが、
色々詰まった個所があったので、参考になれば幸いです。