UnauthorizedAccessException when trying to access files - c#

New to C#/VS, trying to get a listing of files, feel like this has a simple answer but can;t find.
Basically, wanting to get a file listing, tried various methods but for simplicity, why does
var f = Directory.GetFiles(#"C:\");
returns
System.UnauthorizedAccessException: 'Access to the path 'C:\' is
denied.'
Tried running VS as administator, tried on sub folders, tried with sub folders having Everyone with full control permission. Same results.

In order to access an arbitrary folder from your UWP app, the user first needs to provide consent via the FolderPicker dialog:
FolderPicker picker = new FolderPicker();
picker.SuggestedStartLocation = PickerLocationId.ComputerFolder;
picker.FileTypeFilter.Add("*");
StorageFolder folder = await picker.PickSingleFolderAsync();
var files = await folder.GetFilesAsync();
https://learn.microsoft.com/en-us/uwp/api/Windows.Storage.Pickers.FolderPicker

System.UnauthorizedAccessException: 'Access to the path 'C:\' is denied.'
Rob has said Windows Store apps run sandboxed and have very limited access to the file system in his blog. Access to other locations is available only through a broker process. This broker process runs with the user’s full privileges.
So you could access the folder that mentioned by Stefan Wick with full privileges FolderPicker.
Apps can access certain file system locations by default. Apps can also access additional locations by declaring capabilities.
There are some locations that all apps can access. Such as InstalledLocation LocalFolder.
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
In addition to the default locations, an app can access additional files and folders by declaring capabilities in the app manifest. Such as Pictures Music library.
<Capabilities><uap:Capability Name="musicLibrary"/></Capabilities>
<Capabilities><uap:Capability Name="picturesLibrary"/></Capabilities>
For more, you could refer to File access permissions. And Skip the path: stick to the StorageFile will help you understand uwp file access in depth.

Related

Environment.GetFolderPath(Environment.SpecialFolder) is returning wrong value

I have a UWP project, and wrote this code:
foreach (var foldertype in (Environment.SpecialFolder[])Enum.GetValues(typeof(Environment.SpecialFolder)))
{
//string d = Environment.CurrentDirectory;
var path = Environment.GetFolderPath(foldertype);
var folder = await StorageFolder.GetFolderFromPathAsync(path);
StorageApplicationPermissions.FutureAccessList.Add(folder, folder.Path);
Debug.WriteLine($"Opened the folder: {folder.DisplayName}");
this.MenuFolderItems.Add(new MenuFolderItem(folder));
}
It is supposed to enumerate all the special folders, and get their folder. However, while debugging, this is what happens:
foldertype = Desktop
path = "C:\\Users\\cuent\\AppData\\Local\\Packages\\402b6149-1adf-4994-abc9-504111b3b972_a5s740xv383r0\\LocalState\\Desktop"
folder = [ERROR] System.IO.FileNotFoundException: 'The system cannot find the file specified. (Exception from HRESULT: 0x80070002)'
I do not know what is happening here, it seems to be appending the path to the installed location of the app. How do I fix this?
Expected output of GetFolderPath() is wherever the Desktop is, not the weird path.
UWP apps are different from desktop applications when accessing the file system. UWP apps are running in the sandbox so there are limitations for UWP apps when trying to access the file system. You could check this document: File access permissions. The document lists all the locations that UWP apps have permission to access.
Back to your scenario, what you need first is a broadFileSystemAccess restricted capability. This capability enables your app could use the StorageFolder.GetFolderFromPathAsync() API with a Path parameter. This is mentioned in the last part of the document I posted above.
Then the second issue is the Environment.GetFolderPath API. It looks like the API will return a Path that points to a local folder inside the app's local folder. But there is no such desktop folder inside the app's local folder so you will get the FileNotFoundException. You might need to set the correct path by yourself like C:\Users\your user name\Desktop. After that, your code should be able to work correctly.

Where to store user-accessible files in UWP?

I have here a cross platform app, which uses DependencyService to get a file path for my log file. This works fine for ApplicationData.Current.LocalCacheFolder.Path, but now the log file should be made accessible to the user. The idea was that the user plugs his device into the PC, copies the log file from it and then send it to me via normal email. (Currently, it is not planned to distribute the app via the store and it is not guaranteed, that the user has an email account setup on his device.)
First, I tried with KnownFolders.DocumentsLibrary, but here I get Access is denied. If I look into the documentation, this folder is not intended for my use. Other locations also doesn't seem to fit.
Is this approach feasible in UWP?
You need to add Capabilities of documentsLibrary to access KnownFolders.DocumentsLibrary
To add go to "Package.appxmanifest" in YourApp.UWP > "Capability" tab and check the capability where you want to store. Example: "Picture Library" or "Removable Storage"
New anser:
I found out, that Access denied only occurs on desktop, not mobile. Afterwards, I found this post, which describes why this does happen. It's because of the permission handling and that I throw away my permissions. There are several possibilites how to handle this situation:
Use a picker to ask the user
Use FutureAccessList
Example:
FolderPicker folderPicker = new FolderPicker();
folderPicker.FileTypeFilter.Add("*");
StorageFolder folder = await folderPicker.PickSingleFolderAsync();
if (folder != null)
{
StorageApplicationPermissions.FutureAccessList.AddOrReplace("PickedFolderToken", folder);
}
StorageFolder newFolder;
newFolder = await StorageApplicationPermissions.FutureAccessList.GetFolderAsync("PickedFolderToken");
await newFolder.CreateFileAsync("test.txt");
Use streams instead of paths (for library)
Make a copy of the file and store it into the application data folder
Example:
StorageFolder tempFolder = await StorageFolder.GetFolderFromPathAsync(Path.Combine(ApplicationData.Current.LocalCacheFolder.Path, "YourApp"));
StorageFile tempFile = await tempFolder.CreateFileAsync(Path.GetFileName(pathToAttachment), CreationCollisionOption.ReplaceExisting);
await file.CopyAndReplaceAsync(tempFile);
Old answer:
My current solution is that I offer a button in my app, which calls natively the FolderPicker via DependencyService and only on UWP. With this the user can select the location and I copy the file to this location. Works nicely, despite I wish I didn't had to do something only for one platform.

UWP: Access to the path denied [duplicate]

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

Creating and accessing a folder with in the application for windows phone 8.1

Can some one help me with creating and accessing folder with in the application (at the same place where we have our assets,html folders). My requirement is to download a file in that folder and then access it.
I have used:
StorageFolder destinationFolder = await Package.Current.InstalledLocation.GetFolderAsync("Assets");
StorageFile localFile = await destinationFolder.CreateFileAsync(localFileName, CreationCollisionOption.ReplaceExisting);
when I checked it showing the path as: Assets folder path: C:\Data\SharedData\PhoneTools\AppxLayouts\785bb4a5-5b27-4720-918e-7ceaeeb58c52VS.Debug..
If your file saved is not being for any use to end user directly then you should use App local folders. If you have very few amount of data then you can use LocalSettings also. for more available storage options and process of accessing check this link.

Path.GetTempPath() not available in Windows Store Apps

I am trying to get the temp directory by using:
string tempFolder = System.IO.Path.GetTempPath();
However that method does not exist. I can see all the other methods in intelliSense though.
Why is that method not available. Is there another way to get the temp folder location in a Windows Store app?
Create the temporary file in your ApplicatonData storage. You will have to generate your own filename with a guid or timestamp.
Windows.Storage.StorageFolder temporaryFolder = ApplicationData.Current.TemporaryFolder;
StorageFile sampleFile = await temporaryFolder.CreateFileAsync("dataFile.txt", CreationCollisionOption.ReplaceExisting);
await FileIO.WriteTextAsync(sampleFile, formatter.Format(DateTime.Now));
A Windows Store App is sandboxed, so you are expected to read and write to folders inside your sandboxed application folder. You won't be able to write to the traditional temp folder C:\Windows\TEMP, as you probably want, and yeah you are out of luck. There are a few other locations outside of your application folder that you have access to, but in most cases your access is limited.
The KnownFolders class is how you access the following locations.
CameraRoll
DocumentsLibrary
HomeGroup
MediaServerDevices
MusicLibrary
PicturesLibrary
Playlists
RemovableDevices
SavedPictures
VideosLibrary
KnownFolders class on MSDN

Categories