Xbox One CopyAsync failing in Retail Mode only - c#

Basically the following code copies an entire folder from the app installation into the LocalCacheFolder so they can be manipulated/updated. In this case the contents of the folder called 'Data'
This code works fine on mobile, desktop and on Xbox in Dev Mode, but this line fails on Xbox in Retail Mode:
await file.CopyAsync(destinationFolder, file.Name, NameCollisionOption.FailIfExists);
This is also on a fresh install so I know the file(s) don't already exist.
Is there a different way to achieve this in Retail Mode, although in theory all UWP code should work across devices.
private async Task setupdatabase()
{
StorageFolder destinationContainer = Windows.Storage.ApplicationData.Current.LocalCacheFolder;
string root = Windows.ApplicationModel.Package.Current.InstalledLocation.Path;
string path = root + #"\Data";
StorageFolder sfolder = await StorageFolder.GetFolderFromPathAsync(path);
await CopyFolderAsync(sfolder, destinationContainer);
}
public static async Task CopyFolderAsync(StorageFolder source, StorageFolder destinationContainer, string desiredName = null)
{
StorageFolder destinationFolder = null;
destinationFolder = await destinationContainer.CreateFolderAsync(desiredName ?? source.Name, CreationCollisionOption.OpenIfExists);
foreach (var file in await source.GetFilesAsync())
{
await file.CopyAsync(destinationFolder, file.Name, NameCollisionOption.FailIfExists);
}
foreach (var folder in await source.GetFoldersAsync())
{
await CopyFolderAsync(folder, destinationFolder);
}
}

Seems like a bug with CopyAsync on the Xbox in Retail Mode
Replacing:
await file.CopyAsync(destinationFolder, file.Name, NameCollisionOption.FailIfExists);
with:
StorageFile sourcefile = null;
string sourcefiletext = null;
try
{
sourcefile = await source.GetFileAsync(file.Name);
sourcefiletext = await FileIO.ReadTextAsync(sourcefile);
}
catch (Exception e)
{
Debug.WriteLine "Read source error:" + e.ToString();
}
try
{
StorageFile destfile = await destinationFolder.CreateFileAsync(file.Name, CreationCollisionOption.FailIfExists);
await Windows.Storage.FileIO.WriteTextAsync(destfile, sourcefiletext);
}
catch (Exception e)
{
Debug.WriteLine "Write dest error:" + e.ToString();
}
Basically breaking it into 2 separate operations fixed the problem and my app now runs normally. This is now being submitted as a bug report
Update: not quite a bug, but a feature, from Microsoft:
The issue here is that the package install folder is encrypted on Xbox retail mode.  A package has permission to read it's own files which is why the ReadTextAsync+WriteTextAsync works. CopyAsync on the other hand attempts to copy the file with all attributes associated with the file (including encryption).

I'm not sure if that will be the case, as you code looks ok, but once I've stepped in a situation when running the app locally granted it some privileges. Maybe in this case also there are different privileges (for device/retail?) - thus, can you try to access the folder not via its path but directly with StorageFolder? Like this:
private async Task setupdatabase()
{
StorageFolder sfolder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync("Data");
await CopyFolderAsync(sfolder, ApplicationData.Current.LocalCacheFolder);
}
public static async Task CopyFolderAsync(StorageFolder source, StorageFolder destinationContainer, string desiredName = null)
{
StorageFolder destinationFolder = await destinationContainer.CreateFolderAsync(desiredName ?? source.Name, CreationCollisionOption.OpenIfExists);
var existingItems = await destinationFolder.GetFilesAsync(); // to check if files are already there
foreach (var file in (await source.GetFilesAsync()).Where(x => !existingItems.Any(y => y.Name == x.Name)))
{
await file.CopyAsync(destinationFolder, file.Name);
}
foreach (var folder in await source.GetFoldersAsync())
{
await CopyFolderAsync(folder, destinationFolder);
}
}
In second method I've changed FailIfExists attribute for a check-up of existing items - in case a problem is there.

Related

PCLStorage NuGetPackage not allow creating folder or file on device

I have a problem with creating folder with nuget package PCLStorage, I cannot create folder.
Nothing appear inside my files folder. I,m using my device not emulator there is android version 8.0
public async Task WriteDataAsync(string filename, string data)
{
string folderName = "SignatureSotrage";
IFolder folder = FileSystem.Current.LocalStorage;
folder = await folder.CreateFolderAsync(folderName, CreationCollisionOption.ReplaceExisting);
}
Here is a code where I run this function:
public ICommand AddCustomerCommand => new Command(async () =>
{
Signature = await SignatureFromStream();
// Signature should be != null
var customer = new Customer()
{
FullName = this.FullName,
IsAccepted = this.IsAccepted,
Birthday = this.Birthday
};
if(Signature != null)
{
customer.Image = this.Signature.ToString();
}
else
{
await Application.Current.MainPage.DisplayAlert("Błąd", "Nie wszystkie pola zostały poprawnie wypełnione", "OK");
return;
}
await DependencyService.Get<IFileHelper>().WriteDataAsync("signature.txt", "this is file");
//_context.Customers.Add(customer);
//_context.SaveChanges();
});
did you debug your code & check if the file/folder is actually getting created by your code or else it enters the catch block and goes with the normal flow?
Check for UserPermissions every time for reading & write permission before doing any operations on the storage. You can add the Nugget packet Plugin.Permission it handles everything for you, it adds both the permission in the manifest.
For checking user permissions always try calling CheckForStoragePermissions() before performing any operations on storage.(*DialogService is CustomDialogBox)
if( !await CheckForStoragePermissions() )
{
DialogService.Alert("Invalid Permission", "User declined permission for this action");
return;
}
private async Task<bool> CheckForStoragePermissions()
{
PermissionStatus storagePermissionStatus = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Storage);
if (storagePermissionStatus != PermissionStatus.Granted)
{
Dictionary<Permission, PermissionStatus> storagePermissionResult = await CrossPermissions.Current.RequestPermissionsAsync(Permission.Storage);
if (storagePermissionResult.ContainsKey(Permission.Storage))
{
storagePermissionStatus = storagePermissionResult[Permission.Storage];
}
}
return storagePermissionStatus == PermissionStatus.Granted;
}
I test the sample code on GitHub. https://github.com/dsplaisted/PCLStorage
Based on my test the folder path would like:
/data/user/0/PCLStorage.Test.Android/files/
It is a internal storage. You couldn't see the files without root permission. https://learn.microsoft.com/en-us/xamarin/android/platform/files/#working-with-internal-storage
If you want to see the files in internal storage, you could use adb tool. Please refer to the way in the link. How to write the username in a local txt file when login success and check on file for next login?

DisplayApplicationPicker not showing open with prompt

I'm creating a Xamarin Forms application (currently only UWP) where I want to open an PDF file from the local storage. In the UWP project I receive the file path form the Xamarin Portable Project. I use the following function to open the Open With Prompt.
public void OpenFileWith(string path)
{
Task.Run(async () =>
{
var file = await StorageFile.GetFileFromPathAsync(path);
if (file != null)
{
var options = new LauncherOptions();
options.DisplayApplicationPicker = true;
var success = await Launcher.LaunchFileAsync(file, options);
if (success)
{
//File Launched
}
else
{
//File Launch Failed
}
}
});
}
I think I've done everything correct according to the Documentation. When I don't add the LauncherOptions the file opens correctly in the default selected Application.
Is there something I'm missing. Permissions maybe? I know the documentation has a remark "This property is only implemented on Desktop devices.". I'm testing on a Desktop (Windows 10 via VMWare)
This should work:
public async Task OpenFileWithAsync(string path)
{
var file = await StorageFile.GetFileFromPathAsync(path);
if (file != null)
{
var options = new LauncherOptions();
options.DisplayApplicationPicker = true;
var success = await Launcher.LaunchFileAsync(file, options);
if (success)
{
//File Launched
}
else
{
//File Launch Failed
}
}
}
Call:
await OpenFileWithAsync(...);

UWP Check If File Exists

I am currently working on a Windows 10 UWP App.
The App needs to Check if a certain PDF File exists called "01-introduction", and if so open it.
I already have the code for if the file does not exist.
The Code Below is what i currently have:
try
{
var test = await DownloadsFolder.CreateFileAsync("01-Introduction.pdf", CreationCollisionOption.FailIfExists);
}
catch
{
}
This code Does not work correctly because to check if the file exists here, I attempt to create the file. However if the file does not already exist an empty file will be created. I do not want to create anything if the file does not exist, just open the PDF if it does.
If possible, i would like to look inside a folder which is in the downloads folder called "My Manuals".
Any help would be greatly appreciated.
public async Task<bool> IsFilePresent(string fileName)
{
var item = await ApplicationData.Current.LocalFolder.TryGetItemAsync(fileName);
return item != null;
}
But not support Win8/WP8.1
https://blogs.msdn.microsoft.com/shashankyerramilli/2014/02/17/check-if-a-file-exists-in-windows-phone-8-and-winrt-without-exception/
There are two methods
1) You can use StorageFolder.GetFileAsync() as this is also supported by Windows 8.1 and WP 8.1 devices.
try
{
StorageFile file = await DownloadsFolder.GetFileAsync("01-Introduction.pdf");
}
catch
{
Debug.WriteLine("File does not exits");
}
2) Or you can use FileInfo.Exists only supported for windows 10 UWP.
FileInfo fInfo = new FileInfo("01-Introduction.pdf");
if (!fInfo.Exists)
{
Debug.WriteLine("File does not exits");
}
System.IO.File.Exists is UWP way too. I test now in Windows IOT. it just works.
This helped me in my case:
ApplicationData.Current.LocalFolder.GetFileAsync(path).AsTask().ContinueWith(item => {
if (item.IsFaulted)
return; // file not found
else { /* process file here */ }
});
This worked for me running my UWP C# app on Windows 10...
StorageFolder app_StorageFolder = await StorageFolder.GetFolderFromPathAsync( #App.STORAGE_FOLDER_PATH );
var item = await app_StorageFolder.TryGetItemAsync(relative_file_pathname);
return item != null;
public override bool Exists(string filePath)
{
try
{
string path = Path.GetDirectoryName(filePath);
var fileName = Path.GetFileName(filePath);
StorageFolder accessFolder = StorageFolder.GetFolderFromPathAsync(path).AsTask().GetAwaiter().GetResult();
StorageFile file = accessFolder.GetFileAsync(fileName).AsTask().GetAwaiter().GetResult();
return file != null;
}
catch
{
return false;
}
}
You can use System.IO.File.
Example:
// If file located in local folder. You can do the same for other locations.
string rootPath = ApplicationData.Current.LocalFolder.Path;
string filePath = Path.Combine(rootPath, "fileName.pdf");
if (System.IO.File.Exists(filePath))
{
// File exists
}
else
{
// File doesn't exist
}
I'm doing a Win10 IoT Core UWP app and I have to check the file length instead of "Exists" because CreateFileAsync() already creates an empty file stub immediately. But I need that call before to determine the whole path the file will be located at.
So it's:
var destinationFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("MyFile.wow", ...);
if (new FileInfo(destinationFile.Path).Length > 0)
return destinationFile.Path;
In this way System.IO.File.Exists(filePath) I cannot test DocumentLibrary
because KnownFolders.DocumentsLibrary.Path return empty string
Next solution is very slow await DownloadsFolder.GetFileAsync("01-Introduction.pdf")
IMHO the best way is collect all files from folder and check the file name exist.
List<StorageFile> storageFileList = new List<StorageFile>();
storageFileList.AddRange(await KnownFolders.DocumentsLibrary.GetFilesAsync(CommonFileQuery.OrderByName));
bool fileExist = storageFileList.Any(x => x.Name == "01-Introduction.pdf");
CreateFileSync exposes an overload that let's you choose what to do if an existing file with the same name has been found in the directory, as such:
StorageFile localDbFile = await DownloadsFolder.CreateFileAsync(LocalDbName, CreationCollisionOption.OpenIfExists);
CreationCollisionOption is the object that you need to set up. In my example i'm opening the file instead of creating a new one.
Based on another answer here, I like
public static async Task<bool> DoesFileExist(string filePath) {
var directoryPath = System.IO.Path.GetDirectoryName(filePath);
var fileName = System.IO.Path.GetFileName(filePath);
var folder = await StorageFolder.GetFolderFromPathAsync(directoryPath);
var file = await folder.TryGetItemAsync(fileName);
return file != null;
}
You can use the FileInfo class in this case. It has a method called FileInfo.Exists() which returns a bool result
https://msdn.microsoft.com/en-us/library/system.io.fileinfo.exists(v=vs.110).aspx
EDIT:
If you want to check for the files existence, you will need to create a StorageFile object and call one of the GetFile.... methods. Such as:
StorageFile file = new StorageFile();
file.GetFileFromPathAsync("Insert path")
if(file == null)
{
/// File doesn't exist
}
I had a quick look to find the download folder path but no joy, but the GetFile method should give you the answer your looking for
On Window 10, for me, this is the most "elegant" way:
private static bool IsFileExistent(StorageFile file)
{
return File.Exists(Path.Combine(file.Path));
}
Or, as an extension if you prefer and will use it widely:
static class Extensions
{
public static bool Exists(this StorageFile file)
{
return File.Exists(Path.Combine(file.Path));
}
}

Exception, after loading file in WinRT

I'm having some problems. Here's my code:
private async void SetCollectionForGame()
{
maincollection = new Dictionary<string, string>();
bool statebase = await CheckExistingBase();
if (statebase)
{
//If file exists...
basefile = await folder.GetFileAsync(basefilename);
}
else
{
//If file does not exist...
SaveBaseFileAsync(filelink, folder, basefilename);
basefile = await folder.GetFileAsync(basefilename);
}
string content = String.Empty;
content = await FileIO.ReadTextAsync(basefile, Windows.Storage.Streams.UnicodeEncoding.Utf8);
//When the app first starts, I get an exception on the next line,
//because the variable "content" is null.
maincollection = JsonConvert.DeserializeObject<CollectionModel>(content).collection;
}
Does anybody know how to solve this? File downloading works fine, and after the download the file was created in a folder.
Based on the name, I suspect that SaveBaseFileAsync() executes some async operations. If it's true, you need to await it, i.e. call it as
await SaveBaseFileAsync(filelink, folder, basefilename);

How to check if a file exist in windowsstore app [duplicate]

This question already has answers here:
How to check if file exists in a Windows Store App?
(10 answers)
Closed 9 years ago.
While making a lab on window 8 app dev. I could not load all images needed. So inorder for the share part to work with a sharing imag I need to check if the image file is availeble.
The project is a windows grid app using XAML and C#
In the past I used
Using System.IO
... lost of code
privat void share()
....
if (File.exist(filename)
{
add file to share
}
If i try this in my window8 project. The File class is not found.
I search the internet but could not find a code example that checkes the existance in a windowsstore app in C#
Michiel
you need StorageFile not File
here is simple example to check and get the file
StorageFile file;
try {
file = await ApplicationData.Current.LocalFolder.GetFileAsync("foo.txt");
}
catch (FileNotFoundException) {
file = null;
}
you can write a function
public static async Task<bool> FileExistsAsync(this StorageFolder folder, string fileName)
{
try
{
await folder.GetFileAsync(fileName);
return true;
}
catch (FileNotFoundException)
{
return false;
}
}
If you know the path in your local storage and you have a bunch of files to check, you can do the following...
var sourceFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
sourceFolder = await sourceFolder.GetFolderAsync("Assets");
var files = await sourceFolder.GetFilesAsync();
var requiredFiles = new List<String> { "ThisWorks.png", "NotHere.png" };
foreach(var filename in requiredFiles)
{
// your example logic here...
Debug.WriteLine(filename + " " + (files.Any(f => f.Name == filename) ? "Exists" : "Doesn't exist"));
}

Categories