Create a folder on Local Folder of UWP app - c#

I want to create a folder named "TestFolder" on local folder of my uwp app. And need to upload files to it. It works fine on my system when I first manually create a folder((TestFolder) on local folder. but when I create app package for the project and tried to run it in another windows pc. It throws an error "System cant find the file specified". How can I resolve it?
StorageFolder appFolder = await ApplicationData.Current.LocalFolder.GetFolderAsync("TestFolder");
if (appFolder == null)
{
//Create folder
appFolder = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFolderAsync("TestFolder");
}

i would replace this few lines by this single line
var appFolder = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFolderAsync("TestFolder", Windows.Storage.CreationCollisionOption.OpenIfExists);

You can modify your code this way to get your desired result,
StorageFolder appFolder = await ApplicationData.Current.LocalFolder.GetFolderAsync("TestFolder");
if (appFolder == null)
{
//Create folder
appFolder = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFolderAsync("TestFolder",CreationCollisionOption.OpenIfExists);
}

Related

Error in setting custom StorageFolder in UWP app

I am working on a small UWP app that will take pictures and video and save it at a desired location on the PC.
Here is the code base I am using https://github.com/Microsoft/Windows-universal-samples/blob/master/Samples/CameraStarterKit/cs/MainPage.xaml.cs
When I try to initialize StorageFolder class with a desired path, it comes out as null. It only supports to initialize with following paths
var picturesLibrary = await StorageLibrary.GetLibraryAsync(KnownLibraryId.Documents);
var picturesLibrary = await StorageLibrary.GetLibraryAsync(KnownLibraryId.Music);
var picturesLibrary = await StorageLibrary.GetLibraryAsync(KnownLibraryId.Pictures);
var picturesLibrary = await StorageLibrary.GetLibraryAsync(KnownLibraryId.Videos);
Here is my code:
private StorageFolder _captureFolder = null;
_captureFolder = picturesLibrary.SaveFolder ?? ApplicationData.Current.LocalFolder;
var file = await _captureFolder.CreateFileAsync("SmartPhoto.jpg",
CreationCollisionOption.GenerateUniqueName);
var picturesLibrary = await Task.Run(() =>
System.IO.File.Move(file.Path, #"C:\Temp\Pictures\" + file.Name));
Since StorageFolder is not initializing for C:\Temp\Pictures, I tried to move that file from KnownLibraryId.Pictures to C:\Temp\Pictures and that fails too,
System.UnauthorizedAccessException: 'Access to the path
'C:\Temp\Pictures' is denied.'
This is by design, an UWP app can not - by default - access all locations on your hard drive...
It only has a specific set of folders allowed, but you can enable more by using the file picker or adding capabilities.
As mentioned in the docs here : https://learn.microsoft.com/en-us/windows/uwp/files/file-access-permissions
Universal Windows Apps (apps) can access certain file system locations
by default. Apps can also access additional locations through the file
picker, or by declaring capabilities.

UWP c# How to get a StorageFolder object of the app's download folder

I am creating files and folders using DownloadsFolder methods.
I'd like to get the parent folder as a StorageFolder instance so I can list and manipulate all the items in the app's downloads folder.
I've tried GetParentAsync() from a known StorageFile, but the return is null.
StorageFile sf = await DownloadsFolder.CreateFileAsync("testMarker");
StorageFolder dlFolder = await sf.GetParentAsync();
Is there any method to access this folder programmatically?
It seems your app doesn't has permission to read the Downloads directory. We can use GetParentAsync to get a parent the app has permissions for, but not to get folders the app doesn't have permissions in.
If we add the Music Library, Pictures Library and Videos Library to the Capabilities of the appxmanifest that we can use the GetParentAsync method to get the parent folder as a StorageFolder in these folder.
If you create a file or folder in the Downloads folder, we recommend that you add that item to your app's FutureAccessList so that your app can readily access that item in the future.
For more info, please refer the Locations Windows Store apps can access.
So if you want to get the other folders and files in DownloadsFolder, you should be able to Open files and folders with a picker.
It looks like this isn't possible - You can try to get the storage folder by using the Path with System.IO directly like so
var downloadPath = System.IO.Path.GetDirectoryName(storageFile.Path);
var downloadsFolder = await StorageFolder.GetFolderFromPathAsync(downloadPath);
But GetFolderFromPathAsync seems to throw an exception, I think windows just won't give you a reference to this folder.
A solution is to use a folder picker ONCE to pick the downloads folder (as part of the inital setup of the app). After that the app has full access to the downloads folder.
This code needs to be called once:
var folderPicker = new FolderPicker();
folderPicker.SuggestedStartLocation = PickerLocationId.Downloads;
folderPicker.FileTypeFilter.Add("*");
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("DownloadFolderToken", folder);
var messageDialog = new MessageDialog("Download folder: " + folder.Name);
await messageDialog.ShowAsync();
}
else
{
var messageDialog = new MessageDialog("Operation cancelled");
await messageDialog.ShowAsync();
}
This code can then be used to directly access the downloads folder:
var downloadsFolder = await StorageApplicationPermissions.FutureAccessList.GetFolderAsync("DownloadFolderToken");
IReadOnlyList <StorageFile> fileList = await downloadsFolder.GetFilesAsync();
StringBuilder outputText = new StringBuilder();
outputText.AppendLine("Files:");
foreach (StorageFile file in fileList)
{
outputText.Append(file.Name + "\n");
await file.DeleteAsync();
}

ReadLinesAsync in UWP from absolute file path

I get error
The filename, directory name, or volume label syntax is incorrect. (Exception from HRESULT: 0x8007007B)
My code is
public async void ReadFile()
{
var path = #"F:\VS\WriteLines.xls";
var folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
var file = await folder.GetFileAsync(path);
var readFile = await Windows.Storage.FileIO.ReadLinesAsync(file);
foreach (var line in readFile.OrderBy(line =>
{
int lineNo;
var success = int.TryParse(line.Split(';')[4], out lineNo);
if (success) return lineNo;
return int.MaxValue;
}))
{
itemsControl.Items.Add(line);
}
}
The error shows up at var file = await folder.GetFileAsync(path);
You cannot read a file from an arbitrary location on disk in a UWP App.
There are a couple of ways you can still accomplish your task:
You can add the WriteLines.xls file to your project and set it's build action to Content and Copy to output Directory to Copy if newer. You can then access the file with the code you have by simply replacing the "path" value to:
var path = #"WriteLines.xls"
More details here
If you need to be able to read any files from disk, you need to either use a FilePicker to select the file or copy the file in the Documents Folder and change the folder to:
var folder = KnownFolders.DocumentsLibrary;
More details here
You are asking for file with absolute path from application's local folder - hence it throws that error as you provide path that includes drive name.
In general UWP is very restrictive on where/how you can get files from - I don't think you can get it from absolute path in the sample (app needs more permissions to get to similar places). You can try StorageFile.GetFileFromPathAsync.
Detailed info on locations app can access - UWP apps on Windows 10: File access permissions.

Getting all files in UWP app folder

For UWP, it is easy to get all files in the app local folder as:
IReadOnlyList<StorageFile> files = await ApplicationData.Current.LocalFolder.GetFilesAsync();
You can now iterate on the files list and even get further info on individual files.
I would like a similar all-file-getter for an app folder, for instance, consider the /Assets folder where app *.png files are stored.
Single file with a known name is no problem; I can refer to it quite easily as:
StorageFile.GetFileFromApplicationUriAsync(new Uri(#"ms-appx:///Assets/StoreLogo.png"))
My question is, therefore, is there a similar thing for getting all files in an app folder, such as /Assets folder? Logically, it should be something like StorageFile.GetFilesFromApplicationFolderUriAsync(new Uri(#"ms-appx:///Assets")) but unaware if an equivalent of the LocalFolder shown above exists.
You can access you installation folder by using Package.InstalledLocation. Therefore your code can look like this:
StorageFolder appInstalledFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
StorageFolder assets = await appInstalledFolder.GetFolderAsync("Assets");
var files = await assets.GetFilesAsync();
var storageFolder = await ApplicationData.Current.LocalFolder.GetFolderAsync("Assets");
var files = await storageFolder.GetFilesAsync();
https://learn.microsoft.com/en-us/uwp/api/windows.storage.applicationdata

FileIO with Windows Rt and C#

Wow, is this way more complicated than it needs to be. Can someone explain to me why the following code works:
string stringToWrite = "SomeStuff";
Windows.ApplicationModel.Package package = Windows.ApplicationModel.Package.Current;
Windows.Storage.StorageFolder installedLocation = package.InstalledLocation;
var files = await installedLocation.GetFilesAsync();
foreach (Windows.Storage.StorageFile sf in files)
{
if (sf.Name.Equals("log.txt"))
{
await FileIO.AppendTextAsync(sf, stringToWrite);
}
}
And yet the following fails with AccessDenied:
Windows.ApplicationModel.Package package = Windows.ApplicationModel.Package.Current;
Windows.Storage.StorageFolder installedLocation = package.InstalledLocation;
var log = await installedLocation.GetFileAsync("log.txt");
await FileIO.AppendTextAsync(log, stringToWrite);
The only difference is looping through the files returned by the GetFilesAsync method vs getting the file by name. By the way, getting the file by name works because if I misspell log.txt in GetFileAsync, I get an exception.
Very confusing....
You should not be using your installed location to write any files. It is supposed to be read-only as per MSDN: File Access/Permissions in Windows Store Apps:
The app's install directory is a read-only location. You can’t gain access to the install directory through the file picker.
You should be using either the Local, Roaming, or Temporary storage locations.
See this link: MSDN: Quickstart Local Application Data

Categories