■やりたいこと
WPFを、DAC(Desktop App Converter)を使ってUWP(appx)パッケージにするアプリにて、appxにしたときの動作を確認したい。
■やり方
**「アプリケーションパッケージプロジェクト」**を使って、UWPと同じように動作する環境を作る。
■手順
appx(UWP)パッケージしたいUWPでないアプリをつくる
今回は、.NetFramework(4.7.2)のコンソールアプリを作成することにした。
下記のアプリでやっているのは、UWPパッケージしたアプリでしか動作しないUWPのAPIが動くかどうかで、UWPパッケージとして動いているかどうかを確認するということ。
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);
}
}
}
アプリケーションパッケージプロジェクトを追加する
ソリューションに、下図のアプリケーションパッケージ
プロジェクトを追加する。
アプリケーションパッケージプロジェクトに対象のアプリを追加する
アプリケーションパッケージプロジェクトの中の「アプリケーション」を右クリックして「参照の追加」をク選択し、パッケージしたいプロジェクト(ここではConsoleApp12)を追加する。
ビルドして、アプリケーションパッケージプロジェクトをスタートアップPJに設定する
ソリューション全体をビルドした後、アプリケーションパッケージプロジェクトを右クリックして、「スタートアッププロジェクトに設定」をクリックし、F5を押したらこちらのPJから起動するようにする。
F5(デバッグ実行)を押す
アプリケーションパッケージプロジェクトを起動する。
これで、デバッグできる。Breakを貼れば、そこでとめることもできる。
■実行結果
WPFの場合
コンソールアプリをスタートアップにして起動した場合は、Windows.Storage.ApplicationData.Current.LocalFolder
で例外発生して、catch
のほうを通る。
target path is : C:\Users\masa\AppData\Local
UWP(パッケージPJから起動した)場合
パッケージPJをスタートアップにして起動した場合は、Windows.Storage.ApplicationData.Current.LocalFolder
で例外発生せず、パスを取得できる。
target path is : C:\Users\masa\AppData\Local\Packages\6c840429-c91b-4fbf-9592-af26324a4a1e_erpevgh2z069r\LocalState
■気になったところ
ここまでで、一旦デバッグはできるようになった。
以下は、調べる中で気になったことや、注意すべき点をメモしておく。
(調べながらのメモなので、まとまりありません)
出力フォルダはどこか?
アプリケーションパッケージプロジェクトの設定としては、デフォで下記のようになっている。
ので、ビルドすると、下記のようなフォルダにexe一式ができた。
<ソリューションフォルダ>\<プロジェクトフォルダ>\bin\<プラットフォーム>\<コンフィグレーション>\<アプリ名フォルダ>
の中。
出力フォルダは上記だが、F5を押して行う「デバッグ」で動く際は、別のフォルダに、パッケージに含まれるもの一式が出来上がって動くっぽい。
<ソリューションフォルダ>\<プロジェクトフォルダ>\bin\<プラットフォーム>\<コンフィグレーション>\AppX\
の中。
この中に、アプリの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で試してみたところ、下記っぽい。
パッケージプロジェクトの**「最小バージョン」を1803(10.0 ビルド17134)以前**にすると、appxとappxbundleが出来上がり、1809(10.0 ビルド17763)以降にすると、msixとmsixbundleが出来上がる。
なんとなく試してみて上記だと分かったが、どこかに説明かいているのか???
MSdocs色々見たつもりだが、appxとmsixのできる条件、見つけられなかった...
19/08/21 追記その2
下記が、そういうことか??
MSDocsより引用。
(参考)注意・ハマりかけた事
アプリが参照してるdllの配置についての注意
アプリが使うdllは、パッケージPJが、参照の設定をもとに自動でアプリのexeと同じ階層に入れてくれる。試したところ、
- アプリの参照設定に入っていて「ローカルにコピー」がtrueになっているもの
- アプリが参照しているdllが、さらに参照しているdll
は、自動で入れてくれるっぽい。
但し、上の2.は、「アプリが参照しているdll」と同じフォルダに「さらに参照しているdll」が入っていないと自動で配置してくれないっぽい。
なので、dll類を、ビルド後イベントで、別のところからコピーしてきているような場合については、パッケージプロジェクトでは自動で配置してくれなかった。
(そういう時は、パッケージPJの方でもビルド後イベントでコピーなどしないといけないっぽい。未検証)
UWPのAPIを使うときの注意
やりたいことの本筋から少々れるが、この実験をやるうえで、パスを取得するためのUWPのAPI(Windows.Storage.ApplicationData.Current.LocalFolder
)を使いたかったので、NugetでMicrosoft.Windows.SDK.Contracts
を追加して使えるようにしようとしたが、下記のようなエラーが出た。
エラーの主語(アプリケーションは、...)が何を指しているのかあいまいで混乱したが、どうやらMicrosoft.Windows.SDK.Contracts
が、Windowsの10.0.18362.0
、つまり1903
を必要とするので、それ(Contracts)を使っているConsoleApp12(今回作った実験用コンソールアプリ)のMinVerを下げろ、と言っている様子。
Microsoft.Windows.SDK.Contracts
はNugetしてきていて、MinVerを下げることはできないので困った。
解決法としては、Microsoft.Windows.SDK.Contracts
を使うのをやめて、以前の方法(こちら参照。.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