Why can't I read XML from AppData in WinRT? - c#

What I want
get a xml file from the AppData.Local, and serialize it to a list
What I code
The Error Part:
List<myTask> AllTaskList = await objectStorageHelper.LoadAsync();
myTask is a simple class:
public class myTask
{
public string myTitle { get; set; }
public string myDuetime { get; set; }
}
objectStorageHelper is a HelpClass from CodePlex, the LoadAsync part is below:
public async Task<T> LoadAsync()
{
try
{
StorageFile file = null;
StorageFolder folder = GetFolder(storageType);
file = await folder.GetFileAsync(FileName());
//file = await folder.CreateFileAsync("BetterTask.xml", CreationCollisionOption.OpenIfExists);
IRandomAccessStream readStream = await file.OpenAsync(FileAccessMode.Read);
Stream inStream = Task.Run(() => readStream.AsStreamForRead()).Result;
return (T)serializer.Deserialize(inStream);
}
catch (FileNotFoundException)
{
//file not existing is perfectly valid so simply return the default
return default(T);
//Interesting thread here: How to detect if a file exists (http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/1eb71a80-c59c-4146-aeb6-fefd69f4b4bb)
//throw;
}
catch (Exception)
{
//Unable to load contents of file
throw;
}
}
What is the Error
An exception of type 'System.UnauthorizedAccessException' occurred in mscorlib.dll but was not handled in user code
Additional information: Access Denied。 (Exception from HRESULT:0x80070005 (E_ACCESSDENIED))
If there is a handler for this exception, the program may be safely continued.
--
Why does this happen?
I can use this help class to successfully write to a file.
But Why don't I have the permission to read the file?
How to solve it?

change
StorageFolder folder = GetFolder(storageType);
to
StorageFolder folder = ApplicationData.Current.LocalFolder
if this works then the issue is with your folder permissions.

change
Stream inStream = Task.Run(() => readStream.AsStreamForRead()).Result;
return (T)serializer.Deserialize(inStream);
to
using (Stream inStream = Task.Run(() => readStream.AsStreamForRead()).Result)
{
return (T)this.xmlSerializer.Deserialize(inStream);
}
or
inStream.Flush();
inStream.Dispose();
and the same to the SaveAsync()

Related

What are your suggestions for a different logging method in UWP?

During the UWP conversion of an application that was previously designed as a winform, errors occurred in my logging method and I had to change the System.IO reference to Storage. As a result of this change, when the synchronous method started to work asynchronously, I got errors about the request to use the file at the same time. Then I came up with a simple solution by creating the class I mentioned below but this quick amateurish approach do you think is correct?
public class Logging_UWP
{
private List<string> CompletedLog = new List<string>();
private string machineCode = string.Empty;
public Logging_UWP(string MachineCode)
{
machineCode = MachineCode;
Task.Factory.StartNew(()=> WriteLog());
}
public void WriteLogSync(string NewLog)
{
CompletedLog.Add(NewLog);
}
private async void WriteLog()
{
while (true)
{
try
{
foreach (string NewLog in CompletedLog)
{
StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
StorageFile sampleFile = await storageFolder.CreateFileAsync(machineCode + ".log", CreationCollisionOption.OpenIfExists);
var stream = await sampleFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
using (var outputStream = stream.GetOutputStreamAt(stream.Size + 1))
{
using (var dataWriter = new Windows.Storage.Streams.DataWriter(outputStream))
{
dataWriter.WriteString(String.Format("\n[{0}-{1}] >>> {2}", DateTime.Now.ToShortDateString(), DateTime.Now.ToLongTimeString(), NewLog));
await dataWriter.StoreAsync();
await outputStream.FlushAsync();
}
}
}
if (CompletedLog.Count > 0)
CompletedLog.Clear();
await Task.Delay(500);
}
catch (Exception)
{ }
}
}
} '''

Download txt file from google drive in windows phone 8.1

I'm doing a windows phone project, and need to download a text file from the internet and read its content.
This is what I have tried (but it didn't work)
private async Task pobierz()
{
string source = "https://drive.google.com/file/d/0BzgKBwKyU4oORkxxSlVITGswb1E/view?usp=sharing";
string LocalName = "hej.txt";
var srce = new Uri(source, UriKind.Absolute);
// var destinationFile =await KnownFolders.PicturesLibrary.CreateFileAsync()
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(#"ms-appx:///Assets/hej.txt"));
var downloader = new BackgroundDownloader();
DownloadOperation download = downloader.CreateDownload(srce,file);
}
Please see https://msdn.microsoft.com/en-us/library/windows/apps/xaml/jj152726.aspx?f=255&MSPPError=-2147217396 for detailed description of how to use the BackgroundDownloader.
You need to implement and call the following method:
private async void HandleDownloadAsync(DownloadOperation download, bool start)
{
try
{
// Store the download so we can pause/resume.
activeDownloads.Add(download);
Progress<DownloadOperation> progressCallback = new Progress<DownloadOperation>(DownloadProgress);
if (start)
{
// Start the download and attach a progress handler.
await download.StartAsync().AsTask(cts.Token, progressCallback);
}
else
{
// The download was already running when the application started, re-attach the progress handler.
await download.AttachAsync().AsTask(cts.Token, progressCallback);
}
ResponseInformation response = download.GetResponseInformation();
Log(String.Format("Completed: {0}, Status Code: {1}", download.Guid, response.StatusCode));
}
catch (TaskCanceledException)
{
Log("Download cancelled.");
}
catch (Exception ex)
{
LogException("Error", ex);
}
finally
{
activeDownloads.Remove(download);
}
}

How to handle prepopulated database in Windows Phone 8.1

I need to use a prepopulated database in my Xamarin.Forms application, so I searched for possible solutions.
I've found this article and tested with Android - it worked okay.
However, it uses Windows Phone 8 - that is not compatible with Windows 8.1.
So I tried to modify this Windows Phone 8 code:
public static void CopyDatabaseIfNotExists(string dbPath)
{
var storageFile = IsolatedStorageFile.GetUserStoreForApplication();
if (!storageFile.FileExists(dbPath))
{
using (var resourceStream = Application.GetResourceStream(new Uri("people.db3", UriKind.Relative)).Stream)
{
using (var fileStream = storageFile.CreateFile(dbPath))
{
byte[] readBuffer = new byte[4096];
int bytes = -1;
while ((bytes = resourceStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
{
fileStream.Write(readBuffer, 0, bytes);
}
}
}
}
}
Into this code:
public static async void CopyDatabaseIfNotExists(string dbPath)
{
IStorageFolder applicationFolder = ApplicationData.Current.LocalFolder;
StorageFile existingFile = await Windows.Storage.StorageFile.GetFileFromPathAsync("prep.db");
IStorageFile storageFile = await applicationFolder.GetFileAsync(dbPath);
if (storageFile == null)
{
await existingFile.CopyAndReplaceAsync(storageFile);
However, it does not work, I can't provide a proper filepath for my existing db file (it is in the root of the project), it always gives me this error:
Value does not fall within the expected range.
How could I get a proper path to my prepopulated file?
Also, why do I need to use a stream based "copy" when I could simply copy the file itself?
The following code works for Windows Phone 8.1 and UWP:
public async void CopyDatabaseIfNotExists(string dbPath)
{
IStorageFolder applicationFolder = ApplicationData.Current.LocalFolder;
var existingFile = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(myDBFileName);
if (!await CheckForExistingFile(myDBFileName))
await existingFile.CopyAsync(applicationFolder);
}
private async Task<bool> CheckForExistingFile(string filePath)
{
try
{
var file = await ApplicationData.Current.LocalFolder.GetFileAsync(Uri.EscapeDataString(filePath));
//no exception means file exists
return true;
}
catch (FileNotFoundException ex)
{
//find out through exception
return false;
}
}

Directory exists check in metro app(not file)

Directory.Exists(imgFolder.Path);
alternate method in win8.1 store app,
im tried search online but i do get result for file exists only not to check folder exists
In Windows 8.1 you need to do something like following.
The following method will check if files exists or not:
public async Task<bool> isFilePresent(string fileName)
{
bool fileExists = true;
Stream fileStream = null;
StorageFile file = null;
try
{
file = await ApplicationData.Current.LocalFolder.GetFileAsync(fileName);
fileStream = await file.OpenStreamForReadAsync();
fileStream.Dispose();
}
catch (FileNotFoundException)
{
// If the file dosn't exits it throws an exception, make fileExists false in this case
fileExists = false;
}
finally
{
if (fileStream != null)
{
fileStream.Dispose();
}
}
return fileExists;
}
or:
public async Task<bool> isFilePresent(string fileName)
{
var item = await ApplicationData.Current.LocalFolder.TryGetItemAsync(fileName);
return item != null;
}
From Check If File Exists in Windows Phone 8 and Win RT

OneDrive file only uploads when app is terminated

I'm having a problem uploading a file to OneDrive from a universal app that I can't understand or figure out how to debug. I used this guide to go through the process of getting file IDs and such and it worked great until a few hours ago.
Now I can get folder and file ids, so I assume that I am still successfully connecting to OneDrive and my internet connection is still working. But when I step into the BackgroundUploadAsync the thread or whatever that was was executing before never returns. In the code below, the message "Uploading new file to OneDrive..." never disappears.
Strangely, while it is uploading I can refresh my OneDrive folder on ie and I'll never see what I'm trying to upload. But once I stop the debugger, or terminate the app on the phone, I can instantly refresh and the file will be there.
Here is the method for uploading:
public async Task UploadToOneDrive(string folderID, string localFileName)
{
try
{
StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync(localFileName);
string fileName = "backup-" + DateTime.Now.ToString("dd-MM") + ".db";
await file.CopyAsync(ApplicationData.Current.LocalFolder, fileName, NameCollisionOption.ReplaceExisting);
file = await ApplicationData.Current.LocalFolder.GetFileAsync(fileName);
await connectClient.BackgroundUploadAsync(folderID,
fileName, file, OverwriteOption.Overwrite);
}
catch (LiveConnectException)
{
MessageDialog m = new MessageDialog("Could not connect to to OneDrive. Cloud sync will be stopped.");
m.ShowAsync();
}
catch (LiveAuthException)
{
MessageDialog m = new MessageDialog("Error authenticating OneDrive service. Please try cloud sync again later.");
m.ShowAsync();
}
catch (Exception ex)
{
MessageDialog m = new MessageDialog("Unknown exception occurred.\n\nError:{0}", ex.Message);
m.ShowAsync();
}
}
And here is the sync process
public async Task sync()
{
var sb = StatusBar.GetForCurrentView();
sb.ProgressIndicator.Text = "Syncing with OneDrive...";
await sb.ProgressIndicator.ShowAsync();
string cloudFolderID = await syncManager.CreateOrGetOneDriveFolderID("GlucoseCalculator", "Documents/");
string cloudFileID = await syncManager.GetFileID(DataManager.sqlFileName, "Documents/GlucoseCalculator/");
try
{
if (cloudFileID != null)
{
if (!(await dbManager.DoesFileExist(DataManager.sqlFileName)))
{
sb.ProgressIndicator.Text = "Downloading file from OneDrive...";
await syncManager.DownloadFromOneDrive(cloudFileID, DataManager.sqlFileName);
goto BREAK;
}
DateTime cloudLastEditDateTime = DateTime.Parse(await syncManager.GetFileProperty(cloudFileID, "updated_time"));
DateTime localLastEditDateTime = ApplicationData.Current.LocalFolder.GetFileAsync(DataManager.sqlFileName).GetResults().GetBasicPropertiesAsync().GetResults().DateModified.DateTime;
if (cloudLastEditDateTime > localLastEditDateTime)
{
sb.ProgressIndicator.Text = "Downloading file from OneDrive...";
await syncManager.DownloadFromOneDrive(cloudFileID, DataManager.sqlFileName);
}
else if (cloudLastEditDateTime < localLastEditDateTime)
{
sb.ProgressIndicator.Text = "Uploading file to OneDrive...";
await syncManager.UploadToOneDrive(cloudFolderID, DataManager.sqlFileName);
}
}
else if (cloudFileID == null)
{
sb.ProgressIndicator.Text = "Uploading new file to OneDrive...";
await syncManager.UploadToOneDrive(cloudFolderID, DataManager.sqlFileName);
}
}
catch (Exception)
{
sb.ProgressIndicator.Text = "Cloud synchronization failed.";
sb.ProgressIndicator.HideAsync();
return;
}
sb.ProgressIndicator.Text = "Synchronization complete!";
BREAK:;
await sb.ProgressIndicator.HideAsync();
}
Most likely, you are creating some object that implements IDisposible, but it is not in a using block. Maybe the StorageFile.

Categories