The Deadly Access Denied Error!

I could hear the unmistakable whooooooshhh sound of app submission deadline approaching. The app was going through rigorous  and meticulous testing. And finally, we reached a point where no more bugs could be pulled out (*relief) 😀 Although rare occurrence of some garbage value was noted, since it looked liked one of the type, I was a little complacent…

And in the 11th hour, as expected, when everything is bound to go wrong, that ugly pile of garbage values started started popping up, like daisies!

So lemme describe the scenario here.

The apps writes a series of values into files at different points of its execution. The values, be it of type integer, Datetime, bool, would be converted to strings and written to different files. This is how I wrote the values into files

public async Task<bool> WriteHistoryToFile()
{
try
 {
 StorageFile sampleFile = await localfolder.CreateFileAsync("HistoryFile", CreationCollisionOption.ReplaceExisting);
 var stream = await sampleFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
using (var outputStream = stream.GetOutputStreamAt(0))
{
DataWriter dataWriter = new DataWriter(outputStream);
for (int i = 0; i < m_iHistCount; i++)
dataWriter.WriteString(m_dtHistory[i].ToString("d", CultureInfo.InvariantCulture) + "`~");
  await dataWriter.StoreAsync();
  await dataWriter.FlushAsync();
dataWriter.Dispose();
await outputStream.FlushAsync();
fileWrite = true;
}
}
catch (Exception e)
{
 string str = e.Message;
 fileWrite = false;
}
}

On closer examination of the code, I found that, the first call of the function WriteHistoryToFile happens perfectly alright, but if a subsequent call is made to the same function, it would directly go to the catch block! The error message was the a one liner. “ACCESS DENIED”. How very convenient and frustrating!. Clearly I was missing something.

As per msdn docs, you need to open file, create a stream for writing, use a data writer to write into the stream , call StoreAsync and flush the stream. Somehow this seems to be not working.

Frantic searching in the web gave me several instances of the same error thrown, and some had narrated the same scenario. The explanation everyone said was, the stream needs to be freed of the resources, but hey! im flushing the stream. I looked for a close function for the stream which is nonexistent. But I found a Dispose() for the output stream who happened to be my saviour for the day!

So everybody, who has over looked that teensy Dispose(), do not forget this function if you don’t want to be slapped with a Access Denied Exception!

try
 {
 StorageFile sampleFile = await localfolder.CreateFileAsync("HistoryFile", CreationCollisionOption.ReplaceExisting);
var stream = await sampleFile.OpenStreamForWriteAsync();
using (var outputStream = stream)
 {
 DataWriter dataWriter = new DataWriter(outputStream.AsOutputStream());
 for (int i = 0; i < m_iHistCount; i++)
   dataWriter.WriteString(m_dtHistory[i].ToString("d", CultureInfo.InvariantCulture) + "`~");
 await dataWriter.StoreAsync();
 await outputStream.FlushAsync();
 outputStream.Dispose(); // HE is the guy you need! 😀
 fileWrite = true;
 }
}
 catch (Exception e)
 {
 string str = e.Message;
 fileWrite = false;
 }

Note: If you have wrapped the code. with out dispose function, in try catch block, the app would not crash. Execution will move to the catch block and graciously move on. The exception would go unnoticed if you have not set break points. 🙂

May the code be with you!! 🙂

logosmall

References :-
MSDN – Files – This does not mention of the Dispose function! 

Storage Files and JSON

Something I was totally unfamiliar was, how to deal with was the StorageFiles and JSON data in WinRT. This is a basic example of how to read and write JSON data into a StorageFile.

Before we get to the code. What is JSON?

MSDN defines JSON as

an open, text-based data exchange format (see RFC 4627). Like XML, it is human-readable, platform independent, and enjoys a wide availability of implementations. Data formatted according to the JSON standard is lightweight and can be parsed by JavaScript implementations with incredible ease, making it an ideal data exchange format for Ajax web applications. Since it is primarily a data format, JSON is not limited to just Ajax web applications, and can be used in virtually any scenario where applications need to exchange or store structured information as text.

So JSON is relatively simpler than XML. It provides easier format to save and retrieve data and has native support for Arrays and Objects. Data stored will be in the following key value format.

[{“FirstName”:”hello”,”SecondName”:”sir”}]

Lets get our hands dirty with code. 😀

I created a simple page with two textboxes and a button, We enter the first name and the second name and when we click the button called save, it should save the data as JSON data into a File.

Now we make one more copy of the above elements, ie 2 more textboxes and a button. This button is for retrieving the saved data. On press of this retrieve button, it should open the same file, read the data and put them into the newly created textboxes.

<Grid Margin="107,75,816,335" Grid.Row="1">

<TextBox x:Name="firstTextbox" HorizontalAlignment="Left" Height="40" Margin="155,0,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="140" FontSize="20" />

<TextBox x:Name="secondTextbox" HorizontalAlignment="Left" Height="45" Margin="155,65,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="140" FontSize="20" />
<TextBlock x:Uid="firstTextblock" HorizontalAlignment="Left" TextWrapping="Wrap" Text="First" VerticalAlignment="Top" Width="110" Height="40" FontSize="28"/>
<TextBlock x:Uid="secondTextblock" HorizontalAlignment="Left" TextWrapping="Wrap" Text="Second" VerticalAlignment="Top" Margin="0,75,0,0" Width="110" Height="35" FontSize="28"/>
<Button Content="Save JSON" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="80,145,0,0" Tapped="OnSaveButtonClicked"/>
</Grid>

<Grid Margin="640,75,316,335" Grid.Row="1" RenderTransformOrigin="0.5,0.5">
<TextBox x:Name="firstTextbox1" HorizontalAlignment="Left" Height="40" Margin="155,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="140" />
<TextBox x:Name="secondTextbox1" HorizontalAlignment="Left" Height="33" Margin="155,75,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="140" />
<TextBlock x:Uid="firstTextblock" HorizontalAlignment="Left" TextWrapping="Wrap" Text="First" VerticalAlignment="Top" Width="110" Height="40" FontSize="28"/>
<TextBlock x:Uid="secondTextblock" HorizontalAlignment="Left" TextWrapping="Wrap" Text="Second" VerticalAlignment="Top" Margin="0,75,0,0" Width="120" Height="35" FontSize="28"/>
<Button x:Name="RetrieveButton" Content="Retrieve" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="155,155,0,0" Tapped="OnRetrieveClicked"/>
</Grid>

Add the following namespace so as to enable the JSON data and declare a StorageFolder inside the MainPage class

using Windows.Data.Json;

Windows.Storage.StorageFolder localfolder;

So on the click of save button you call the SaveJSONData function.


private async void OnSaveButtonClicked(object sender, TappedRoutedEventArgs e)
 {
await SaveJSONData();
}

And the SaveJSONData has the code to convert the text to JSON. Here I have declared just one JsonObject. If you have an array of objects you can declare a JsonArray to which each object can be placed.

public async Task<bool> SaveJSONData()
 {
 JsonArray dataArray = new JsonArray();

JsonObject dataObject = new JsonObject();
 dataObject.Add("FirstName", JsonValue.CreateStringValue(firstTextbox.Text));
 dataObject.Add("SecondName", JsonValue.CreateStringValue(secondTextbox.Text));

dataArray.Add(dataObject);

string jsonString = dataArray.Stringify();
 await WriteToFile(jsonString);
 return true;
 }

JsonArray.Stringify returns the JSON representation of the encapsulated value. So after obtaining the encapsulated value we write it to a file.

public async Task<bool> WriteToFile(string jsonString)
 {
 try
 {
 StorageFile DataFile = await localfolder.CreateFileAsync("SampleFile", CreationCollisionOption.ReplaceExisting);

using (var stream = await DataFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite))
 {
 var outputStream = stream.GetOutputStreamAt(0);

using (DataWriter dataWriter = new DataWriter(outputStream))
 {
 dataWriter.WriteString(jsonString);

await dataWriter.StoreAsync();
 dataWriter.Dispose();
 await outputStream.FlushAsync();
 }

await stream.FlushAsync();
 }
 }
 catch (Exception)
 {
 }

return true;
 }

Similarly for reading the saved data,

private async void OnRetrieveClicked(object sender, TappedRoutedEventArgs e)
 {
 await RetrieveJSONData(); ;
 }

public async Task<bool> RetrieveJSONData()
 {
 string jsonString = await ReadFromFile();
 if (jsonString != null)
 {
 JsonArray jsonArray = JsonArray.Parse(jsonString);
 firstTextbox1.Text = jsonArray.GetObjectAt(0).GetNamedString("FirstName");
 secondTextbox1.Text = jsonArray.GetObjectAt(0).GetNamedString("SecondName");
 return true;
 }
 return false;
 }

 public async Task<string> ReadFromFile()
 {
 StorageFile DataFile = null;
 String buffer = null;

try
 {
 DataFile = await localfolder.GetFileAsync("SampleFile");
 }
 catch (FileNotFoundException)
 {
 }
if (DataFile != null)
 {
 try
 {
 using (var fs = await DataFile.OpenAsync(FileAccessMode.Read))
 {
 using (var inStream = fs.GetInputStreamAt(0))
 {

using (var reader = new DataReader(inStream))
 {
 await reader.LoadAsync((uint)fs.Size);
 buffer = reader.ReadString((uint)fs.Size);
 }
 }
 }
 return buffer;
 }
 catch (Exception)
 {
 }
 }
 return buffer;
 }

You have successfully created JSON data and written it to a file and read it back. Alternatively you can use serialize the .NET class objects to JSON and deserialize them back.

How to: Serialize and Deserialize JSON Data

Happy coding! 😀