public static List<Product> Load(string filename)
{
if (!File.Exists(filename))
{
throw new FileNotFoundException("Data could not be found ", filename );
}
}
Visual Studio 2010 gives the following exception, "FileNotFoundException"
emmm.. ok. this problem seem to have been solved.
.
But however, I still can not find the file!! But the file is there, in the same directory, Ive already verified and double-verified the name is correct! I have no idea what is going on.
The file is called "Products.xml".
You are the one who is throwing the exception. Do you mean to put up an error message?
File.Exists may return false if the user that the code runs under does not have access to the file, as well as if the does not exist.
http://msdn.microsoft.com/en-us/library/system.io.file.exists.aspx
The file is called "Products.xml".
You expose yourself to random failure with a filename like that. You should use the full path name of the file, like c:\mumble\foo\products.xml. If you don't then you completely rely on your program's working directory being set correctly. The value of Environment.CurrentDirectory.
Even if it is set correctly by whatever program is starting yours (like a shortcut on the desktop), you still can get into trouble when code you didn't write changes the working directory. A good example is OpenFileDialog with the RestoreDirectory property left to the default value of false.
Always use full path names in your code. Or let the user select the file.
It looks like the problem is File.Exists is returning false and you're throwing an exception which is not handled by your code. Did you intend for this exception to be handled or does this represent a fatal error to your program?
The file located at filename does not exist, and thus it throws the exception with the following line: throw new FileNotFoundException("Data could not be found ", filename );
Did you mean to just output an error?
In you code first check for empty filename as the passed parameter may be empty string, plus apply try catch block on the code as the passed filename might not satisfy the path rules for a file. in catch block through your exception too.
You either:
A) Don't want to throw the exception via this line
throw new FileNotFoundException()
and instead want to display a Dialog to the user, or use some other error handling technique in there. To output an error either use one of the following:
Console.WriteLine("File not found")
MessageBox.Show("File not found");
B) Higher up in your call stack have a try/catch and handle your error there, similarly with a dialog or another error handling approach suitable for your application.
try
{
Load(filename);
}
catch(FileNotFoundException fe)
{}
Related
Well, what I want to do is to remove my folder that is located inside Roaming. I want this to work for every user, so the username of every PC is different. I already know that to get path of AppData I need following:
var path = Environment.SpecialFolder.ApplicationData;
But what to do to remove the folder with a specific name (Let's call it ExampleDir)? I tried this:
Path.Combine(path + "Kappa");
Directory.Delete(true.ToString());
But this does not work. I am beginner at C#, still, I want to practice. Will be grateful for help =)
First of all, Path.Combine() is used to replace string concatenation so don't concatenate strings in it. Pass every name you want to concatenate as a parameter and the function will do the rest.
Secondly, to remove a folder containing files you have to use the Directory.Delete(string, bool) overload. The bool value (called recursive) indicates wether you want to remove files and subfolders in the specified directory (see the MSDN Documentation for Directory.Delete()).
And finally, Environment.SpecialFolder.ApplicationData is just an enumration (meaning it's just a number). You have to pass it as a parameter to the Environment.GetFolderPath() method to get the actual path of the AppData folder.
Example:
string AppDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string FolderToDelete = Path.Combine(AppDataFolder, "Kappa");
try
{
Directory.Delete(FolderToDelete, true); //Setting "recursive" to true will remove every subfile/-folder.
}
catch (Exception ex)
{
//An error occurred, use this block to log it/show it to the user/whatever.
//ex.Message - The error message.
//ex.StackTrace - Where in the code the error occurred.
}
EDIT:
As #dman2306 said in his comment, some exception handling is good practice in case of that the deletion fails. I have added this to my above code.
The code in the try block will run until an exception is thrown (if any). If an exception is thrown the execution will move on to the catch block, which is where you catch the exception and perform for example error logging, stopping other procedures, etc.
EDIT 2:
You possibly have to add "Roaming" to Path.Combine(). I am unsure if it's already included or not, and I'm unable to test that now.
string FolderToDelete = Path.Combine(AppDataFolder, "Roaming", "Kappa");
Forget what I said, SpecialFolder.ApplicationData gives you the path to the Roaming folder.
First of all you are using Path.Combine() wrong. But you don't need that at all.
Second you have to use backslases to separate folders in a path when combining them with +.
And third: The method Directory.Delete() wants the path of the folder you want to delete as an argument.
Try this:
Directory.Delete(Environment.SpecialFolder.ApplicationData + "\\Kappa");
The log I'm trying to work with belongs to another program that runs concurrently with my own. I get a DirectoryNotFoundException stating "Could not find a part of the path " when I try to make the copy. The assert does pass. The exception is thrown at File.Copy(...) itself. With the if(File.Exists(...)) in place, the program is clearly able to see the file before it attempts to copy it.
Edit: Could permissions be a possible cause? The directory is located in the root of the C drive.
Edit: By adding the two asserts suggested by Jim Mischel and stepping through in the cold light of a new day, newControlProgramLog path was revealed as the culprit. GetSaveFilePath() was returning a default path for the particular run state I was testing. I declared the default but never checked to see that it existed on program start up. The directory is now created if it does not exist, and the function now works as intended.
Shout out to Christian Hagelid for calling that it wasn't an issue with controlProgramLogPath from the start.
private void CopyLogsToDataDirectoy()
{
Debug.Assert(Directory.Exists(_controlProgramDirectory));
string controlProgramLogPath = Path.Combine(_controlProgramDirectory, _controlProgramLogFileName);
if (File.Exists(controlProgramLogPath))
{
string dataFilePath = GetSaveFilePath();
string newControlProgramLogName = Path.GetFileNameWithoutExtension(dataFilePath);
newControlProgramLogName = newControlProgramLogName + ".control.log";
string newControlProgramLogPath = Path.GetDirectoryName(dataFilePath);
newControlProgramLogPath = Path.Combine(newControlProgramLogPath, newControlProgramLogName);
File.Copy(controlProgramLogPath, newControlProgramLogPath);
}
}
DirectoryNotFoundException occurs when part of the path you specified does not exist. It does not occur because a file is locked. If you get DirectoryNotFoundException, then it's almost certainly because the string you supplied does not reference a valid directory path. Documentation also says that you can get this exception if your code doesn't have the PathDiscovery permission. I suspect that's pretty unlikely in your case.
You should check the paths in controlProgramLogPath and newControlProgramLogPath immediately before calling File.Copy.
Debug.Assert(Directory.Exists(Path.GetDirectoryName(controlProgramLogPath));
Debug.Assert(Directory.Exists(Path.GetDirectoryName(newControlProgramLogPath));
I suspect that will reveal the problem.
Why I can't catch the Argument excpetion here:
string path = "\"";
bool dirOk = true;
try
{
dirOk = Directory.Exists(path);
}
catch (ArgumentException)
{
dirOk = false;//Never gets in here
}
Edited: Sorry, bad sample path, changed now!
Config VS debugger to halt on all exceptions.VS will break saying: "ArgumentException Occurred" "Illegal characters in path.", but the try catch do nothing.
Edit 2: I think I got it, sorry. VS breaks but the exception is already catch inside Exists().
The posted code does not throw any exception...
Directory.Exists("nonsense string") just returns false.
As far as I can tell it even returns when the string contains invalid path characters or is null.
On the MSDN page there is no mention of exceptions so I assume this is very 'safe' method to call.
The page does have this to say:
The Exists method returns false if any error occurs while trying to determine if the specified file exists. This can occur in situations that raise exceptions such as passing a file name with invalid characters or too many characters, a failing or missing disk, or if the caller does not have permission to read the file.
Simply because Directory.Exists does not throw exception when the path is not valid, it only returns true or false depending on the existance of the directory.
Look in the documentation on MSDN
Directory.Exists(string path) is not throwing exceptions at all. This seems to be a classic RTFM case ;)
As stated here the method just returns false on any parameter that is not specifying an absolute or relative path.
System.IO.File.Exists(string path)
returns always false, even when the file exists on the specified path. What could be the possible solution?
It could well be a permission problem. From the documentation:
The Exists method returns false if any error occurs while trying to determine if the specified file exists. This can occur in situations that raise exceptions such as passing a file name with invalid characters or too many characters, a failing or missing disk, or if the caller does not have permission to read the file.
One way of seeing what's happening is to just try to read the file (e.g. with File.OpenRead). I'd be surprised if that succeeds - but if it fails, the exception should give you more information.
Hiding file endings in windows can sometimes cause confusion: you KNOW your file is named file.txt when it is actually named file.txt.txt because the last 4 characters have been hidden by the OS.
One possibility not mentioned in any of the answers here is 'File System Redirection' on Windows 8.1 onward.
For example, if your program is a 32-bit application and you're running on 64-bit Windows then an attempt to access %windir%\System32 would be redirected to %windir%\SysWOW64. And if the file you're trying to access doesn't exist in %windir%\SysWOW64 then System.IO.File.Exists(string path) would return False.
Link to a nice article explaining this behavior
I was puzzling over this as well, then realized I was using File.Exists when I should have been using Directory.Exists.
in my case, a different "dash" in file name causes the issue.
var f1 = "4-37R.pdf";
var f2 = "4‐37R.pdf";
var r = f1==f2?"same":"diff";
Console.Write(r); //diff
turns out
var c1 = '-';
var c2 = '‐';
Console.WriteLine((int)c1); //45
Console.WriteLine((int)c2); //8208
use the same '-' fixes the issue.
How I got around this was using Server.MapPath(fileName) as it kept trying to find the file somewhere else.
System.IO.File.Exists(Server.MapPath(string path))
This had me stumped for a while while I was debugging a service locally, I was running File.Exists("U:\dir1") against a server location mapped on my workstation as (U:). I replaced the U:\dir1 to "\\serverPath\dir1" and File.Exists then returned true.
I was experiencing this myself too. In my case, I was deleting the file and re-creating it. In the process that was deleting the file, I forgot to add in WaitForExit() before using File.Exists later on
I just learned today that System.IO.File.Exists will return false if the file exists but is empty
System.IO.File.Exists(string path) returned false for me while trying to read C:\OpenSSL\bin\file.txt.
Running the application in Administrator mode did not help.
(I was logged on the administrator account, Windows 10)
Once I moved the file to C:\Users\MyUser\Desktop\file.txt, File.Exists() returned true.
Here's one more, which took me far too long to twig to.
The file name was in a constructed variable that was use to write the file, then the same variable used to check that it had been successfully written, so it could not have been different versions of '-'. I am running mono on Linux and debugging as a different user than the program is normally run by/as. Many of these types of errors are related to permissions and I spent a while banging my head on that. When File.OpenRead also threw "file not found" I finally noticed my file name had a space character at the end. I only saw this when I copied the exception message, which showed quote marks around the file name string, revealing the included space.
Apparently you can write a file name with a trailing space, but File.Exists trims that off and doesn't recognize it. When I eliminated the trailing space File.Exists worked as expected.
There can be requirement to use the DirectoryProvider Refresh() process to get the correct result from the Exists function.
e.g. code as per:
private DirectoryInfo CreateDirectory(string folderPath, int code, string message)
{
DirectoryInfo di;
try
{
di = DirectoryProvider.CreateDirectory(folderPath);
}
catch
{
throw new WebServiceException(code, HttpStatusCode.BadRequest, message);
}
di.Refresh();
if (!DirectoryProvider.Exists(di))
{
throw new WebServiceException(code, HttpStatusCode.BadRequest, message);
}
return di;
}
I was using System.IO.Path.Combine and assuming it would remove any trailing white space. For the life of me I could figure out why System.IO.File.Exists(path) was returning false.
I used the below snippet to test why it was failing
Turns out that a trailing white space was introduced causing an
"The filename, directory name, or volume label syntax is incorrect inside batch"
Hopefully someone will avoid the same stupid mistake as me
bool FileExists(string path){
try
{
using var stream = File.Open(path, FileMode.Open);
return true;
}
catch (FileNotFoundException)
{
return false;
}
catch (DirectoryNotFoundException)
{
return false;
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine(ex.message);
throw;
}
catch (Exception ex)
{
Console.WriteLine(ex.message);
throw;
}
}
logging exception
the code below allows to save the content of an exception in a text file. Here I'm getting only the decription of the error.
but it is not telling me where the exception occured, at which line.
Can anyone tell me how can I achive that so I can get even the line number where the exception occured?
#region WriteLogError
/// <summary>
/// Write an error Log in File
/// </summary>
/// <param name="errorMessage"></param>
public void WriteLogError(string errorMessage)
{
try
{
string path = "~/Error/" + DateTime.Today.ToString("dd-mm-yy") + ".txt";
if (!File.Exists(System.Web.HttpContext.Current.Server.MapPath(path)))
{
File.Create(System.Web.HttpContext.Current.Server.MapPath(path))
.Close();
}
using (StreamWriter w = File.AppendText(System.Web.HttpContext.Current.Server.MapPath(path)))
{
w.WriteLine("\r\nLog Entry : ");
w.WriteLine("{0}", DateTime.Now.ToString(CultureInfo.InvariantCulture));
string err = "Error in: " + System.Web.HttpContext.Current.Request.Url.ToString()
+ ". Error Message:" + errorMessage;
w.WriteLine(err);
w.WriteLine("__________________________");
w.Flush();
w.Close();
}
}
catch (Exception ex)
{
WriteLogError(ex.Message);
}
}
#endregion
I find that the easiest way to log exceptions in C# is to call the ToString() method:
try
{
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
This usually gives you all the information you need such as the error message and the stack trace, plus any extra exception specific context information. (however note that the stack trace will only show you source files and line numbers if you have your application compiled with debug information)
It is worth noting however that seeing a full stack trace can be fairly offputting for the user and so wherever possible you should try to handle exceptions and print out a more friendly error message.
On another note - you should replace your method WriteLogError with a fully featured logging framework (like Serilog) instead of trying to write your own.
Your logging method is not thread safe (your log file will probably end up with log messages being intermingled with each other) and also should definitely not call itself if you catch an exception - this will mean that any exceptions that occur whilst logging errors will probably cause a difficult to diagnose StackOverflow exception.
I could suggest how to fix those things, however you would be much better served just using a proper logging framework.
Just log ToString(). Not only will it give you the stack trace, but it'll also include the inner exceptions.
Also, when you deploy a release build of your code to a production environment for instance, don't forget to include the .pdb files in the release package. You need that file to get the line number of the code that excepted (see How much information do pdb files contain? (C# / .NET))
Your solution is pretty good. I went through the same phase
and eventually needed to log more and more (it will come...):
logging source location
callstack before exception (could be in really different place)
all internal exceptions in the same way
process id / thread id
time (or request ticks)
for web - url, http headers, client ip, cookies, web session content
some other critical variable values
loaded assemblies in memory
...
Preferably in the way that I clicked on the file link where the error occurred,
or clicked on a link in the callstack, and Visual Studio opened up at the appropriate location.
(Of course, all you need to do is *.PDB files, where the paths from the IL code
to your released source in C # are stored.)
So I finally started using this solution:
It exists as a Nuget package - Desharp.
It's for both application types - web and desktop.
See it's Desharp Github documentation. It has many configuration options.
try {
var myStrangeObj = new { /*... something really mysterious ...*/ };
throw new Exception("Something really baaaaad with my strange object :-)");
} catch (Exception ex) {
// store any rendered object in debug.html or debug.log file
Desharp.Debug.Log(myStrangeObj, Desharp.Level.DEBUG);
// store exception with all inner exceptions and everything else
// you need to know later in exceptions.html or exceptions.log file
Desharp.Debug.Log(ex);
}
It has HTML log formats, every exception in one line,
and from html page you can open in browser, you can click
on file link and go to Visual Studio - it's really addictive!
It's only necessary to install this Desharp editor opener.
See some demos here:
Web Basic App
Web MVC App
Console App
Try to check out any of those repos and log something by the way above.
then you can see logged results into ~/Logs directory. Mostly anything is configurable.
I am only answering for the ask, other people have already mentioned about the code already. If you want the line number to be included in your log you need to include the generated debug files (pdb) in your deployment to the server. If its just your Dev/Test region that is fine but I don't recommend using in production.
Please note that the exception class is serializable. This means that you could easily write the exception class to disk using the builtin XmlSerializer - or use a custom serializer to write to a txt file for example.
Logging to output can ofcourse be done by using ToString() instead of only reading the error message as mentioned in other answers.
Exception class
https://learn.microsoft.com/en-us/dotnet/api/system.exception?redirectedfrom=MSDN&view=netframework-4.7.2
Info about serialization, the act of converting an object to a file on disk and vice versa.
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/serialization/