synchronous write on a file different exceptions and access denied - c#

i need to synchronous write on a file, i know that there are methods to do that async but thats not my case.
after navigate from an other page.xml i come to my main page and in the onnavigated method i need to write in a file.txt a text that i takes from the previous page.
(that's how i thought to save a data from a first open of the app and every time the app will open it will load these data to not make tutorial anymore)
protected override void OnNavigatedTo(NavigationEventArgs e)
{
Regione = e.Parameter as regione;
string ciccio = "" + Regione2.RegNome.ToString() + "," + Regione2.RegLat.ToString() + "," + Regione2.regLon.ToString();
//File.WriteAllText("Data/data1.txt", ciccio);
File.WriteAllText("C:/Users/giuli/Documents/Source/xxx/XXX/XXX/Data/data1.txt", ciccio);
}
and if i try with the File.WriteAllText("C:/Users/giuli/Documents/Source/xxx/XXX/XXX/Data/data1.txt", ciccio);
i get an exception that tell me that i cannot use sync method:
"Synchronous operations should not be performed on the UI thread. Consider wrapping this method in Task.Run."
ok but i need to, and i tried with File.WriteAllText("Data/data1.txt", ciccio);
and i get an
System.UnauthorizedAccessException:
access to the path denied
and if i try with some async method
Windows.Storage.StorageFolder installedLocation = Windows.ApplicationModel.Package.Current.InstalledLocation;
StorageFile File2 = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Data/data1.txt"));
await Windows.Storage.FileIO.WriteTextAsync(File2, ciccio1);
i get an
System.UnauthorizedAccessException: 'Accesso negato
i created the file data.txt via visual studio, it's not open on VS and i think noone know that that file exist rather than VS.
How can i finally write on that file ?
Thanks .)
"the read sync and async method work perfect so it's not a problem about the path
Regione.RegNome = File.ReadAllText("Data/data1.txt");"

Other than the error saying not to call synchronous API from the UI thread none of the other errors you have are related to the API being synchronous or asynchronous. They all look like legitimate errors because the app doesn't have access to write to the locations it attempts to write to.
Use ApplicationData.RoamingSettings to store your seen-the-tutorial flag. You don't need to manage this yourself in a file. See Store and retrieve app settings and data for details.
The UnauthorizedAccessException on ms-appx:///Data/data1.txt is because an app's install location is read only. Sync vs. async isn't relevant here: reading but not writing from this location is expected to work. The install location is also shared between users, so even if the app could write here it wouldn't be a good place for user-specific data like a seen-the-tutorial flag. If you want to store this in a writable user-specific file then use ApplicationData.LocalFolder or RoamingFolder as described in Store and retrieve app settings and data
The app doesn't have direct access to the Documents folder. With appropriate capabilities it can get brokered access to that folder via the StorageFile class, but the app won't have direct access using System.IO.File.

Related

Access Denied when creating SQLite DB file

I'm trying to create the database file to initialize it but I'm getting "Access Denied" error during execution. I think is something related with permissions but I'm not able to find any information that could fix it, since every guide I check does it the same way.
This is an UWP application using C# and SQLite library. Thanks in advance for the help.
In the past I've tried to also create json file with other methods but I've never been able to create a file from a UWP application
Code that raises an error:
private const string DBName = "data.sqlite";
if (!File.Exists(Path.GetFullPath(DBName)))
{
SQLiteConnection.CreateFile(DBName);
RecentlyCreated = true;
}
Error message:
System.UnauthorizedAccessException: 'Access to the path 'C:\Users\myuser\source\repos\Pass\Pass\bin\x64\Debug\AppX\dataAccount.sqlite'
is denied.'
UWP has a very limited access to the user filesystem, as it described at File access permissions specification. You can use user libraries (downloads, documents) for storing the data (after allowing an access in appxmanifest file) or application data store (more viable in your case). Try to define DBName as
string DBName = ApplicationData.Current.LocalFolder.Path + #"\data.sqlite";
Or you can allow broadFileSystemAccess using link above

UWP FolderPicker does not grant me permission to access folder

The following code is taken from Microsoft's documentation on the subject with slight modification:
var folderPicker = new Windows.Storage.Pickers.FolderPicker();
folderPicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.Desktop;
folderPicker.FileTypeFilter.Add("*");
Windows.Storage.StorageFolder folder = await folderPicker.PickSingleFolderAsync();
if (folder != null)
{
// Application now has read/write access to all contents in the picked folder
// (including other sub-folder contents)
Windows.Storage.AccessCache.StorageApplicationPermissions.
FutureAccessList.AddOrReplace("PickedFolderToken", folder);
if (Directory.Exists(folder.Path)) // fails, I don't have permission to read this folder even though the documentation suggests that I should have access
{
this.textBlock.Text = "Picked folder: " + folder.Name; // never gets printed
}
}
I also tried adding the broadFileSystemAccess capability to the application manifest. What am I missing here?
broadFileSystemAccess only works with Windows.Storage namespace, and this is already mentioned in the docs as follows :
This is a restricted capability. On first use, the system will prompt
the user to allow access. Access is configurable in Settings > Privacy
File system. If you submit an app to the Store that declares this capability, you will need to supply additional descriptions of why
your app needs this capability, and how it intends to use it. This
capability works for APIs in the Windows.Storage namespace
UWP applications have limited access and the regular IO commands do not work, including System.Diagnostic.Process. The only way to launch a process is to use FullTrustProcessLauncher Class as documented here: https://learn.microsoft.com/en-us/uwp/api/Windows.ApplicationModel.FullTrustProcessLauncher.
Working examples can be found here: https://github.com/StefanWickDev/UWP-FullTrust
However, this does not solve the problem of working with existing libraries since they are not processes in the first place. We now have an RPC service where the requests are made from the service and results obtained.

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.

How can I detect if a StorageFile was renamed or deleted in a UWP app?

For a Windows Store app: how can I detect if a StorageFile was renamed or deleted outside of my application while it is open in my app?
I have a Windows 10 UWP app running on the desktop. The app lets the user open and edit documents.
Things I've tried:
Checking DateModified:
I tried checking storageFile.GetBasicPropertiesAsync().DateModified, but even it I delete the file and empty the trash, the call returns successfully with the (old) DateModified. (I assume it uses an in-memory version and does not check the file on disk)
Re-Open the StorageFile:
I then tried to "re-open" the file using StorageFile.GetFileFromPathAsync(file.Path). This correctly threw a FileNotFoundException the first time.
However, later this failed with an Unauthorized access/permission denied exception. It kind of makes sense, because I need the user to pick the file in a FileOpenPicker to have my app get permission to use it.
Monitor the parent folder:
Did not get far with this one. I tried to use StorageFolder.CreateFileQuery(), but I can't access the parent folder form the StorageFile instance (again, it makes sense, because my app does not have permission to access the parent folder)
Found a nice and short way to check if file was deleted:
public async bool StorageFileExists(StorageFile file)
{
try
{
var stream = await StorageFile.OpenReadAsync();
stream.Dispose();
return true;
}
catch (FileNotFoundException e)
{
return false;
} //Other exceptions are not caught on purpose and should propagate
}
Even in a UWP App you can use System.IO.File.Exists(String).
https://msdn.microsoft.com/de-de/library/system.io.file.exists(v=vs.110).aspx

WP8.1: Exporting data to "reachable" .txt file

I am creating an app that is tracking GPS data (latitude, longitude, altitude). So far I've managed to create a listbox that gets an extra line everytime another set of coordinates is made.
I tried writing it to file with this function.
private async Task WriteToFile()
{
string ResultString = string.Join("\n", locationData.ToArray());
byte[] fileBytes = System.Text.Encoding.UTF8.GetBytes(ResultString);
StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
var dataFolder = await local.CreateFolderAsync("DataFolder", CreationCollisionOption.OpenIfExists);
var file = await dataFolder.CreateFileAsync("DataFile.txt", CreationCollisionOption.ReplaceExisting);
using (var s = await file.OpenStreamForWriteAsync())
{
s.Write(fileBytes, 0, fileBytes.Length);
}
}
I can read this file, but I can't view this "DataFile.txt" anywhere in Files app.
I tried using WP Power Tools, but it doesn't work with 8.1, I am unable to update Visual Studio 2013 in order to get ISExplorer.exe working and
IsoStoreSpy keeps crashing everytime I try to connect my Lumia 620.
But all of this looks too complitated to me. Is there any other way of getting this .txt file without messing with IsolatedStorage? I feel like I'm missing out on something so simple here, I just can't believe that such basic thing as writing output to .txt, that can be later used by PC, couldn't be available.
You're storing the file in your app's local storage (Windows.Storage.ApplicationData.Current.LocalFolder), which is the same as Isolated Storage.
The Files app can see only public locations not app-specific locations.
There are several ways your app can share this file more globally:
Use the share contract to let the user share the file to wherever they'd like (OneNote, Email, etc.). See Sharing and exchanging data
Let the user choose where to save the file with a FileSavePicker. See How to save files through file pickers
Save the file on the SD card. See Access the SD card in Windows Phone apps.
Save the file to the user's OneDrive. See Guidelines for accessing OneDrive from an app
Save to a RoamingFolder so the file can be read by the same app on a Windows PC, which can then export using similar methods (especially a file picker) but on the desktop device. See Quickstart: Roaming app data

Categories