Read from an external text file in a built WPF application - c#

I am building a desktop application in WPF and it requires user preferences from an external text file. The file should be available for the user to directly manipulate after final building and publishing.
String settingsPath = "settings.txt";
try
{
if (!File.Exists(settingsPath))
throw new Exception("settings file does not exist");
String settingsText = File.ReadAllText(settingsPath);
MessageBox.Show(settingsText);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
Window.GetWindow(this).Close();
}
Even when I create a settings.txt file using file explorer, it throws the exception when built.

The text file you are creating is probably not in the working directory folder.
Use this code to diagnose your problem, it will show you where your code is looking for the file.
String settingsPath = "settings.txt";
try
{
if (!File.Exists(settingsPath))
throw new FileNotFoundException("settings file does not exist", Path.GetFullPath(settingsPath));
String settingsText = File.ReadAllText(settingsPath);
MessageBox.Show(settingsText);
}
catch (FileNotFoundException fileEx)
{
MessageBox.Show($"{fileEx.Message}:{fileEx.FileName}");
Window.GetWindow(this).Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
Window.GetWindow(this).Close();
}

Related

How to restore Configuration Settings when they fail to initialize

I have my program which has some Application Settings and some User Settings. On some machines my User Settings config file becomes corrupt and stops my program loading. I then log into the machine and delete the UserConfig directory stored at
%USERPROFILE%\Appdata\Local\MyApp
When my file is corrupt the error thrown is Configuration Settings Failed To Initialize so I was wondering if this happened in my program whether there was a way to delete the corrupt file and reset the configuration.
So far I have:
try
{
var prop1= Settings.Default.prop1;
}
catch (Exception ex)
{
var userSettingsLocation =
Path.Combine(Environment.ExpandEnvironmentVariables(
"%USERPROFILE%"), "AppData","Local", "MyApp");
if (Directory.Exists(userSettingsLocation))
{
DeleteDirectory(userSettingsLocation); // This is a reccursive
// delete method
// I need to reload settings
}
}
This deletes the file fine but if I try to read my settings again using for example: Settings.Reset(); I still get the same error. I need to somehow reset the configuration Settings after deleting the corrupt file. Is this possible?
So heres the trick if anyone else wants to know:
try
{
var prop1= Settings.Default.prop1;
}
catch (Exception ex)
{
var userSettingsLocation =
Path.Combine(Environment.ExpandEnvironmentVariables(
"%USERPROFILE%"), "AppData","Local", "MyApp");
if (Directory.Exists(userSettingsLocation))
{
if (ex.InnerException is System.Configuration.ConfigurationException)
{
var settingsFile = (ex.InnerException as ConfigurationException).Filename;
File.Delete(settingsFile);
System.Windows.Forms.Application.Restart();
}
}
}
Edit: after some trials, I think you need to restart the application after deleting the faulty config file. Here another SO thread: C# - User Settings broken
The last answer there is essentially the code you could use.
Actually I think you must call Settings.Reset after deleting the file.
By the way you should use the exception details to get the config file name causing the issue:
catch(Exception ex)
{
if(ex.InnerException is ConfigurationErrorsException)
{
var settingsFile = (e.InnerException as ConfigurationErrorsException).Filename;
/* ....Your code... */
}
}
string filename (()e.InnerException).Filename;

What is the common way to throw exception if my exe file that i need to start does not exist on the machine

in my application i am start capinfos.exe that is part of Wireshark.
in the constructor i am check if Wireshark install on the machine:
private string _filePath = "";
public Capinfos(string capturePath)
{
if (Directory.Exists(#"C:\Program Files (x86)\Wireshark"))
{
_capInfos = #"C:\Program Files (x86)\Wireshark\capinfos.exe";
}
else if (Directory.Exists(#"C:\Program Files\Wireshark"))
{
_capInfos = #"C:\Program Files\Wireshark\capinfos.exe";
}
_filePath = capturePath;
}
what is the best way to do it and throw an exception if the file does not exist on the machine: please install Wireshark
private string _filePath = "";
public Capinfos(string capturePath) throws FileNotFoundException
{
if (Directory.Exists(#"C:\Program Files (x86)\Wireshark"))
{
_capInfos = #"C:\Program Files (x86)\Wireshark\capinfos.exe";
}
else if (Directory.Exists(#"C:\Program Files\Wireshark"))
{
_capInfos = #"C:\Program Files\Wireshark\capinfos.exe";
} else
{
throw new FileNotFoundException(#"Wireshark installation not found");
}
_filePath = capturePath;
}
You can then catch the exception by using this code:
try
{
Capinfos("path");
}
catch (FileNotFoundException ex)
{
Messagebox.Show("Please install wireshark.");
}
I don't have C# installed, this was written by hand. Hope it's fine!
Here's an excellent resource to learn on exceptions: http://msdn.microsoft.com/en-us/library/0yd65esw(v=vs.80).aspx
Something like:
throw new FileNotFoundException("Could not find " + _capInfos, _capInfos);
Not sure if this is what you want, but try to use a try-catch block. You could attempt to start the .exe in the try block and if it fails, throw a FileNotFoundException and create a popup box in the catch block that will alert the user of what they need to do.

Unrar file with subdirectory

I have used NUnrar to extract my files :
NUnrar.Archive.RarArchive archive = NUnrar.Archive.RarArchive.Open(location + "1.rar");
foreach (RarArchiveEntry item in archive.Entries)
{
string path = Path.Combine(location, Path.GetFileName(item.FilePath));
item.WriteToFile(path);
}
If my file has no any sub directory all things works but if rar file has sub directory all of them extracted to same folder how i can keep model of sub directory and file places
I've had to do some experimenting to get NUnrar to work properly as well.
Perhaps the little success I had can help you.
RarArchive archive = RarArchive.Open(#"D:\Archives\Test.rar");
foreach (RarArchiveEntry entry in archive.Entries)
{
try
{
string fileName = Path.GetFileName(entry.FilePath);
string rootToFile = Path.GetFullPath(entry.FilePath).Replace(fileName, "");
if (!Directory.Exists(rootToFile))
{
Directory.CreateDirectory(rootToFile);
}
entry.WriteToFile(rootToFile + fileName, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
}
catch (Exception ex)
{
//handle your exception here..
}
}
The code I have already uses (Exception e) further up, so I had to use (Exception ex) instead.
It's probably sloppy code, and could do with a tidy up - but being as late as it is I'm inclined to leave it be as it 'works'..
NUnrar.Archive.RarArchive.WriteToDirectory("update.rar", Application.StartupPath,NUnrar.Common.ExtractOptions.ExtractFullPath | NUnrar.Common.ExtractOptions.Overwrite);
if "update.rar" is inside the same directory as the executable.
I'd think RarArchive.ExtractToDirectory(source, destination); should work.
Or using your loop, change it to string path = Path.Combine(location, item.FilePath);

Trouble Moving files in C#?

I am making a software that will move files from the downloads folder to a specific sub folder in a directory. The sub folder is selected by the user by a combobox. I keep getting this error: System.IO.IOException: Cannot create a file when that file already exists. Also, these error come up on people's computer who install my program...exceptions and things. How do i turn it off. Also, why do i get this error? Here is my code:
string pathUser4 = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
string pathDownload4 = (pathUser4 + #"\Downloads\");
string sourceFile = pathDownload4 + listBox1.Text;
string pathdoc5 = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string pathDownload5 = (pathdoc5 + #"\iracing\setups\");
string destinationFile = pathDownload5 + comboBox1.Text;
File.Move(sourceFile, destinationFile);
if (comboBox1.Text == "Select File Destination")
{
MessageBox.Show("Please Select A Destination Folder", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
Each File.Move should be wrapped in a try/catch block as you can never expect an IO operation to execute without error. It could be something as simple as the user having a file handle open, or the file existing in the destination folder, either way, you don't want a single file to throw an exception that stops the entire operation. You will want to catch the exceptions and log them either to an error log file or to the event log, this way you can see the errors that occurred but it will not interrupt anything.
Secondly, for any desktop application I would add global error handling to log any uncaught errors. You can do this by putting this code at the beginning of your program,
AppDomain.CurrentDomain.UnhandledException += (a, exception) => File.AppendAllText("errorlog.txt", exception.ToString() + "\n"
This will keep the user from ever seeing ugly exceptions being thrown. Also be sure you are not giving the users the .pdb files as this will cause exceptions to contain paths of the computer it was compiled on which can contain your username and other sensitive information you wouldn't want a client to see.
You can register the global exception handling when the main window is initialized, you want it to be the first thing you do before any thing else because again you never know when an exception will be thrown so you have to think defensively.
public partial class MainWindow : Window
{
public MainWindow()
{
AppDomain.CurrentDomain.UnhandledException += (a, exception) => File.AppendAllText("errorlog.txt", exception.ToString() + "\n");
InitializeComponent();
}
}
C# uses exceptions extensively so it will be good concept for you to study up on if you are not familiar with this type of error handling. All exceptions derive from the Exception class so when you write catch (Exception e) this will catch all exceptions (because a base reference can hold an object of a derived type), however if you know the specific exception a method will throw you can catch a more specific exception (always before the more general catch) and handle it in a specific way. In this example you may have an IOException from the File.Move() that you want to catch and handle differently.
try
{
string pathUser4 = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
string pathDownload4 = (pathUser4 + #"\Downloads\");
string sourceFile = pathDownload4 + listBox1.Text;
string pathdoc5 = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string pathDownload5 = (pathdoc5 + #"\iracing\setups\");
string destinationFile = pathDownload5 + comboBox1.Text;
File.Move(sourceFile, destinationFile);
if (comboBox1.Text == "Select File Destination")
{
MessageBox.Show("Please Select A Destination Folder", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
catch (Exception e)
{
File.AppendAllText("ErrorLog.txt", e.ToString() + "\n");
}
The example code from MSDN for File.Move should get you pointed at the various things you need to deal with, such as an already existing file and basic error handling.
using System;
using System.IO;
class Test
{
public static void Main()
{
string path = #"c:\temp\MyTest.txt";
string path2 = #"c:\temp2\MyTest.txt";
try
{
if (!File.Exists(path))
{
// This statement ensures that the file is created,
// but the handle is not kept.
using (FileStream fs = File.Create(path)) {}
}
// Ensure that the target does not exist.
if (File.Exists(path2))
File.Delete(path2);
// Move the file.
File.Move(path, path2);
Console.WriteLine("{0} was moved to {1}.", path, path2);
// See if the original exists now.
if (File.Exists(path))
{
Console.WriteLine("The original file still exists, which is unexpected.");
}
else
{
Console.WriteLine("The original file no longer exists, which is expected.");
}
}
catch (Exception e)
{
Console.WriteLine("The process failed: {0}", e.ToString());
}
}
}
The error may caused by your code, or by some invalid input.
As #Despertar mentioned, I suggest all the program include error handling and log features in your code. It will be very helpful for your debug.
But I suggest use open source log library, not do it by yourself. For example, log4net, NLog, etc.

Permission problem with bitmap.Save()

I have this simple code:
System.Drawing.Bitmap bm = bitmapSourceToBitmap(source);
try
{
bm.Save(#"C:\Seva\testeImagem.jpg");
}
catch (Exception ex)
{
}
This throws: Generic Error GDI+.
Anyway, I seached and people say that the problem is with permissions. How can I give permissions to it? Thanks
First find out under what credentials the code is running.
Then check (and, when needed, fix) the security/NTFS settings of the Seva folder.
Especially when this code is running from within a website or service the account will not have permissions to write to the folder.
instead of saving to C:\Seva\testeImagem.jpg why not try saving to
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
"testeImagem.jpg");
You must ensure that the Seva folder exists under C:\ and ensure that the current user has permissions to write to\create this folder. Also, its considered bad practice to write to folders that the user doesn't own. If the user is Running As A Normal User (not an admin) failure to do so results in permission exceptions.
Could you test if the folder exists?
void BitmapCopy(System.Drawing.Bitmap source, string filename) {
if (!String.IsNullOrEmpty(filename) && (source != null)) {
string dirName = #"C:\Seva";
if (!System.IO.Directory.Exists(dirName)) {
dirName = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
}
string bmpFile = System.IO.Path.Combine(dirName, filename);
System.Drawing.Bitmap bm = bitmapSourceToBitmap(source);
try {
bm.Save(bmpFile);
} catch (ArgumentNullException ex) {
Console.WriteLine(ex.Message);
} catch (System.Runtime.InteropServices.ExternalException ex) {
Console.WriteLine(ex.Message);
}
}
}

Categories

Resources