MSIX形式で配布すると、プロジェクトに含めたファイルが見つからない場合の対処方法
WPFプロジェクトに画像ファイルや、実行ファイル等を含めて、プログラムの中から参照したり、実行したりするのは珍しいことではないと思います。
Visual Studio上のソリューションエクスプローラーで対象のファイルをクリックして、プロパティから「出力ディレクトリにコピー」で、「新しい場合はコピーする」や「常にコピーする」を選択してビルドすれば、出力フォルダ(binディレクトリ配下の所定の場所)にコピーされます。
ファイル名(ディレクトリを作成している場合は、ディレクトリ名\ファイル名)を指定するだけで、プログラム上から参照したり、実行したりする事ができます。
Visual Studio上でのデバッグ実行や、出力フォルダにあるアプリケーションを実行した場合は問題ありませんでした。
しかし、それをMSIX形式にパッケージングして配布したら、ファイルが見つかりませんという例外が発生してしまったので、対処方法を調べました。
調査開始
まず、MS公式サイトを確認しましたが、よくわからなかったです。
次に、しばやん(id:shiba-yan)さんが、実行ファイルのパスについて書いていたので、試すことにしました。
加えて、以下のサイトも参考にしながら、取得するパスを追加しました。
techinfoofmicrosofttech.osscons.jp
実際には、以下のコードで試しました。
Logger.Debug($"Assembly.GetExecutingAssembly().Location\n -> {Assembly.GetExecutingAssembly().Location}"); Logger.Debug($"Environment.GetCommandLineArgs()[0]\n -> {Environment.GetCommandLineArgs()[0]}"); Logger.Debug($"Environment.CurrentDirectory\n -> {Environment.CurrentDirectory}"); Logger.Debug($"AppContext.BaseDirectory\n -> {AppContext.BaseDirectory}"); Logger.Debug($"AppDomain.CurrentDomain.BaseDirectory\n -> {AppDomain.CurrentDomain.BaseDirectory}"); Logger.Debug($"MainModule.FileName\n -> {Process.GetCurrentProcess().MainModule?.FileName}"); //階層を下ってディレクトリ、ファイルを全て表示 Logger.Debug("AppDomain.CurrentDomain.BaseDirectory All Entries"); foreach (var entry in Directory.EnumerateFileSystemEntries(AppDomain.CurrentDomain.BaseDirectory, "*.*", SearchOption.AllDirectories)) { Logger.Debug(entry); }
調査結果
Environment.CurrentDirectoryがC:\WINDOWS\System32
を返していて、他はC:\Program Files\WindowsApps
配下のアプリケーション個別のパスを返していました。
AppDomain.CurrentDomain.BaseDirectory
で得られたパスの階層を下っていくと、プロジェクトに含めたファイルがありました。
対処方法
ファイル名だけを指定した場合は、Environment.CurrentDirectoryのパス配下していると想定できるので、
AppDomain.CurrentDomain.BaseDirectory
で得られたパスを使用して、絶対パスを作成することで、プロジェクトに含まれたファイルを参照・実行する事が出来ました。
以上