I´m developing an app that is reading jpeg and pdf files from a configurable location on the filesystem.
Currently there is a running version implemented in WPF and now I´m trying to move to the new Windows Universal apps.
The following code works fine with WPF:
public IList<string> GetFilesByNumber(string path, string number)
{
if (string.IsNullOrWhiteSpace(path))
throw new ArgumentNullException(nameof(path));
if (string.IsNullOrWhiteSpace(number))
throw new ArgumentNullException(nameof(number));
if (!Directory.Exists(path))
throw new DirectoryNotFoundException(path);
var files = Directory.GetFiles(path, "*" + number + "*",
SearchOption.AllDirectories);
if (files == null || files.Length == 0)
return null;
return files;
}
With using Universal Apps I ran into some problems:
Directory.Exists is not available
How can I read from directories outside of my app storage?
To read from an other directory outside the app storage I tried the following:
StorageFolder folder = StorageFolder.GetFolderFromPathAsync("D:\\texts\\");
var fileTypeFilter = new string[] { ".pdf", ".jpg" };
QueryOptions queryOptions = new QueryOptions(CommonFileQuery.OrderBySearchRank, fileTypeFilter);
queryOptions.UserSearchFilter = "142";
StorageFileQueryResult queryResult = folder.CreateFileQueryWithOptions(queryOptions);
IReadOnlyList<StorageFile> files = queryResult.GetFilesAsync().GetResults();
The thing is: It isn´t working, but I get an exception:
An exception of type 'System.UnauthorizedAccessException' occurred in TextManager.Universal.DataAccess.dll but was not handled in user code
Additional information: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
I know that you have to configure some permissions in the manifest, but I can´t find one suitable for filesystem IO operations...
Did someone also have such problems/a possible solution?
Solution:
From the solutions that #Rico Suter gave me, I chosed the FutureAccessList in combination with the FolderPicker. It is also possible to access the entry with the Token after the program was restarted.
I can also recommend you the UX Guidlines and this Github sample.
Thank you very much!
In UWP apps, you can only access the following files and folders:
Directories which are declared in the manifest file (e.g. Documents, Pictures, Videos folder)
Directories and files which the user manually selected with the FileOpenPicker or FolderPicker
Files from the FutureAccessList or MostRecentlyUsedList
Files which are opened with a file extension association or via sharing
If you need access to all files in D:\, the user must manually pick the D:\ drive using the FolderPicker, then you have access to everything in this drive...
UPDATE:
Windows 10 build 17134 (2018 April Update, version 1803) added additional file system access capabilities for UWP apps:
Any UWP app (either a regular windowed app or a console app) that declares an AppExecutionAlias is now granted implicit access to the files and folders in the current working directory and downward, when it’s activated from a command line. The current working directory is from whatever file-system location the user chooses to execute your AppExecutionAlias.
The new broadFileSystemAccess capability grants apps the same access to the file system as the user who is currently running the app without file-picker style prompts. This access can be set in the manifest in the following manner:
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
...
IgnorableNamespaces="uap mp uap5 rescap">
...
<Capabilities>
<rescap:Capability Name="broadFileSystemAccess" />
</Capabilities>
These changes and their intention are discussed at length in the MSDN Magazine article titled Universal Windows Platform - Closing UWP-Win32 Gaps. The articles notes the following:
If you declare any restricted capability, this triggers additional
scrutiny at the time you submit your package to the Store for
publication. ... You don’t need an AppExecutionAlias if you have this
capability. Because this is such a powerful feature, Microsoft will
grant the capability only if the app developer provides compelling
reasons for the request, a description of how this will be used, and
an explanation of how this benefits the user.
further:
If you declare the broadFileSystemAccess capability, you don’t need to
declare any of the more narrowly scoped file-system capabilities
(Documents, Pictures or Videos); indeed, an app must not declare both
broadFileSystemAccess and any of the other three file-system
capabilities.
finally:
Even after the app has been granted the capability, there’s also a
runtime check, because this constitutes a privacy concern for the
user. Just like other privacy issues, the app will trigger a
user-consent prompt on first use. If the user chooses to deny
permission, the app must be resilient to this.
The accepted answer is no longer complete. It is now possible to declare broadFileSystemAccess in the app manifest to arbitrarily read the file system.
The File Access Permissions page has details.
Note that the user can still revoke this permission via the settings app.
You can do it from UI in VS 2017.
Click on manifest file -> Capabilities -> Check photo library or whatever stuff you want.
According to MSDN doc : "The file picker allows an app to access files and folders, to attach files and folders, to open a file, and to save a file."
https://msdn.microsoft.com/en-us/library/windows/apps/hh465182.aspx
You can read a file using the filepicker through a standard user interface.
Regards
this is not true:
Files which are opened with a file extension association or via sharing
try it, by opening files from mail (outlook) or from the desktop...
it simply does not work
you first have to grant the rights by the file picker.
so this ist sh...
This is a restricted capability. Access is configurable in Settings > Privacy > File system. and enable acces for your app. Because users can grant or deny the permission any time in Settings, you should ensure that your app is resilient to those changes. If you find that your app does not have access, you may choose to prompt the user to change the setting by providing a link to the Windows 10 file system access and privacy article. Note that the user must close the app, toggle the setting, and restart the app. If they toggle the setting while the app is running, the platform will suspend your app so that you can save the state, then forcibly terminate the app in order to apply the new setting. In the April 2018 update, the default for the permission is On. In the October 2018 update, the default is Off.
More info
Related
Problem Summary
My app (in development), when run on the desktop, can both:
Write to & read from private storage
Write to & read from public storage.
However, when run on Android, only private storage is accessible.
How To Replicate The Issue
Instead of sharing excerpts of my project's codebase, let me refer to another codebase we share and have - the gluon-connect-file-provider project in Gluon Samples. The sample apps only demonstrate private storage usage. None demonstrate public storage usage, so in the gluon-connect-file-provider project, you can make the following change in com.gluonhq.samples.connect.file.Main.java:
Before
static {
ROOT_DIR = Services.get(StorageService.class)
.flatMap(StorageService:getPrivateStorage)
.orElseThrow(() -> new RuntimeException("Error retrieving private storage"));
}
After
static {
ROOT_DIR = Services.get(StorageService.class)
.flatMap(s -> s.getPublicStorage("Gluon"))
.orElseThrow(() -> new RuntimeException("Error retrieving public storage"));
ROOT_DIR.mkdir();
}
When starting the app on the Desktop after this change, you can first observe the directory ~/Gluon being created on your machine. Then, as you toggle the checkbox on/off in the app's Object Viewer screen, you can also confirm the underlying JSON file ~/Gluon/user.json is being updated. So, therefore, we can agree public storage works.
However, when deployed to Android, we can see file-permission related failures in the scrolling terminal during mvn -Pandroid gluonfx:nativerun. First, the Gluon directory fails to be created at startup and, consequently later, attempts to write the user.json file occur.
I thought the soluton was to define in the project the file src/android/AndroidManifest.xml. The default found at target/gluonfx/aarch64-android/gensrc/android/AndroidManifest.xml does not include the following permissions:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
So, I copied the generated AndroidManifest.xml file to src/android, including these entries to it. Even though the Android Settings shows me my app has Storage Permission, this still didn't resolve the problem.
Note - when preparing this post asking for your help, I noticed that, without also provisioning src/android/AndroidManifest.xml file with EXTERNAL READ/WRITE permissions for the gluon-connect-file-provider, the Android device already showed the deployed app had Storage Permission enabled.
I used two different Android devices to test with.
Pixel XL running Android version 10.
Samsung S9 running Android version 10.
I tested with the latest GluonHQ Attach dependency 4.0.13 and also with the oldest I found available, 4.0.7.
Is there something more that must be done for the Storage Attach Service to allow public storage access on Android? Please tell me how else to modify the gluon-connect-file-provider app to make it so, thank you.
Resolution
Update to Gluon Attach 4.0.14.
<dependency>
<groupId>com.gluonhq.attach</groupId>
<artifactId>storage</artifactId>
<version>4.0.14</version>
</dependency>
With this update, Storage Service will allow you to access pre-existing Android folders, like "Documents" for example. Or, as seen in this post's code excerpt above, you can define your own new directory like "Gluon", or naming the folder after your own App.
Extra
Another cascading result of this Attach update is, in addition to Storage Service, file sharing via the Share Service is now available on Android. Its JavaDoc states Storage Service as a requirement to use Share Service. Below is a quote from its documentation:
Note that on Android, the file has to be located in a public folder
(see StorageService#getPublicStorage), or sharing it won't be allowed.
I need to create a backup service so I intend to save the SQLite database file on each platform. The saved file should be available after the uninstall of the app.
I intend to use the Downloads folder (which should be available on every platform).
I have created an interface and use the following code per platform:
Interface:
public interface IBackupService
{
string GetDownloadPath();
}
Android:
public string GetDownloadPath()
{
return Android.OS.Environment.DirectoryDownloads;
}
UWP:
public string GetDownloadPath()
{
return Windows.Storage.KnownFolders.???????;
}
What should I do about that? Is there a public library that I could use?
There does not seem to be a general downloads folder as per this documentation on KnownFolders. So your assumption on the Downloads folder being on every platform doesn't seem to be correct.
If we dive in a bit further we get to the DocumentsLibrary which seems the obvious choice for this kind of purpose, but it is not. Microsoft says:
The Documents library is not intended for general use. For more info,
see App capability declarations. Also, see the following blog post.
Dealing with Documents: How (not) to use the documentsLibrary capability in Windows Store apps
The paragraph after that seems to describe what we have to do then;
If your app has to create and update files that only your app uses,
consider using the app's local folder. Get the app's local folder from
the Windows.Storage.ApplicationData.Current.LocalFolder property.
So, as I can extract from your question you only want to use storage for your app, so the Windows.Storage.ApplicationData.Current.LocalFolder seems to be the right choice according to Microsoft.
Hi I already posted a question Qt WinRT App cannot access file permission denied regarding ffmpeg library and video file read, and now I think the entire project should have some permission to access/modify the files system in WinRt Qt App.
Below is a simple code which create a directory if not exist, bu this also failing always, so I think it permission issue, and there are something should add on AppxManifest.xml.
QString dirname = QDir::homePath()+"/test";
QDir dir(dirname);
if(!dir.exists())
{
//dir.mkdir(dirname);
if(false==dir.mkpath(dirname)){
qDebug()<<"Creating "<<dirname<<" failed...";
}
}
Anyone have faces this before, any suggestion, tips ..
Thanks in Advance.
Haris
WinRT as a platform will not allow you to "simply" create files outside the sandbox of the application. There are certain directories you can use (Media, Photos, ...) in case you have the correct capability set. And even then you will only be allowed to open/create/read/write files selected by the file picker.
We're using TeamCity to automate MSBuild to use WebDeploy to push our application to our various servers.
For the most part, we've got this working, and great. One snag, though: we've got a folder that holds uploads that we don't want to have deleted during the publication.
How do I tell WebDeploy, "I know that folder's not in the compiled application. Ignore it. Just leave it alone."
If you're using the dirPath, filePath, or contentPath providers, you can specify the DoNotDelete rule to block deletions of files on the destination computer that do not exist on the source. The syntax to add to the command line would be -enableRule:DoNotDelete. For more information, see the provider articles mentioned and Web Deploy Rules.
I have a requirement to select a file from fileReference.browse(), but I want to browse a file to specific location say D:\Dir\file instead of the OS specific (The dialog box is native to the user's operating system).
Is it possible?
Thanks in Advance-
Since you're using File, I'm assuming you're using the Air runtime. To do this, you just need to set the path in the file constructor before you browser; like this:
var file:File = new File(somePath);
file.browse();
The only problem with this is that if you set it as an absolute path (like say, "c:\Users\SomeUser"), it might not work on Macs or Linux computers. Be sure to use some of the File class' built in static properties when you can, like these:
File.applicationStorageDirectory—a storage directory unique to each installed AIR application
File.applicationDirectory—the read-only directory where the application is installed (along with any installed assets)
File.desktopDirectory—the user's desktop directory
File.documentsDirectory—the user's documents directory
File.userDirectory—the user directory