[C#/DesktopBridge] WPFをUWPパッケージしたときのUWPとしての動作確認のやりかた

# ■やりたいこと
WPFを、DAC(Desktop App Converter)を使ってUWP(appx)パッケージにするアプリにて、appxにしたときの動作を確認したい。

# ■やり方
**「アプリケーションパッケージプロジェクト」**を使って、UWPと同じように動作する環境を作る。

# ■手順
## appx(UWP)パッケージしたいUWPでないアプリをつくる
今回は、.NetFramework(4.7.2)のコンソールアプリを作成することにした。

下記のアプリでやっているのは、UWPパッケージしたアプリでしか動作しないUWPのAPIが動くかどうかで、UWPパッケージとして動いているかどうかを確認するということ。

```Program.cs
using System;
using System.Diagnostics;

namespace ConsoleApp12
{
    class Program
    {
        static void Main(string[] args)
        {
            string path = string.Empty;
            try
            {
                // UWPアプリ
                var localDir = Windows.Storage.ApplicationData.Current.LocalFolder;
                path = localDir.Path;
            }
            catch (Exception ex)
            {
                // UWPアプリでない
                Debug.WriteLine(ex.Message);
                path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
            }
            Debug.WriteLine("target paht is : " + path);
        }
    }
}
```

## アプリケーションパッケージプロジェクトを追加する
ソリューションに、下図の`アプリケーションパッケージ`プロジェクトを追加する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/a712abb9-031e-a81c-95e6-0199b66b25f0.png)

## アプリケーションパッケージプロジェクトに対象のアプリを追加する
アプリケーションパッケージプロジェクトの中の「アプリケーション」を右クリックして「参照の追加」をク選択し、パッケージしたいプロジェクト(ここではConsoleApp12)を追加する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/ab534ce0-c633-ca1a-027a-dbc5409e235c.png)

## ビルドして、アプリケーションパッケージプロジェクトをスタートアップPJに設定する
ソリューション全体をビルドした後、アプリケーションパッケージプロジェクトを右クリックして、「スタートアッププロジェクトに設定」をクリックし、F5を押したらこちらのPJから起動するようにする。

## F5(デバッグ実行)を押す
アプリケーションパッケージプロジェクトを起動する。
これで、デバッグできる。Breakを貼れば、そこでとめることもできる。

# ■実行結果

### WPFの場合
コンソールアプリをスタートアップにして起動した場合は、`Windows.Storage.ApplicationData.Current.LocalFolder`で例外発生して、`catch`のほうを通る。

```実行結果.txt
target path is : C:\Users\masa\AppData\Local
```

### UWP(パッケージPJから起動した)場合
パッケージPJをスタートアップにして起動した場合は、`Windows.Storage.ApplicationData.Current.LocalFolder`で例外発生せず、パスを取得できる。

```実行結果.txt
target path is : C:\Users\masa\AppData\Local\Packages\6c840429-c91b-4fbf-9592-af26324a4a1e_erpevgh2z069r\LocalState
```
---
---
---

# ■気になったところ
ここまでで、一旦デバッグはできるようになった。
以下は、調べる中で気になったことや、注意すべき点をメモしておく。
(調べながらのメモなので、まとまりありません)

## 出力フォルダはどこか？
アプリケーションパッケージプロジェクトの設定としては、デフォで下記のようになっている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/469e3c3c-ab3d-581b-fd38-d7b5ae2d3335.png)

ので、ビルドすると、下記のようなフォルダにexe一式ができた。
`<ソリューションフォルダ>\<プロジェクトフォルダ>\bin\<プラットフォーム>\<コンフィグレーション>\<アプリ名フォルダ>` の中。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/51c9c9d2-8c97-6548-64eb-8a2985c7dfaf.png)

出力フォルダは上記だが、F5を押して行う「デバッグ」で動く際は、別のフォルダに、パッケージに含まれるもの一式が出来上がって動くっぽい。
`<ソリューションフォルダ>\<プロジェクトフォルダ>\bin\<プラットフォーム>\<コンフィグレーション>\AppX\` の中。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/54a5576e-6434-0ad7-9465-167f4f533614.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/1bd9a288-9f23-8c8e-2bfa-4b1d634a1207.png)

この中に、アプリのexeと、exeが参照してるdllなどが、一式入る。


# (参考)パッケージの作成
いろいろ調べてると、DACはすでにマイクロソフトの推奨から外れているらしい。

現状にわか状態なので詳しくはあとで調べるとして、とりあえず下記のようにすると、パッケージを作れる様子。

- パッケージPJを右クリックして [ストア] > [アプリ パッケージの作成]を選択
- 
ここでパッケージを作成すると、下記のようなものができる。

### \<プロジェクトフォルダ>\\AppPackages フォルダ
その中の`<PJ名>_<バージョン>_<コンフィグ>_Test`フォルダに、`.appxbundle`または`.msixbundle`を含むインストーラー一式が出来上がる。(.cerの証明書ファイルも一緒にできてる)


### \<プロジェクトフォルダ>\bin\\<プラットフォーム>\\<コンフィグレーション> フォルダ
ここに、`.appx`または`.msix`ができてる。


# (参考)パッケージ作成時、appxとmsixのどちらができるのか？
`.appxbundle`ができるときと、`.msixbundle`ができるときがある。どっちができるか決める条件はなんなのか？

**19/08/21 追記**
⇒VS2019 v16.1.6で試してみたところ、下記っぽい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/120a8eca-950a-3183-d7da-da2293dc9c87.png)

パッケージプロジェクトの**「最小バージョン」**を**1803(10.0 ビルド17134)以前**にすると、appxとappxbundleが出来上がり、**1809(10.0 ビルド17763)以降**にすると、msixとmsixbundleが出来上がる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/5eeab9e6-683b-1902-5af7-d1c88920a46b.png)

なんとなく試してみて上記だと分かったが、どこかに説明かいているのか？？？
MSdocs色々見たつもりだが、appxとmsixのできる条件、見つけられなかった...

**19/08/21 追記その2**
下記が、そういうことか？？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/0577cadb-58d4-6db5-806e-845587357f48.png)
[MSDocsより引用。](https://docs.microsoft.com/ja-jp/windows/msix/desktop/desktop-to-uwp-root#build-an-msix-from-an-existing-app-installer)

# (参考)注意・ハマりかけた事
## アプリが参照してるdllの配置についての注意
アプリが使うdllは、パッケージPJが、参照の設定をもとに自動でアプリのexeと同じ階層に入れてくれる。試したところ、

1. アプリの参照設定に入っていて「ローカルにコピー」がtrueになっているもの
2. アプリが参照しているdllが、さらに参照しているdll

は、自動で入れてくれるっぽい。

但し、上の2.は、**「アプリが参照しているdll」と同じフォルダに「さらに参照しているdll」が入って**いないと自動で配置してくれないっぽい。
なので、**dll類を、ビルド後イベントで、別のところからコピーしてきているような場合については、パッケージプロジェクトでは自動で配置してくれなかった。**
(そういう時は、パッケージPJの方でもビルド後イベントでコピーなどしないといけないっぽい。未検証)



## UWPのAPIを使うときの注意
やりたいことの本筋から少々れるが、この実験をやるうえで、パスを取得するためのUWPのAPI(`Windows.Storage.ApplicationData.Current.LocalFolder`)を使いたかったので、Nugetで`Microsoft.Windows.SDK.Contracts`を追加して使えるようにしようとしたが、下記のようなエラーが出た。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/6fdb599f-9fdd-465e-2957-bd7cce8300ad.png)

エラーの主語(アプリケーションは、...)が何を指しているのかあいまいで混乱したが、どうやら`Microsoft.Windows.SDK.Contracts`が、Windowsの`10.0.18362.0`、つまり`1903`を必要とするので、それ(Contracts)を使っているConsoleApp12(今回作った実験用コンソールアプリ)のMinVerを下げろ、と言っている様子。
`Microsoft.Windows.SDK.Contracts`はNugetしてきていて、MinVerを下げることはできないので困った。

解決法としては、`Microsoft.Windows.SDK.Contracts`を使うのをやめて、以前の方法([こちら](https://blog.okazuki.jp/entry/2018/03/29/101601)参照。.winmdファイルを参照するやり方)でUWPのAPIを呼ぶようにして対応した。

# 参考
WPF などの .NET Framework のアプリから UWP の API を呼ぶ
https://blog.okazuki.jp/entry/2018/03/29/101601

.NET のプロジェクトから WinRT API を呼ぶのが凄く簡単になってます
https://blog.okazuki.jp/entry/2019/05/09/115020