I am using StreamWriter to write a file in a sessionchange like logon and logoff.
But if a reboot happens just about the time when we write/close the file, we are getting an empty file and some time data already in it is getting deleted
This is my code
public void ToJson(T objectToWrite)
{
InformFileLogger.Instance.Debug(">>> start >>>");
try
{
string json = null;
string directory = Path.GetDirectoryName(this.serializeFilePath);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
if (File.Exists(this.serializeFilePath))
{
if (new FileInfo(this.serializeFilePath).Length == 0)
{
File.Delete(this.serializeFilePath);
}
}
json = JsonConvert.SerializeObject(objectToWrite);
if (json != null)
{
using (StreamWriter streamWriter = new StreamWriter(this.serializeFilePath))
{
streamWriter.WriteLine(json);
streamWriter.Close();
}
}
}
catch (Exception ex)
{
InformEventLogger.Error(ex.ToString());
InformFileLogger.Instance.Error(InformHelper.ExceptionMessageFormat(ex));
}
InformFileLogger.Instance.Debug("<<< end <<<");
}
How can I avoid writing null entries in the files/ getting the data deleted?
This really depends on how the reboot is triggered.
Unless the reboot is triggered by your code, you won't be able to make sure your code can do anything before a reboot - including completing a StreamWriter function.
Related
I use this code here to create a user-scoped setting during runtime:
System.Configuration.SettingsProperty userScopedProperty =
new System.Configuration.SettingsProperty("New Setting");
userScopedProperty.DefaultValue = "This setting default value";
userScopedProperty.IsReadOnly = false;
userScopedProperty.PropertyType = typeof(string);
userScopedProperty.Provider =
Properties.Settings.Default.Providers["LocalFileSettingsProvider"];
userScopedProperty.Attributes.Add(typeof(System.Configuration.UserScopedSettingAttribute),
new System.Configuration.UserScopedSettingAttribute());
Properties.Settings.Default.Properties.Add(userScopedProperty);
Properties.Settings.Default["New Setting"] = "value changed to this";
Properties.Settings.Default.Save();
Properties.Settings.Default.Reload();
Which for some reason only sometimes works and will create the settings in the userSettings section in the user.config file. While executing in the same session this works:
Properties.Settings.Default["New Setting"]
But as soon as I close the application and the start it up again, that line of code will give me a System.Configuration.SettingsPropertyNotFoundException. I have tried adding Properties.Settings.Default.Reload() right before attempting to read the setting but that doesnt seem to work either.
The goal of this portion of the project is to be able to create user settings during runtime, close the program, and when you start the program again you can view those settings. You should also be able to change them at any point. I run the program in Visual Studio in debug mode, not sure if that information is needed.
So my questions are:
How do I properly create during runtime and read the properties that are stored in the user.config file that I saved in a previous session? Is there a better way to do this?
I generally keep settings like that in an XML file in IsolatedStorage. I create a ProgramSettings class that I annotate for XML serialization (using XmlRootAttribute, XmlElementAttribute, and sometimes XmlArrayAttribute and XmlArrayItemAttribute) and then I use this class to read and write that XML settings file:
public static class PersistedSettings<T> where T : class, new()
{
public static T LoadSettings(string applicationName, ISettingsErrorReporter errorReporter)
{
var filename = GetFileName(applicationName);
try
{
using (var isoStore = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Domain | IsolatedStorageScope.Assembly, null, null))
{
if (!isoStore.FileExists(filename))
{
return new T();
}
//otherwise
using (var settingsStream = isoStore.OpenFile(filename, FileMode.Open, FileAccess.Read))
{
var serializer = new XmlSerializer(typeof(T));
var settings = (T)serializer.Deserialize(settingsStream);
settingsStream.Close();
return settings;
}
}
}
catch (IOException ioException)
{
errorReporter.WriteError($"IO Exception:{Environment.NewLine}{ioException.Message}");
}
catch (Exception ex)
{
errorReporter.WriteError($"Exception ({ex.GetType().Name}):{Environment.NewLine}{ex.Message}");
}
//no matter what kind of exception,
return new T();
}
public static void SaveSettings(string applicationName, T settings, ISettingsErrorReporter errorReporter)
{
try
{
using (var isoStore = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Domain | IsolatedStorageScope.Assembly, null, null))
{
using (var settingsStream = isoStore.CreateFile(GetFileName(applicationName)))
{
var serializer = new XmlSerializer(typeof(T));
serializer.Serialize(settingsStream, settings);
//let's be safe and use both suspenders and a belt (Flush, Close, Dispose)
settingsStream.Flush();
settingsStream.Close();
}
}
}
catch (IOException ioException)
{
errorReporter.WriteError($"I/O Exception:{Environment.NewLine}{ioException.Message}");
}
catch (Exception ex)
{
errorReporter.WriteError($"Exception ({ex.GetType().Name}):{Environment.NewLine}{ex.Message}");
}
}
private static string GetFileName(string applicationName)
{
return applicationName + ".xml";
}
}
I usually use this from simple WinForms apps. I make my Form class implement this interface:
public interface ISettingsErrorReporter
{
void WriteError(string message);
}
(usually by popping up a message box)
Then I call LoadSettings in the FormLoad event and SaveSettings in the form closing event.
It's not what you are asking, but it may satisfy your needs
Sometimes I get a clipboard error. I've researched this and found that there is a better way to do this, but being new I can't figure out how to integrate it in my code. Trying to make it more stable.
Tried multiple ways to convert the information. Looking to fix this not rewrite everything. I have been down many paths with no luck.
void exportagfile()
{
if (editgrid.Items.Count == 0)
{
MessageBox.Show("Nothing to export.");
}
else
{
try
{
editgrid.SelectAllCells();
editgrid.ClipboardCopyMode =
DataGridClipboardCopyMode.ExcludeHeader;
ApplicationCommands.Copy.Execute(null, editgrid);
String resultat2 =
(string)Clipboard.GetData(DataFormats.CommaSeparatedValue);
String result2 =
(string)Clipboard.GetData(DataFormats.Text);
editgrid.UnselectAllCells();
System.IO.StreamWriter file2 = new
System.IO.StreamWriter
(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) +
#"\MI_imp.txt");
file2.WriteLine(result2.Replace('\t', ',').Replace('ยป',
','));
file2.Close();
MessageBox.Show(" Exporting File MI_imp.txt to Desktop");
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
}
Trying to stop error when clipboard tries to open. Error: System.Runtime.InteropServices.COMExeption (0x800401D0) OpenClipboard Failed
I have what I thought would be a very simple file mover script. It checks for a file and moves it to a new directory if it exists:
if (File.Exists(_collection[x,0]))
{
System.IO.File.Move(_collection[x, 0], _moveTo);
MessageBox.Show("File moved because it was stale.");
}
It passes the check that the file exists, but then errors on the following line when trying to move it stating that the file is being used by another process. I can only assume that File.Exists is causing it to hang up somehow, but can't find a solution from anyone else who had this problem.
try this code:
string filePathNameToMove = "";
string directoryPathToMove = "";
if (File.Exists(filePathNameToMove))
{
string destinationFilePathName =
Path.Combine(directoryPathToMove, Path.GetFileName(filePathNameToMove));
if (!File.Exists(destinationFilePathName))
{
try
{
File.Move(filePathNameToMove, destinationFilePathName);
Console.WriteLine("File Moved!");
}
catch (Exception e)
{
Console.WriteLine("File Not Moved! Error:" + e.Message);
}
}
}
In case anyone else has this problem. In my case, the file had been opened in Excel and Excel was never garbage collected after being terminated. So the OS still thought the file was being accessed. I did the following, crude, but it works.
for (int i = 1; i > 0; i++)
{
try
{
File.Move(sourceFileName, destinationFileName);
break;
} catch
{
GC.Collect();
}
}
I have a problem coping a file. I need to copy a .db file and put it in a new folder (called "directory",selected previously with FolderPicker).
The code that i have is: (this is for a store app for Windows 8.1)
try{
StorageFile newDB = await StorageFile.GetFileFromPathAsync(directory);
StorageFile originalDB = await StorageFile.GetFileFromPathAsync(Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "AFBIT.db"));
await newDB.CopyAndReplaceAsync(originalDB);
}
catch(Exception ex){
}
I have a exception in neDB, and said "Value does not fall within the expected range."
I dont know another way to copy a file in xaml, if u know what is the problem or another way to do this i llbe very grateful.
I have something similar that I currently use when copying a file CopyFileAsync method I have created see if this can help you in regards to refactoring your code to a working model
public static async Task CopyFileAsync(string sourcePath, string destinationPath)
{
try
{
using (Stream source = File.Open(sourcePath, FileMode.Open))
{
using (Stream destination = File.Create(destinationPath))
{
await source.CopyToAsync(destination);
}
}
}
catch (IOException io)
{
HttpContext.Current.Response.Write(io.Message); //I use this within a web app change to work for your windows app
}
}
I'm not sure what your truly inquiring but I believe your attempting is:
public static bool CopyFile(string source, string destination)
{
if(!File.Exist(source))
return false;
if(string.IsNullOrEmpty(destination))
return false;
try
{
using(var reader = File.Open(source))
using(var writer = File.Create(destination))
reader.CopyTo(writer);
return true;
}
catch(IOException ex) { return false; }
}
Bare in mind this will eat your exception, then return false if it fails at any point for any reason.
That would essentially copy the file, I noticed that your trying to read your local application folder. Be careful, as it often requires Administrator Privileges when it resides in several locations within the Operating System.
this is my first post on this site and I searched high and wide to get my code to work.
Like the title says, it's a WinRT App and I'm having difficulty with File IO. What I want to do is read in a text file stored in a folder that is inside the application installation directory and that contains lines of data that I'll feed into an List<>.
public static async void GetStations()
{
try
{
using (var stream = await Windows.Storage.ApplicationData.Current.LocalFolder.OpenStreamForReadAsync(#"MyApp\Data\file.txt"))
{
using (var streamReader = new StreamReader(stream))
{
while (streamReader.Peek() >= 0)
{
string line = await streamReader.ReadLineAsync();
//do something with
}
}
}
}
catch (Exception e)
{
...
}
finally
{
...
}
}
the problem is I am getting file not found errors when trying to run it. Can anyone help? If you require that I post more information, I can...
Thanks in advance.
If you are distributing your file as a part of your application package then Package.Current.InstalledLocation is the right location. ApplicationData.Current.LocalFolder contains only files that have been put there by your application.
The correct code would be:
public static async void GetStations()
{
try
{
using (var stream = await Windows.ApplicationModel.Package.Current.InstalledLocation.OpenStreamForReadAsync(#"Data\file.txt"))
{
using (var streamReader = new StreamReader(stream))
{
while (streamReader.Peek() >= 0)
{
string line = await streamReader.ReadLineAsync();
//do something with
}
}
}
}
catch (Exception e)
{
//...
}
finally
{
//...
}
}
The file must be included in you project inside Data folder and have Build Action set to Content.
Instead of opening from ApplicationData, you probably need:
Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync
This will get the file in the package's installation folder, instead of the Application's Data folder.