We have a Silverlight app that needs to read and write dates to an isolated storage file. After a certain process we write the date to a text file as a fixed date format . Before the same process we read the text, and parse the date. Sounds straight forward right?
Unfortunately, we're getting a problem where the date written to the file is full of whitespace instead of the date as a string. The text is the correct length, but all the characters have a value of 0 (null). This has been an ongoing problem for months and months. We can't recreate the problem ourselves. It only happens 3-4 times per week with about 10-20 users using the app.
Here is some code that writes the date:
public static string DateFormat = "dd/MM/yyyy HH:mm:ss";
private static bool WriteLastDateTime(DateTime lastDateTime, string fileName, out string currentDateString) { currentDateString = lastDateTime.ToRegionlessString(); return IsolatedStorageUtilities.WriteFile(fileName, currentDateString); }
public static string ToRegionlessString(this DateTime date) { return date.ToString(DateFormat); }
Here is some code that reads the date:
private static DateTime? GetLastDateTime(string fileName) { DateTime? retVal = null; string dateString = null; try { dateString = IsolatedStorageUtilities.ReadFileWithoutCatch(fileName); Logger.Log(string.Format("Successfully read text from file: {0}, Text: {1}", fileName, dateString), LogMessageType.Information, typeof(OfflineUtilities).FullName, null); if (!string.IsNullOrEmpty(dateString)) { //User ParseExact so that no matter what the regional settings are AU/NZ data formatting is used as per the DateFormat variable retVal = DateTime.ParseExact(dateString, DateFormat, System.Globalization.CultureInfo.InvariantCulture); Logger.Log(string.Format("Successfully parsed the last date as {0}", retVal), LogMessageType.Information, typeof(OfflineUtilities).FullName, null); } else { Logger.Log(string.Format("There was no text in the file {0}.", fileName), LogMessageType.Warning, typeof(OfflineUtilities).FullName, null); return null; } } catch (Exception ex) { Logger.Log($"An error occurred while attempting to get the last date. File: {fileName}. The date format must be: {DateFormat}. The date text was '{(dateString != null ? dateString : string.Empty)}'", ex); } return retVal; }
We've tried everything we can think of to solve this problem, but is still occurs.
At first we thought it was something to do with regional settings, but we ruled this out by explicitly formatting the text, and by reading the file in as invariant culture.
We thought it might be related to the Silverlight isolated file storage API. So, I duplicated all the code for writing the file with windows APIs. This method uses Windows API calls with elevated trust to write the file outside of isolated storage:
public static void WriteAllText(string fileName, string text) { uint lengthWritten; NativeOverlapped overLap = new NativeOverlapped(); var stringBuilder = new StringBuilder(text); //Check if the file exists if (WindowsAPICalls.PathFileExists(fileName)) { //Delete the original file if it exists if (!WindowsAPICalls.DeleteFile(fileName)) { throw new Exception($"The file {fileName} could not be accessed for writing. It may be in use by another process."); } } //Create a file handle for writing var fileHandle = WindowsAPICalls.CreateFile(fileName, 0x40000000, 0x00000001, IntPtr.Zero, 4, 0x00000080, IntPtr.Zero); if (fileHandle == null) { throw new Exception($"The file {fileName} could not be accessed for writing. It may be in use by another process."); } //Write the buffer of the string builder to file if (!WindowsAPICalls.WriteFile(fileHandle, stringBuilder, (uint)text.Length, out lengthWritten, ref overLap)) { throw new Exception($"The file {fileName} could not be written to file. It may be in use by another process."); } if (text.Length != lengthWritten) { throw new Exception($"The length of the text was {text.Length} but the length written to the file {fileName} was {lengthWritten}"); } if (!WindowsAPICalls.CloseHandle(fileHandle)) { throw new Exception($"The file {fileName} was successfully written to, but the file handle could not be closed afterwards"); } }
This method works correctly, but what we found is that the same issue occurs occasionally. The text is written with whitespace in it. So, it can't be a problem with the Silverlight file writing API.
I thought that perhaps it could get a bug in DateTime.ToString(). But, I'm pretty sure that this is not the case because we also occasionally get cases where a big chunk of white space is written to a log file. I.e. the same problem occurs.
It almost seems as though the string data is getting corrupted in memory before it is being written to file.
We are very stuck!