L’un des griefs les plus important à l’encontre du développement d’application UWP est sa capacité limitée à accéder aux fichiers de son ordinateur. Pourtant il existe plusieurs méthodes, que nous allons passer en revue, qui permettent de manipuler facilement les fichiers et dossiers .
ApplicationData et les fichiers de l’applications
Au lancement d’UWP Les concepteurs ont pris le parti, très sécuritaire, de ne pouvoir accéder qu’à des répertoires du disque dédiés à l’application (LocalFolder, TemporaryFolder, …). Ceux-ci sont regroupés dans la classe ApplicationData :
https://docs.microsoft.com/en-us/uwp/api/windows.storage.applicationdata
Ce parti pris est, comme souvent pour UWP, lié à la nature sandboxée de l’application. Elle permet de s’assurer que le développeur ne pourra pas accéder à des données sensibles du système.
Les fichiers de l’application sont donc écris dans un répertoire par nature difficilement accessible par l’utilisateur car nécessitant des droits Administrateurs. Or, l’utilisateur à souvent besoin de récupérer des fichiers exportés par l’application.
Heureusement, le store autorise un accès complets à des répertoires particuliers.
Les KnownFolders
Ces répertoires sont regroupés dans la classe KnownFolders. Ils permettent un accès à des répertoires externes à l’application à partir du moment ou ils sont déclarés comme Capacité dans le manifeste de l’application :
Vous pouvez retrouver l’intégralité de ces dossiers et leurs descriptions en suivant ce lien :
https://docs.microsoft.com/en-us/uwp/api/windows.storage.knownfolders
En attendant en voici quelques uns parmi les plus utilisés :
- Picture (répertoire Images)
- Music (répertoire Musique)
- Videos (répertoire Vidéos)
- Removable Storage (clé USB ou carte SD par exemple). Dans ce cas seul les types de fichiers déclarés dans le manifeste de l’application sont accessibles.
Le cas DownloadFolder
Il est possible d’accéder au répertoire Download sans avoir a déclarer une Capacité particulière. En revanche, on ne pourra accéder qu’aux fichiers et dossiers crées par l’application. Une autre application UWP ne pourra donc pas accéder à nos propres fichiers. Cela reste tout de même un moyen trivial et rapide d’écrire des fichiers récupérables facilement par l’utilisateur.
La classe static DownloadFolder ne contient que des méthodes permettant de créer des fichiers ou des dossiers. Une fois appelé on récupère un StorageFile ou un StorageFolder qui les rendent accessibles à l’application.
StorageFile newFile = await DownloadsFolder.CreateFileAsync("file.txt");
La classe DownloadFolder ne possède pas de méthode pour lire le contenu du dossier Downloads. C’est ennuyeux si l’on souhaite réutiliser le fichier crée après redémarrage de l’application. Heureusement on peut palier à ce problème en stockant le StorageFile ou StorageFolder dans une liste persistante : StorageApplicationPermissions.FutureAccessList
Documentation sur le DownloadFolder :
https://docs.microsoft.com/en-us/uwp/api/windows.storage.downloadsfolder
Documentation sur la FutureAccessList :
https://docs.microsoft.com/fr-fr/uwp/api/windows.storage.accesscache.storageitemaccesslist
Je sélectionne avec les Pickers
Si l’écriture ou la lecture de votre fichier ou dossier doit être sélectionnées par l’utilisateur, il est possible d’utiliser des boites de dialogues spécialisées : Les Pickers
Les Pickers permettent d’atteindre l’ensemble du système de fichiers accessible pas l’utilisateur de l’application. Pour être utilisés, ils n’ont pas besoin d’un ajout de capacité.
Il existe plusieurs types de pickers à utiliser selon les cas :
- FileOpenPicker qui permet l’ouverture d’un ou plusieurs fichiers
- FileSavePicker pour enregistrer un fichier
- FolderPicker pour ouvrir un dossier
Comme dans le cas du DownloadFolder, il peut être intéressant de sauver les derniers fichiers ou dossiers utiliser pour un accès futur par l’utilisateur ou l’application. Vous pouvez utiliser FutureAccessList mais également StorageItemMostRecentlyUsedList (liste MRU) qui permet de conserver les 25 derniers fichiers ou dossiers récemment ouverts.
Documentation sur les pickers :
https://docs.microsoft.com/fr-fr/windows/uwp/files/quickstart-using-file-and-folder-pickers
Documentation sur la liste MRU :
Accèder à tous les fichiers sans Pickers
Les applications en provenance du store ont des nécessités en terme de sécurité que les applications dont la vocation est d’être utilisées dans une entreprise ou dans le cadre d’un kiosque n’ont pas.
Microsofts à donc récemment décidé d’assouplir les accès aux fichiers pour ces cas particuliers en ajoutant une nouvelle capacité : broadFileSystemAccess. Pour la déclarer il faut ouvrir le manifeste de l’application sous forme XML puis ajouter rescap dans IgnorableNameSpace et la rescap:Capability broadFileSystemAccess dans Capabilities.
<Package
...
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap mp uap5 rescap">
...
<Capabilities>
<rescap:Capability Name="broadFileSystemAccess" />
</Capabilities>
Aucune autre capacité de type Documents, Pictures ou Videos ne doit être déclaré pour que cette capacité puisse fonctionner correctement.
IMPORTANT : Pour que l’accès aux fichiers soit effectif, l’utilisateur doit l’autoriser explicitement dans les settings de la machine. Par défaut la valeur est OFF (depuis Windows October 2018 update).
Il est possible de lancer cette page de settings à partir de son application :
bool result = await Windows.System.Launcher.LaunchUriAsync(new Uri("ms-settings:privacy-broadfilesystemaccess"));
Conclusion
Même si l’accès aux fichiers est moins aisé qu’une application .NET de bureau, il reste par le biais des Picker et de la capacité broadFileSystemAccess relativement simple et puissant. On peut espérer que Microsoft ajoute un jour une capacité permettant à une application UWP d’avoir un accès complet à la machine, sans settings externes à configurer, comme le ferait une application .NET classique. en attendant le développeur est suffisamment armé pour faire face à la grandes majorités des demandes clients.