Save string to xml file (UWP) c# - c#

I am trying to save an string to an xml file and am recieving the following error:
An exception of type 'System.UnauthorizedAccessException' occurred in System.IO.FileSystem.dll but was not handled in user code
Additional information: Access to the path 'c:\users\brandon\documents\visual studio 2015\Projects\UniversalTestApp\UniversalTestApp\bin\x86\Debug\AppX\xmlfile.xml' is denied.
Reading further into the issue it would seem that I don't have the approriate permissions to complete this save. How would I go about
private async void btnSubmit_Click(object sender, RoutedEventArgs e)
{
var bookmark = new Bookmark();
bookmark.Button = cmbButton.SelectedIndex;
bookmark.Name = txtName.Text;
bookmark.URL = txtURL.Text;
string output = SerializeToXml(bookmark);
XmlDocument xdox = new XmlDocument();
File.WriteAllText("xmlfile.xml",output);
}

As it turns out the reason for the error message is that you can only access certain file system locations by default in UWP. I made some modifications to my code and it is now working correctly. Thanks to those who tried to help.
private async void btnSubmit_Click(object sender, RoutedEventArgs e)
{
var bookmark = new Bookmark();
StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
StorageFile createFile = await storageFolder.CreateFileAsync("bookmark.xml", CreationCollisionOption.ReplaceExisting);
bookmark.Button = cmbButton.SelectedIndex;
bookmark.Name = txtName.Text;
bookmark.URL = txtURL.Text;
var output = SerializeToXml(bookmark);
StorageFile sampleFile = await storageFolder.GetFileAsync("bookmark.xml");
await FileIO.WriteTextAsync(sampleFile, output);
}

Try to run your application "as administrator"

Related

How to read files from Android external storage in MAUI application

How can I read/write all/specific files from an android external storage folder in a MAUI application. I know there are native ways to do that in Xamarin.Android but here I am looking for more modern abstract way to achieve it. Kindly help.
To be specific I am looking for some abstraction/API to list files on Android platform. something like below would be ideal or similar-
var files = Directory.GetFiles(<FolderPath>)
Any pointer would really help. Thanks a lot.
Take .txt file as an example.
MainPage.xaml:
...
<VerticalStackLayout>
<Button Text="File"
Clicked="file_clicked"/>
<Button Text="Read_file"
Clicked="Read_file"/>
</VerticalStackLayout>
In MainPage.xaml.cs, you can add this:
//string targetFile = System.IO.Path.Combine(FileSystem.Current.AppDataDirectory, "TextFile3.txt");
// Write the file content to the app data directory
private async void file_clicked(object sender, EventArgs e)
{
#if ANDROID
//var docsDirectory = Android.App.Application.Context.GetExternalFilesDir(Android.OS.Environment.DirectoryDocuments);
//File.WriteAllText($"{docsDirectory.AbsoluteFile.Path}/atextfile.txt", "contents are here");
var docsDirectory = Android.App.Application.Context.GetExternalFilesDir(Android.OS.Environment.DirectoryDcim);
File.WriteAllText($"{docsDirectory.AbsoluteFile.Path}/atextfile.txt", "contents are here");
#endif
//using FileStream outputStream = System.IO.File.OpenWrite(targetFile);
//using StreamWriter streamWriter = new StreamWriter(outputStream);
//await streamWriter.WriteAsync("ssss");
}
//read file
private async void Read_file(object sender, EventArgs e)
{
#if ANDROID
var docsDirectory = Android.App.Application.Context.GetExternalFilesDir(Android.OS.Environment.DirectoryDcim);
var a = File.OpenRead($"{docsDirectory.AbsoluteFile.Path}/atextfile.txt");
using StreamReader reader_1 = new StreamReader(a);
var doc = await reader_1.ReadToEndAsync();
await DisplayAlert("content", doc, "OK");
#endif
//using FileStream outputStream_2 = System.IO.File.OpenRead(targetFile);
//using StreamReader reader_2 = new StreamReader(outputStream_2);
//string content_2 = await reader_2.ReadToEndAsync();
//content_2 = content_2.ToUpperInvariant();
}

Why SetSource cannot change the value of Source?

I set the original Source of MediaElement to be abc.mp3, and I'm trying to play another local mp3, like D://xxx.mp3.
When I use SetSource, I found that the value of Source was still abc.mp3, but the music actually changed to be xxx.mp3.
Can I use player.Source = "D://xxx.mp3"; ?
Here is my code:
//player is a MediaElement.
private async void Button_Click(object sender, RoutedEventArgs e)
{
await SetLocalMedia();
}
async private System.Threading.Tasks.Task SetLocalMedia()
{
var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
openPicker.FileTypeFilter.Add(".wmv");
openPicker.FileTypeFilter.Add(".mp4");
openPicker.FileTypeFilter.Add(".wma");
openPicker.FileTypeFilter.Add(".mp3");
var file = await openPicker.PickSingleFileAsync();
if (file != null)
{
var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
Debug.WriteLine(player.Source);
player.SetSource(stream, file.ContentType);
Debug.WriteLine(player.Source);//The output of these tow Debug are same
}
}
Why SetSource cannot change the value of Source?
Thank you for your time to report this, the problem is that if you call the SetSource method to set media source with local file open stream, so the Source property will not contain value, and it is by design.
Can I use player.Source = "D://xxx.mp3"; ?
Source property is Uri type, it support http and UWP local uri scheme, if the file stored in D disk, you could not set the player.Source = "D://xxx.mp3(file scheme). If you do want to set the source with uri value, I suggest copy the file to the app's local folder then use UWP local file uri scheme. But it will cause the app's local storage becomes larger.
private async void Button_Tapped(object sender, TappedRoutedEventArgs e)
{
var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
openPicker.FileTypeFilter.Add(".wmv");
openPicker.FileTypeFilter.Add(".mp4");
openPicker.FileTypeFilter.Add(".wma");
openPicker.FileTypeFilter.Add(".mp3");
var file = await openPicker.PickSingleFileAsync();
if (file != null)
{
await file.CopyAsync(ApplicationData.Current.LocalFolder, file.Name, NameCollisionOption.ReplaceExisting);
var path = ApplicationData.Current.LocalFolder.Path;
var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
Debug.WriteLine(player.Source);
player.Source = new Uri($"ms-appdata:///local/{file.Name}");
Debug.WriteLine(player.Source);//The output of these tow Debug are same
}
player.Play();
}

C# problem with big JSON in InnerText of Webbrowser Control

I Can't get a big JSON loaded in the Webbrowser Control. Using IE11 and this reg to load the JSON instead of downloading it.
[HKEY_CLASSES_ROOT\MIME\Database\Content Type\application/json]
"CLSID"="{25336920-03F9-11cf-8FD0-00AA00686F13}"
"Encoding"=hex:08,00,00,00
If I download the file it has 7.329.068 chars.
If I load it in webbrowser control (or WebClient) and access webBrowser2.Document.Body.InnerText it has only 2.634.268 chars.
The interesting part is, the file isn't chopped. There are child elements missing in the file.Checked tis in Notepad++.
Biggest problem is, even without the registry workaround and a webclient dowload the file isn't complete.
I have to use webbrowser control because of difficult session handling in this case. JSON is a 1 line file with above 5 millions chars. JSON file is deserialized with JavaScriptSerializer and works perfekt for the given JSON
private void GetJsonView(string url_)//object sender, EventArgs e)
{
webBrowser2.Navigate(new Uri(url_));
webBrowser2.Navigate(url_);
}
private void webBrowser2_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
innerText = webBrowser2.Document.Body.InnerText;
JavaScriptSerializer test = new JavaScriptSerializer();
test.MaxJsonLength = Int32.MaxValue;
sicht = test.Deserialize<View>(innerText);
}
Workaround instead of registry entry, gives same missing nodes result
private void webBrowser2_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
if (e.Url.Segments[e.Url.Segments.Length - 1].EndsWith("/"))
{
e.Cancel = true;
string filepath = null;
saveFileDialog1.FileName = e.Url.Segments[e.Url.Segments.Length - 1];
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
filepath = saveFileDialog1.FileName;
WebClient client = new WebClient();
client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
client.DownloadFileAsync(e.Url, filepath);
}
}
}
For now I have no clue, why IE is 'hiding' some nodes. It doesn't matter if the file is saved or directly parsed as string to my method. Main goal is to receive the whole payload and I have no clue how to achive this.

Windows UWP C# delete folder

When I try to delete a folder I get the following error:
Exception thrown: 'System.UnauthorizedAccessException' in mscorlib.ni.dll
Additional information: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
The whole block of code is here:
StorageFolder folder;
try
{
folder = await ApplicationData.Current.LocalFolder.GetFolderAsync("images");
await folder.DeleteAsync();
StorageFolder new_images = await ApplicationData.Current.LocalFolder.CreateFolderAsync("images", CreationCollisionOption.ReplaceExisting);
}
catch (FileNotFoundException ex)
{
StorageFolder new_images = await ApplicationData.Current.LocalFolder.CreateFolderAsync("images", CreationCollisionOption.ReplaceExisting);
}
The error occurs on this line:
await folder.DeleteAsync();
I'm guessing the issue comes when I add a bunch of images from the images folder like so:
tmp.Source = new BitmapImage(new Uri("ms-appdata:///local/images/image_" + ring.Name + ".jpg", UriKind.Absolute));
It could also be when I save the image:
try {
StorageFile file = await image_folder.CreateFileAsync("image_" + id + ".jpg", CreationCollisionOption.ReplaceExisting);
await FileIO.WriteBytesAsync(file, responseBytes);
} catch (System.Exception)
{
}
If the issue comes because it is reading it and I try to delete the folder, how can I make it work, I honestly don't know what to do here.
Exception thrown: 'System.UnauthorizedAccessException' in mscorlib.ni.dll
I noticed that you were trying to save the image using FileIO.WriteBytesAsync() method, I couldn't see how you load the image file to Byte array. The most possible reason is "forgot to dispose of the stream after opening it to load image data"
This is the way I load an image and save to LocalFolder:
private async Task<byte[]> ConvertImagetoByte(StorageFile image)
{
IRandomAccessStream fileStream = await image.OpenAsync(FileAccessMode.Read);
var reader = new Windows.Storage.Streams.DataReader(fileStream.GetInputStreamAt(0));
await reader.LoadAsync((uint)fileStream.Size);
byte[] pixels = new byte[fileStream.Size];
reader.ReadBytes(pixels);
return pixels;
}
private async void btnSave_Click(object sender, RoutedEventArgs e)
{
try
{
var uri = new Uri("ms-appx:///images/image.jpg");
var img = await StorageFile.GetFileFromApplicationUriAsync(uri);
byte[] responseBytes = await ConvertImagetoByte(img);
var image_folder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("images", CreationCollisionOption.OpenIfExists);
StorageFile file = await image_folder.CreateFileAsync("image_test.jpg", CreationCollisionOption.ReplaceExisting);
await FileIO.WriteBytesAsync(file, responseBytes);
tmp.Source = new BitmapImage(new Uri("ms-appdata:///local/images/image_test.jpg", UriKind.Absolute));
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
It may sound strange but at times authorization type of issues occur when we don't start our IDE as an administrator. Which is done by right clicking on the IDE (Visual Studio) icon and then select 'Run as Administrator'
Try this if it resolves your issue.
You need to use lock to be sure that file or folder will not be modified while it using in another thread. Since you are using await I would suggest to take a look at this - https://github.com/bmbsqd/AsyncLock/
You can get more info about thread sync here - https://msdn.microsoft.com/ru-ru/library/ms173179(v=vs.80).aspx

System.Runtime.InteropServices.COMException occurred in mscorlib.ni.dll but was not handled in user code

I am developing a windows application in 8.1 and I am getting a following error.
my application includes a procedure in which I will be moving a file from local storage to SD card.
My code is as follows
namespace MoveFile
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
private async void btnCreateFolder_Click(object sender, RoutedEventArgs e)
{
await ReadFile();
//Error is showing here
**await WriteToFile();
}
public async Task WriteToFile()
{
// Get the text data from the textbox.
byte[] fileBytes = System.Text.Encoding.UTF8.GetBytes(this.txtSafakCount.Text.ToCharArray());
//I got the error in this line.....showing interopservice exception
** StorageFolder knownFolder = await KnownFolders.RemovableDevices.CreateFolderAsync("bdfbdfb", CreationCollisionOption.ReplaceExisting);
StorageFolder sdCard = (await knownFolder.GetFoldersAsync()).FirstOrDefault();
// Create a new file named DataFile.txt.
var file = await sdCard.CreateFileAsync("kaaaaammmmfewfwmHoJa.txt", CreationCollisionOption.ReplaceExisting);
// Write the data from the textbox.
using (var s = await file.OpenStreamForWriteAsync())
{
s.Write(fileBytes, 0, fileBytes.Length);
}
}
public async Task ReadFile()
{
// Get the local folder.
StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
if (local != null)
{
// Get the DataFolder folder.
var dataFolder = await local.GetFolderAsync("DataFolder");
// Get the file.
await dataFolder.CreateFileAsync("DataFile.txt", CreationCollisionOption.ReplaceExisting);
var file = await dataFolder.OpenStreamForReadAsync("DataFile.txt");
// Read the data.
using (StreamReader streamReader = new StreamReader(file))
{
this.txtSafakCount.Text = streamReader.ReadToEnd();
}
}
}
}
}
I want to know why this exception occurred and how it can be resolved.
Thanks in advance.
You are doing it wrong - first you should get SD card, then create folder. As the name KnownFolders.RemovableDevices says devices (not single device) - so you get the first of them as SD card (note that Universal Apps are not only for phones). So the working code can look like this:
// first get the SD card
StorageFolder sdCard = (await KnownFolders.RemovableDevices.GetFoldersAsync()).FirstOrDefault();
// then perform some actions - create folders, files ...
StorageFolder myFolder = await sdCard.CreateFolderAsync("bdfbdfb", CreationCollisionOption.ReplaceExisting);
Note also that you also need to add Capabilities in package.appxmanifest file, and Declarations if you want to use files (File Type Associations).
You will also find more help at MSDN.

Categories