UWP StorageFile Access Denied in LocalFolder in Release build - c#

I am trying to write a very simple program that reads a txt file when it starts. The file is in "ApplicationData.Current.LocalFolder", as it is supposed to be something I can access without explicitly telling the user. However, after I try to check the existence of and to create the file, I receive a access denied exception at 'file.OpenStreamForReadAsync()' at the 2nd line of the second method.
The StorageFile object is passed from the checking process, so that I think I am able to avoid the situation where two objects try to open the same file. However, the problem persists.
public async Task<StorageFile> checkConfig()
{
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
if (await localFolder.TryGetItemAsync("ifthen.txt") != null)
return await localFolder.GetFileAsync("ifthen.txt");
else
return await localFolder.CreateFileAsync("ifthen.txt");
}
public async void load()
{
Windows.Storage.StorageFile file = await checkConfig();
using (var input = await file.OpenStreamForReadAsync())
using (var dataReader = new StreamReader(input))
{
...
}
}
Furthermore, the problem only occurs in Release Build. Debug Build always works fine, regardless of whether the file exists or not before launching the program.

Related

UWP, Access to the path is denied

I read some topic about file permission.
Someone said "App can access directories and files which the user manually selected with the FileOpenPicker or FolderPicker"
My codes are like as below:
public async void CsvParse()
{
var picker = new Windows.Storage.Pickers.FileOpenPicker();
picker.FileTypeFilter.Add(".csv");
Windows.Storage.StorageFile file = await picker.PickSingleFileAsync();
if (file != null)
{
string[] lines = File.ReadAllLines(file.Path);//this is where app stops working and gives error message.
}
}
Even when I choose file with FilePicker, it still gives me error. But when I choose file from appx folder, it works fine.
Is there a way to access other locations than app's folder?
try it this way:
public async void CsvParse()
{
var picker = new Windows.Storage.Pickers.FileOpenPicker();
picker.FileTypeFilter.Add(".csv");
Windows.Storage.StorageFile file = await picker.PickSingleFileAsync();
if (file != null)
{
IList<string> lines = await FileIO.ReadLinesAsync(file);//this is where app stops working and gives error message.
}
}
the StorageFile is the way you get access to a file. File.ReadAllLines(file.Path) you are passing a Filename, not the StorageFile but just the filepath is not enough for getting access

Creating txt file on hololens

I'm trying to create an app on the hololens that creates and writes to a text file to log inputs from the user. Currently, I'm stuck on trying to make the file and access it from the file explorer or the one drive. This is the method I have:
public void createFile()
{
#if WINDOWS_UWP
Task task = new Task(
async () =>
{
testText.text="hi";
StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
StorageFile textFileForWrite = await storageFolder.CreateFileAsync("Myfile.txt");
});
task.Start();
task.Wait();
#endif
}
It's basically what I found here: https://forums.hololens.com/discussion/1862/how-to-deploy-and-read-data-file-with-app, but when I try to run that method, the app on the hololens freezes for a bit then closes. Is there something wrong with the code? Any idea what is going on?
Thanks in advance
In Unity, you can use Application.persistentDataPath: https://docs.unity3d.com/ScriptReference/Application-persistentDataPath.html
In Device Portal/File Explorer, it is mapped to LocalAppData/YourApp/LocalState. The code below would write "MyFile.txt" there.
using System.IO;
string path = Path.Combine(Application.persistentDataPath, "MyFile.txt");
using (TextWriter writer = File.CreateText(path))
{
// TODO write text here
}

No permission to delete / overwrite files in subfolders of ApplicationData.Current.LocalFolder

I am facing an problem with files that I create within my application in dedicated sub folders of ApplicationData.Current.LocalFolder. I can create sub folders with ApplicationData.Current.LocalFolder.CreateFolderAsync() and even place files in it. But as soon as I try to overwrite or delete files, I get an access violation exception. (Read Access is still possible)
Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
I looked up the UWP pages but most of the time they simply create a new folder and that's it.
My attempt to overwrite the file:
public async Task WriteFileAsync(string filename, Stream fileContent)
{
StorageFolder folder = ApplicationData.Current.LocalFolder;
var deepFolders = filename.Split('/');
if (deepFolders != null)
{
for (var i=0; i<deepFolders.Length - 1; i++)
{
folder = await folder.GetFolderAsync(deepFolders[i]);
}
filename = deepFolders[deepFolders.Length - 1];
}
try
{
StorageFile oldFile = await folder.GetFileAsync(filename);
await oldFile.DeleteAsync();
}
catch (FileNotFoundException) { }
StorageFile file = await folder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
}
The first time it runs just fine, but as soon as the overwrite should take place, I get the exception.
Running the whole stuff without sub-folders works like charm.
The attempt to first read and delete the file resulted in the same exception already during the deletion.

How to add folder to StorageLibrary without RequestAddFolderAsync in C#

I need to save app files to plugged SD card. I'm using UWP and Windows 10.
MSDN tells how to do it with Windows Libraries.
var myPicsLibrary = await Windows.Storage.StorageLibrary.GetLibraryAsync(Windows.Storage.KnownLibraryId.Pictures);
await myPicsLibrary.RequestAddFolderAsync();
RequestAddFolderAsync() shows file picker, where user can choose folder to add into Pictures. In my case it's a folder, created on SD card.
Is there a way to do this thing without file picker dialog?
I'm trying to do like this:
var myPicsLibrary = await Windows.Storage.StorageLibrary.GetLibraryAsync(Windows.Storage.KnownLibraryId.Pictures);
// Get the logical root folder for all external storage devices.
StorageFolder externalDevices = Windows.Storage.KnownFolders.RemovableDevices;
// Get the first child folder, which represents the SD card.
StorageFolder sdCard = (await externalDevices.GetFoldersAsync()).FirstOrDefault();
var folder = await sdCard.CreateFolderAsync("MySDCardFolder");
myPicsLibrary.Folders.Insert(myDocs.Folders.Count+1, folder); // NotImplementedException: 'The method or operation is not implemented.'
myPicsLibrary.Folders.Add(folder); // NotImplementedException: 'The method or operation is not implemented.'
Or maybe I can do the same without using Windows Libraries directly working with SDCard?
Thanks a lot!
EDIT:
In the another hand my question sounds like "How to save files to plugged SD card?"
The StorageLibrary.Folders gets the folders in the current library, it return the IObservableVector of the StorageFolder. When we add the folder into the IObservableVector, it will not change the folder in files system. It will throw the "The method or operation is not implemented." exception.
We should be able to get the name of the folder, and create the folder uses that name. Then we can StorageFile.CopyAsync method to copy the file that in your folder.
For example:
public static async Task CopyFolderAsync(StorageFolder source, StorageFolder destinationContainer, string desiredName = null)
{
StorageFolder destinationFolder = null;
destinationFolder = await destinationContainer.CreateFolderAsync(
desiredName ?? source.Name, CreationCollisionOption.ReplaceExisting);
foreach (var file in await source.GetFilesAsync())
{
await file.CopyAsync(destinationFolder, file.Name, NameCollisionOption.ReplaceExisting);
}
foreach (var folder in await source.GetFoldersAsync())
{
await CopyFolderAsync(folder, destinationFolder);
}
}
Then we can use the CopyFolderAsync method to copy the folder in the Picture Library.
var myPicsLibrary = await Windows.Storage.StorageLibrary.GetLibraryAsync(Windows.Storage.KnownLibraryId.Pictures);
var myfolder = myPicsLibrary.Folders[0];
StorageFolder externalDevices = Windows.Storage.KnownFolders.RemovableDevices;
StorageFolder sdCard = (await externalDevices.GetFoldersAsync()).FirstOrDefault();
var folder = await sdCard.CreateFolderAsync("MySDCardFolder");
await CopyFolderAsync(folder, myfolder);
As I get from your question you need to create a Folder in PicturesLibrary .
You can use the code below to add a folder into PicturesLibrary
await Windows.Storage.KnownFolders.PicturesLibrary.CreateFolderAsync("MySDCardFolder");
if you want to make it on SD Card only Maybe KnownFolders.RemovableDevices Should be helpful . I didn't used KnownFolders.RemovableDevices yet but if you have any issue let me know to test it on my phone directly

Opening PDF with Adobe works but I have a message "do you want to replace that file ?

I want to open a PDF file. If I choose PDF Reader, it works fine.
If I choose Adobe Reader, I have a message : "letter.pdf already exists. Do you want to replace that file ?"
If I click Yes, it works fine.. And if I click No, it works fine too ! So why do I have this message ?
Here's my code. At first, I tried this
// Access local storage
IStorageFolder local = ApplicationData.Current.LocalFolder;
IStorageFile storageFile = await local.CreateFileAsync("letter.pdf", CreationCollisionOption.ReplaceExisting);
using (Stream stream = await storageFile.OpenStreamForWriteAsync())
{
await stream.WriteAsync(document, 0, document.Length);
}
IStorageFile courrier = await local.GetFileAsync("letter.pdf");
// Launch
var success = await Launcher.LaunchFileAsync(courrier);
If the file already exists, I modified my code to delete it to make sure there is only one file to open.
// Access local storage
IStorageFolder local = ApplicationData.Current.LocalFolder;
if (await local.GetFileAsync("letter.pdf") != null)
{
IStorageFile tmp = await local.GetFileAsync("letter.pdf");
await tmp.DeleteAsync(StorageDeleteOption.PermanentDelete);
}
IStorageFile storageFile = await local.CreateFileAsync("letter.pdf", CreationCollisionOption.ReplaceExisting);
using (Stream stream = await storageFile.OpenStreamForWriteAsync())
{
await stream.WriteAsync(document, 0, document.Length);
}
if (storageFile!= null)
{
var success = await Launcher.LaunchFileAsync(storageFile);
return success;
}
So I have this code, but I still have the message, only with Adobe.. Can anyone explain that ?
Thank you very much !
The file is being stored on the phone, not just locally within the app. In order to read it in adobe, it automatically moves a copy into a common folder area.
Because of that, there is already a letters.pdf file there, even if you deleted it from local storage.
You can't (and shouldn't) just assume the user wants to override/delete letters.pdf from their phone, so the pop up needs to stay.
The good news is, whichever option they chose they will still read the file you want them to open

Categories

Resources