ファイルの「フルアクセス」機能を使う
要約
- この機能は、broadFileSystemAccessケイパビリティを有効にすることで、利用可能になります
- このケイパビリティがあると、任意の絶対パス文字列からIStorageItemオブジェクトを取得できます
- 「フルアクセス」とカッコ書きにしているのは、システム属性/隠し属性が付いているフォルダー/ファイルにはアクセスできないからです
- broadFileSystemAccessケイパビリティは、開発者がアプリマニフェストで許可していても、ユーザーが設定で拒否できるようになっています
- このケイパビリティを使ったアプリをMicrosoftストアに申請するには、それが必要であることをストア側に説明して納得してもらう必要があります
broadFileSystemAccessケイパビリティ
Windows 10 1803(build 17134)以上を最小バージョンにしてUWPアプリのプロジェクトを作り、アプリマニフェストにbroadFileSystemAccessケイパビリティを追加します。ただし、特殊なケイパビリティなので、マニフェストエディターの[機能]タブには表示されません。
ソリューションエクスプローラーで「Package.appxmanifest」ファイルを右クリックし、コンテキストメニューから[コードの表示]を選ぶと、XMLエディターでマニフェストファイルが開かれます。そこで次のコードに示すように、マニフェストを書き換えます。ここでrescapは"restricted capability"(制限されているケイパビリティ)の意味です。また、rescap:Capability要素を記述すると警告が出るかもしれませんが、無視してください。
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
IgnorableNamespaces="uap mp">
↓
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap mp rescap">
<Capabilities>
<Capability Name="internetClient" />
</Capabilities>
</Package>
↓
<Capabilities>
<Capability Name="internetClient" />
<rescap:Capability Name="broadFileSystemAccess" />
</Capabilities>
</Package>
なお、broadFileSystemAccessケイパビリティを付与したUWPアプリは、WACK(Windows App Cert. Kit)のテストにパスしなくなります。
任意のパス文字列からIStorageItemオブジェクトを取得する
といっても、新しいAPIを使うわけではありません。Windows 8の「ストアアプリ」からあるStorageFolder.GetFolderFromPathAsyncメソッド/StorageFile.GetFileFromPathAsyncメソッドを使います。
これら2つのメソッドは、引数にフルパスを要求します。しかし、これまでは、アプリに許可されたフォルダーでしか有効ではありませんでした。アプリに許可されたフォルダーならば、取得が困難なフルパス文字列を使うより、アプリからの相対URIや決められたURIを使うStorageFile.GetFileFromApplicationUriAsyncメソッドなどの方がよっぽど楽ですから、これら2つのメソッドを使う機会はめったになかったのです。
それがbroadFileSystemAccessケイパビリティを付与すると、任意のフルパスを指定できるようになります。試しに、MainPageクラスに次のようなコードを追加して実行してみてください。ソースコード冒頭にusing Windows.Storage;の追加が必要です。
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
// GetFolderFromPathAsync() の動作確認
IStorageItem winFolder
= await StorageFolder.GetFolderFromPathAsync(@"c:\windows");
await (new Windows.UI.Popups.MessageDialog(winFolder.Path)).ShowAsync();
// GetFileFromPathAsync() の動作確認
IStorageItem notepadFile
= await StorageFile.GetFileFromPathAsync(@"c:\windows\NotePad.exe");
await (new Windows.UI.Popups.MessageDialog(notepadFile.Path)).ShowAsync();
}
上のコードでパスを変えていろいろ試してみてください。ルートフォルダー(「C:\」など)も取得できます。しかし、隠し属性などが付いていると、アクセス拒否されます。ユーザーが普通にアクセスできる場所に限定されているようです(「エクスプローラーで隠しファイル/システムファイルを表示する設定に変えておくのが『普通』だろ」というのは、今はなしで)。
さて、ファイルマネージャーを作るには、ルートフォルダーのStorageFolderオブジェクトさえ取得できればよいです。あとは、StorageFolder.GetItemsAsyncメソッドなどで配下のフォルダー/ファイルを探索していけばよいのですから。ルートフォルダのフルパスは、ドライブ名さえ分かれば簡単に生成できます。
ドライブレターを取得する
すべてのドライブ名を取得するには、System.IO名前空間のDirectory.GetLogicalDrivesメソッドを使います。
このメソッドは.NET Frameworkの初期からあるものですが、UWPで使えるようになったのは.NET Core 2.0から、すなわちWindows 10 1709(build 16299)からです。これには、broadFileSystemAccessケイパビリティは必要ありません。.NET CoreとUWPのバージョンの関係については、連載第3回「UWPアプリからSQL Serverにアクセス ~.NET Standard 2.0の威力! WPFやXamarinからも共通に使えるクラスライブラリを作る」2ページ目の下方にある表をご覧ください。
ユーザー設定
このbroadFileSystemAccessケイパビリティは、ユーザーが拒否できます。Windows 10 1803(build 17134)では、次の画像のように設定アプリで行います。すべてのアプリをまとめてオン/オフすることも(中央付近のスイッチ)、アプリごとに個別にオン/オフすることもできます(右下のスイッチ)。
設定でオフにされると、アプリマニフェストにbroadFileSystemAccessケイパビリティが書かれていないときと同様に、UnauthorizedAccessException例外「アクセスが拒否されました」が発生します。「ケイパビリティを与えたら必ずアクセスできる」とは思わないでください。例外をキャッチして適切な対処をしてください。サンプルコードでは、アプリ起動時にオフにされていたら設定アプリの上記の画面を呼び出すようにしています。
配布方法
サイドローディング
サイドローディングでの配布は、従来通りです。組織内での業務アプリなどは、broadFileSystemAccessケイパビリティ付きであってもサイドローディングすれば問題ありません。
業務アプリをサイドローディングで配布する方法は、「Windows 10 での LOB アプリのサイドローディング」や「Enterprise app management」(本稿執筆時点では英語のみ)などをご覧ください。なお、Windows 10 1607からは、(正式なデジタル署名がされた)アプリパッケージをダブルクリックするだけで次の画像のようなインストーラーが立ち上がってインストールできるようになっています。
Microsoftストアへの申請
broadFileSystemAccessケイパビリティは「制限付き機能」(restricted capability)です。普通のUWPアプリのつもりでストアに申請するとリジェクトされてしまいます。詳細は「アプリ機能の宣言」の「制限付き機能」セクションをご覧いただきたいのですが、このケイパビリティの必要性をストアのテスターに納得してもらわねばなりません。
その手順は変更されることがあります。本稿執筆時点では、申請するときに「申請オプション」のページの「認定の注意書き」セクション(次の画像)に説明を記述します。なぜ必要なのか、それによってユーザーにどんなメリットがあるのかといったことを説明して、テスターに「なるほど、これはストアで公開する価値がある」と思ってもらえれば認定されるでしょう。日本語を理解できないテスターが担当することもあるので、英語で記述したほうが無難です。
