I am using Json files for local storage for my app. While using Visual Studio's emulator reading and writing to the files works correctly. When I connect a device and try to run on that device I cannot access my Json files.
My json files are set to Content and Copy always.
Here is my try statement for reading the file. I have tried two main ways to access the file Current.InstalledLocation and Uri("ms-appx:///). Both seem to work in the emulator but neither work on the device.
try
{
var package = Windows.ApplicationModel.Package.Current.InstalledLocation;
StorageFolder folder = await package.GetFolderAsync("Data");
StorageFile file = await folder.GetFileAsync("Users.json");
//Uri dataUri = new Uri("ms-appx:///Data/Users.json");
//StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(dataUri);
string jsonText = await FileIO.ReadTextAsync(file);
JsonArray jsonArray = JsonArray.Parse(jsonText);
foreach (JsonValue userValue in jsonArray)
{
//Build my model object out of json
}
}
catch(Exception e)
{
//Creating instance for the MessageDialog Class
//and passing the message in it's Constructor
MessageDialog msgbox = new MessageDialog(e.Message);
//Calling the Show method of MessageDialog class
//which will show the MessageBox
await msgbox.ShowAsync();
}
The Output Window Displays:
Exception thrown: 'System.ArgumentException' in mscorlib.ni.dll
Exception thrown: 'System.ArgumentException' in mscorlib.ni.dll
Edit:
The try catch loop is not catching the exceptions related to the file system access problem.
On startup when stepping through I am failing out at StorageFile file = await folder.GetFileAsync("Users.json");
Why I trigger the function through a button I fail at string jsonText = await FileIO.ReadTextAsync(file);
The device I am looking to run my application on is running Windows Embedded 8.1 Handheld update 2 (its a ToughPad Panazonic FZ-E1). Do I need to to targeting windows 8.1 instead of windows phone 8.1? It has been working fine with phone up until this point controlling the POS bar-code scanner.
Any help would be appreciated I am at a loss. Could my issue be caused by settings on the device?
Try using a stream reader on it like below:
var myStream = await (await Package.Current.InstalledLocation.GetFolderAsync("Data")).OpenStreamForReadAsync("Users.json");
Check the properties of the json file. Right click the file-> Properties.
Check the copy to output directory and select copy always option in the menu.
That should help.
Related
I have a question regarding accessing data from another application.
I need access to files that are inside another, already installed, application on iPhone so they can be uploaded via REST POST method.
When we tried testing this with simple picker [FileData fileData = await CrossFilePicker.Current.PickFile();] and navigating to the other application we got something along the lines of 'access denied' message.
We've done this on Android while using Android.App.Application.Context(StartActivity and StartActivityForResault) and Intents (ActionGetContent).
I've read a few articles on Accessing data from another application but I did not fully understand the concept of 'application sandbox'.
Is it even possible? If so, can you give me an example or link to follow so I can see how it's done?
You can have a try with Xamarin.Essentials: Share to share data between apps.
Files:
var fn = "Attachment.txt";
var file = Path.Combine(FileSystem.CacheDirectory, fn);
File.WriteAllText(file, "Hello World");
await Share.RequestAsync(new ShareFileRequest
{
Title = Title,
File = new ShareFile(file)
});
This code snippet tries to read a file outside the location allowed for UWP apps:
StorageFile sf2 = await StorageFile.GetFileFromPathAsync(Path.Combine("C:\\Temp", "spam.dat"));
throws System.UnauthorizedAccessException which is intercepted by a Visual Studio 2015 debugger and shown in a nice popup:
The entire text is below:
An exception of type 'System.UnauthorizedAccessException' occurred in mscorlib.ni.dll but was not handled in user code
WinRT information: Cannot access the specified file or folder (C:\Temp\spam.dat). The item is not in a location that the application has access to (including application data folders, folders that are accessible via capabilities, and persisted items in the StorageApplicationPermissions lists). Verify that the file is not marked with system or hidden file attributes.
An exception of type 'System.UnauthorizedAccessException' occurred in mscorlib.ni.dll but was not handled in user code
Now another code snippet (this code tries to read a file which is already opened for writing):
StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(ApplicationData.Current.LocalFolder.Path);
StorageFile file = await folder.CreateFileAsync("spam.dat", CreationCollisionOption.ReplaceExisting);
Stream fs = await file.OpenStreamForWriteAsync();
StorageFile sf2 = await StorageFile.GetFileFromPathAsync(Path.Combine(ApplicationData.Current.LocalFolder.Path, "spam.dat"));
await sf2.OpenStreamForReadAsync();
The exception screen in the debugger looks completely different:
Additional information: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
I don't understand how debugger looks different for these exceptions. In my code, I need to understand the reason of getting UnauthorizedAccessException - if it was because file is locked for reading as it's occupied by another writer (and I can try again a bit later) or due to another reason, like it's outside of LocalFolder (and it's not worth retrying). I'm actually developing a library which will be used by developers of UWP apps so I don't know which file/filepath I will be given and can make no assumptions for permissions, directory structure, etc. I just get the path on input and, if anything happens, can only use exception handling to understand the reasons.
So, Visual Studio debugger somehow sees the difference but I don't see how I can do this programmatically. InnerException is null in both cases, HResult is the same either (0x80070005).
If you're porting a .NET library to UWP, presumably it has no dependencies on StorageFile at all (either in implementation or public interface) so I would continue to use .NET types, which have distinct errors (Unauthorized Access vs. IO):
try
{
var f = File.OpenRead(#"d:\temp\foo.txt");
}
catch (UnauthorizedAccessException ex)
{
Debug.WriteLine(ex.Message);
}
try
{
var localPath = ApplicationData.Current.LocalFolder.Path;
var filename = Path.Combine(localPath, "foo.txt");
var f1 = File.OpenWrite(filename);
var f2 = File.OpenRead(filename);
}
catch (IOException ex)
{
Debug.WriteLine(ex.Message);
}
If I run your sample code, I don't get any exceptions for the write / read example using StorageFile (although I am running Insider Builds of the Windows 10 Creator's Update). I can get an exception if I try to open the same file twice for writing, but then it's also projected as an IOException:
try
{
var f = await StorageFile.GetFileFromPathAsync(#"d:\temp\foo.txt");
}
catch (UnauthorizedAccessException ex)
{
Debug.WriteLine(ex.Message);
}
try
{
var localFolder = ApplicationData.Current.LocalFolder;
var f1 = await localFolder.CreateFileAsync("foo.txt", CreationCollisionOption.ReplaceExisting);
var f2 = await localFolder.GetFileAsync("foo.txt");
var s1 = await f1.OpenAsync(FileAccessMode.ReadWrite, StorageOpenOptions.AllowOnlyReaders);
var s2 = await f2.OpenAsync(FileAccessMode.ReadWrite, StorageOpenOptions.AllowOnlyReaders);
}
catch (IOException ex)
{
Debug.WriteLine(ex.Message);
}
Alex,
For the second one you are working with the IO stream without disposing the previous stream you are trying to create another stream on the same file. Thus it is preventing you saying unauthorized Access. I have introduced flush the stream and dispose the stream then the code is working for me. Below is the modified code:
StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(ApplicationData.Current.LocalFolder.Path);
StorageFile file = await folder.CreateFileAsync("spam.dat", CreationCollisionOption.ReplaceExisting);
Stream fs = await file.OpenStreamForWriteAsync();
fs.Flush();
fs.Dispose();
StorageFile sf2 = await StorageFile.GetFileFromPathAsync(Path.Combine(ApplicationData.Current.LocalFolder.Path, "spam.dat"));
var x = await sf2.OpenStreamForReadAsync();
I'm new to windows phone development, and not using silverlight or WPF. I copy the file "links.txt" into my Windows Phone folder at "\Documents\" and I want to access and get the content in the file, but I'm getting back as access denied error. I click on Package.appxmanifest file then select "Capabilities" tab, but I don't see "Documents Library Access" for me to check it. As matter fact I don't see any "... Library Access" showing. Below is the code:
string fileName = "\\Documents\\links.txt";
string parentPath = ApplicationData.Current.LocalFolder.Path;
string filePath = Path.Combine(parentPath, fileName);
StorageFile file = await StorageFile.GetFileFromPathAsync(filePath);
Any suggestion how can I read the file? thanks.
Updates:
It seems the code above does not work, but when using the code below and change the folder to "Music" instead of "Documents" then check the Capabilities for "MusicLibrary", it's working.
var folder = KnownFolders.MusicLibrary;
var file = await folder.GetFileAsync("links.txt");
var read = await FileIO.ReadTextAsync(file);
Thanks!
You are give the wrong filePath actual path is in this image
i try your code it shows same error so correct your file path
If you checked need Capability for Documents you should use KnownFolders class instead ApplicationData.Current.LocalFolder.Path.
For example:
StorageFolder storageFolder = KnownFolders.DocumentsLibrary;
StorageFile file = await storageFolder.CreateFileAsync("sample.dat", CreationCollisionOption.ReplaceExisting);
The app Works perfectly fine when I deploy it from VS 2015 (Windows 10)
But the story is very different when I create the build from "Store > Create App Packages...", then install the app from the app from the powershell script.
I have isolated the problem to a section where I set an image for the lock screen. Whenever I click yes on the message dialog to change the lock screen I get a crash, I have attached the debugger and I only get the following exception:
Exception thrown at 0x00007FFA61091F08 (KernelBase.dll) in
ApplicationFrameHost.exe: 0x80010012:
The callee (server [not server application]) is not available
and disappeared; all connections are invalid. The call did not execute.
The code to reproduce the error is based on the following article:
https://msdn.microsoft.com/en-us/windows.system.userprofile.userprofilepersonalizationsettings.trysetlockscreenimageasync
public async Task<bool> ChangeLockScreenBackground()
{
bool success = false;
if (UserProfilePersonalizationSettings.IsSupported())
{
var uri = new Uri("ms-appx:///Assets/SplashScreen.scale-400.png");
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(uri);
UserProfilePersonalizationSettings profileSettings = UserProfilePersonalizationSettings.Current;
success = await profileSettings.TrySetLockScreenImageAsync(file);
}
return success;
}
I have no idea what is going on, I thought it was the capabilities of the app.
But I have enabled User Account Information and Pictures Library and still no luck :(
Looks that you're using a file already opened: SplashScreen* and also from that folder may be you can't set the wallpaper.
Pay Attention: "Your app can't set wallpapers from any folder. Copy file in ApplicationData.Current.LocalFolder and set wallpaper from there"
So I have changed the code a Little bit and also I put attention to documentation:
Remarks
Caution For the mobile device family, you can only set a lock screen image that is smaller than 2 megabytes (MB). Attempting to set
a lock screen image that is larger fails, even though the async
operation returns true.
Caution When you set an image more than once, the new image file must have a different name than the previously set image. If you set a
new image using a file with the same name as the previous image, it
will fail.
In this code I'm adding a file to Visual Studio Project in a folder called img, and setting the image properties to "Copy if newer". Then I load the image from such location.
async Task<bool> SetWallpaperAsync(string localAppDataFileName)
{
bool success = false;
var uri = new Uri($"ms-appx:///img/{localAppDataFileName}");
//generate new file name to avoid colitions
var newFileName = $"{Guid.NewGuid().ToString()}{Path.GetExtension(localAppDataFileName)}";
if (UserProfilePersonalizationSettings.IsSupported())
{
var profileSettings = UserProfilePersonalizationSettings.Current;
var wfile = await StorageFile.GetFileFromApplicationUriAsync(uri);
//Copy the file to Current.LocalFolder because TrySetLockScreenImageAsync
//Will fail if the image isn't located there
using (Stream readStream = await wfile.OpenStreamForReadAsync(),
writestream = await ApplicationData.Current.LocalFolder.OpenStreamForWriteAsync(newFileName,
CreationCollisionOption.GenerateUniqueName)
)
{ await readStream.CopyToAsync(writestream); }
StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync(newFileName);
success = await profileSettings.TrySetLockScreenImageAsync(file);
}
Debug.WriteLine(success);
return success;
}
This code works perfectly in Windows Mobile 10, and because this is an Universal App you should expect it runs same way in Windows 10 Apps... and yes.
Letme know if this was enough for you.
What is the right place for my Windows 10 IoT UWP app to persist temporary working data considering the device is occasionally turned off ? I have been researching about saving files on the SD card and reading from it, but it's been tough. Not even the code below is running, for the line IReadOnlyList<StorageFile> files = await folder.GetFilesAsync(); is causing the task to abort without raising any error. It's VS 2015 on Raspberry Pi 2.
public async void pop()
{
StorageFolder folder = Windows.Storage.ApplicationData.Current.LocalFolder;
IReadOnlyList<StorageFile> files = await folder.GetFilesAsync();
foreach (StorageFile sf in files)
{
if (sf.Name.EndsWith(".mtk"))
{
var file = await folder.GetFileAsync(sf.Name);
var readFile = await Windows.Storage.FileIO.ReadTextAsync(file);
nextFileContents = readFile.ToString();
break;
}
}
}
If you read Microsoft Documentation about access uSD on Windows 10 (here link)
you have to do two tasks:
specify the removableStorage capability in the app manifest file and
register to handle the file extensions associated with the type of media that you want to access
read the documentation and enjoy