I made an application that search for some files in some directories. When a directory isn't there it throws the DirectoryNotFoundException. I catch that exception but it doesn't have a DirectoryName property or something like that like the FileNotFoundException (FileName). How can I find the Directory Name from the exception properties?
There's no way to natively do this.
Add this class somewhere to your project:
public static class DirectoryNotFoundExceptionExtentions
{
public static string GetPath(this DirectoryNotFoundException dnfe)
{
System.Text.RegularExpressions.Regex pathMatcher = new System.Text.RegularExpressions.Regex(#"[^']+");
return pathMatcher.Matches(dnfe.Message)[1].Value;
}
}
Catch the exception and use the type extension like this:
catch (DirectoryNotFoundException dnfe)
{
Console.WriteLine(dnfe.GetPath());
}
It looks like a hack, but you can extract the path from the Message property. As for me, I would prefer to check if the directory exists first, by using the Directory.Exists method.
catch (DirectoryNotFoundException e)
{
// Result will be: Could not find a part of the path "C:\incorrect\path".
Console.WriteLine(e.Message);
// Result will be: C:\incorrect\path
Console.WriteLine(e.Message
.Replace("Could not find a part of the path \"", "")
.Replace("\".", ""));
}
It is a little inconsistent that FileNotFoundException has the file name, but DirectoryNotFoundException doesn't have the directory name, isn't it?
Here's a work around: Before you throw the exception, associate the errant directory name using Exception's Data property.
Immediately before you attempt to find files in a directory, save the name of the directory in a variable. Then begin a try block for the code that looks in that directory. You now have the directory name available should that block of code throw.
For example:
// ... somewhere in some method that's about to search a directory.
var dirName = directories[i]; // or something -- how do you get it before you pass it to DirectoryInfo?
try
{
SearchDirectory(dirName); // or a block of code that does the work
}
catch(Exception e)
{
// at this point, you know dirName. You can log it, add it to a list of erroring
// directories, or whatever. You could throw here, or swallow the error after logging it, etc.
}
Check that it exists first with Directory.Exists
If you are only looking to stomp this one bug in your IDE, then you can try doing this:
In Visual Studio, go to Debug -> Exceptions, then check the Thrown box for Common Language Runtime Exceptions. This will take you right to an exception when it happens, instead of waiting to get caught.
Sorry to dig up an old post, but as other has said it is pretty stupid that DirectoryNotFoundException does not have the directory as a property when FileNotFoundException does.
I've put it in as feature request for .NET:
http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/4472498-directorynotfoundexception-should-expose-the-name-
The format of the Message member of the DirectoryNotFoundException thrown from most Directory class methods is "Directory 'input' not found.". It shouldn't be hard to extract the input from this string.
Question thou, why would you need to get the input parameter from the exception if you're the one invoking the method with that exact parameter?
Related
I have an unmanaged dll so i wrote this to save the dll to file once the program is run.
Working code :
public static void ExtractResourceToFile()
{
if (!File.Exists("loader.dll"))
try
{
using (System.IO.FileStream fs = new System.IO.FileStream("loader.dll", System.IO.FileMode.Create))
System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("Kraken.Resources.loader.dll").CopyTo(fs);
Thread.Sleep(5000);
}
catch ( Exception ex)
{ }
}
Problem:
if the compiled Kraken.exe name changed the DLL is not being saved.
what I've tried :
public static void ExtractResourceToFile()
{
if (!File.Exists("loader.dll"))
try
{
string file = System.Reflection.Assembly.GetExecutingAssembly().Location;;
string app = System.IO.Path.GetFileNameWithoutExtension(file);
using (System.IO.FileStream fs = new System.IO.FileStream(file, System.IO.FileMode.Create))
System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(app + ".Resources.loader.dll").CopyTo(fs);
Thread.Sleep(5000);
}
catch ( Exception ex)
{ }
}
I've also tried to get the current process name and use it, but same problem occurred.
See this:
How do I get the name of the current executable in C#?
Particularly these comments are interesting:
Beware of GetExecutingAssembly(): if you call this from a library
assembly, it returns the name of the library assembly, which is
different from the name of the entry assembly (i.e. the original
executable). If you use GetEntryAssembly(), it returns the name of the
actual executable, but it throws an exception if the process is
running under WCF (admittedly a rare situation). For the most robust
code, use Process.GetCurrentProcess().ProcessName. – Contango Nov 3
'10 at 12:01
Hmm, note that the returned string won't change even if you rename
the executable file by hand using the file explorer. While
Environment.GetCommandLineArgs()[0] changes along with the actual
executable filename (of course). Coincidentally, the second method
resulted better for my specific situation as I want the data folder to
be named as the actual executable filename. – Hatoru Hansou Jan 23 '14
at 2:25
Hatoru's comment seems to support Phil1970's comment, that GetExecutingAssembly() probably use the resource properties found in the assembly instead of the actual file name.
So I'd use
Process.GetCurrentProcess().ProcessName
as Contango suggested.
And as zerkms said, don't ignore exceptions.
I'm trying to extract the file name from a ProjectItem and already found out a few things:
Using projectItem.Properties.Item("FullPath").Value.ToString() will sometimes fail, namely with HTML files.
Using projectItem.FileNames[0] seemed to be the solution, it worked for all types of files inside projects.
But when trying to get a file path from a solution file (a file that is saved directly in a solution folder, not inside a project), the call failed with an ArgumentException. Some more investigation and trial-and-error later I seem to have found the cause: For solution files the FileNames property is 1-based, not 0-based. Now I'm completely lost and fail to see the system behind all this. My current solution is:
Check if the Kind of the project item is equal to VSConstants.GUID_ItemType_PhysicalFile (then it is a "regular" file). If yes, return projectItem.FileNames[0].
In all other cases return projectItem.FileNames[1].
var projItemGuid = new Guid(projectItem.Kind);
try
{
return (projItemGuid == VSConstants.GUID_ItemType_PhysicalFile)
? projectItem.FileNames[0]
: projectItem.FileNames[1];
}
catch (Exception e)
{
throw new FileNotFoundException(
$"The file path of {projectItem.Name} could not be retrieved" +
$"\nThe index might be wrong.) \nOriginal exception: {e.Message}");
}
Is this exhaustive or am I missing something? Is getting a file name from a ProjectItem really this annoying and unsafe?
Which one code is better?
Code1:
if (!Directory.Exists("DirectoryPathHere"))
Directory.CreateDirectory("DirectoryPathHere");
Code2:
Directory.CreateDirectory("DirectoryPathHere");
I think Code2 because as I saw it not gives any error and its not making new folder when the folder already exists, so I though that checking for folder existence is useless. Right?
You don't need to check if the directory already exists, the method does it for you. If you check on MSDN :
Any and all directories specified in path are created, unless they
already exist or unless some part of path is invalid. The path
parameter specifies a directory path, not a file path. If the
directory already exists, this method does not create a new directory,
but it returns a DirectoryInfo object for the existing directory.
I would use a DirectoryInfo class, check if it exists, and maybe also if it does exist, check the permissions on the directory in case my current run-time permissions are not sufficient to access the contents or update the directory.
You should apply exception handling to whichever method you go with; what if, for instance, a file exists with the name of the directory?
The key thing is the CreateDirectory method implicitly checks if the Directory Exists before attempting to create it.
For code readability it is better to use the explicit method Directory.Exists first.
I also strongly agree with #SimonWhitehead on the defensive programming front. Showing you're aware of the pit falls... and defending actively against them explicitly it in your code is a good thing:)
I think we can all see the fact that the second method does the same,
but, is it cheaper in terms of being more readable? No.
Anyone who knows the framework will probably disagree, and I can too. But:
Always code as if the person who ends up maintaining your code is a
violent psychopath who knows where you live.
http://www.codinghorror.com/blog/2008/06/coding-for-violent-psychopaths.html
Edit 2: I have a funny feeling that the compiler does this. The assembly programmers would be able to detect it before producing the IL..
Here is a simple code from http://msdn.microsoft.com/en-us/library/54a0at6s.aspx
using System;
using System.IO;
class Test
{
public static void Main()
{
// Specify the directory you want to manipulate.
string path = #"c:\MyDir";
try
{
// Determine whether the directory exists.
if (Directory.Exists(path))
{
Console.WriteLine("That path exists already.");
return;
}
// Try to create the directory.
DirectoryInfo di = Directory.CreateDirectory(path);
Console.WriteLine("The directory was created successfully at {0}.", Directory.GetCreationTime(path));
// Delete the directory.
di.Delete();
Console.WriteLine("The directory was deleted successfully.");
}
catch (Exception e)
{
Console.WriteLine("The process failed: {0}", e.ToString());
}
finally {}
}
}
You don't need to check it, but because there are many problems that occur when handling files and folder, its better that include a try-catch statement so that any potential problems be handled:
try {
Directory.CreateDirectory("DirectoryPathHere");
}
catch (Exception ex)
{
MessageBox.Show("Error: "+ex.Message);
}
you could also add finally if its needed.
I run into a very strange problem in my C# 2.0 WinForms app and I'm not even sure if its worth asking SO, because the problem occurs in a strange setup and I don't think that you could reproduce it without my sources, but I'm totally out of ideas.
I have a Form with a TreeView on the left and an ListView on the right. The TreeView shows all available files and subfolders from a specific folder(which contains documents i need for my app). If a Folder is selected the ListView shows all files and subfolders from the selected folder. At startup I populate the TreeView form the folder and after that I select the first TreeNode by code(in my case it's an folder). After that the Content of the TreeView looks like this:
-folder
-file1
-file2
Selecting the folder triggers the AfterSelecedEvent of the TreeView. Because a folder was selected I populate the ListView using the following methode:
private void fillOverview(FAFolder folder)
{
lv_overview.Items.Clear();
ListViewItem item;
foreach (FAFile file in folder.sortedContent)
{
if (file is FAFolder)
{
item = new ListViewItem(file.Name, "Folder"); //exception got thrown here
}
else
{
item = new ListViewItem(file.Name, file.Name);
}
item.Tag = file;
lv_overview.Items.Add(item);
}
}
As you can see there is no subfolder, so the line item = new ListViewItem(file.Name, "Folder"); should never be touched in this setup, but every now and then a NullReferenceException got thrown. If I wrap this line with try/catch the exception got thrown inside the catch block. I tried checking everything if it's null or not, but ther were no nullreferences. Or if I add a MessageBox right before this line the exceptions got still thrown and no MessageBoxpops up. This brings me to the conclusion that the execption stacktrace is wrong and/or this exceptions comes from an other Thread or something like that.
I'm a very optimistic person and I know how clever the SO community can be, but I don't think that anybody can point out what the problem is. So what i'm actuallly looking for are hints and advices how i could find and debug the cause of this strange behavior.
EDIT:
internal abstract class FAFile
{
internal string Name;
internal readonly FAFolder Parent;
internal FAFile(FAFolder parent)
{
this.Parent = parent;
}
}
internal sealed class FAFolder : FAFile
{
internal readonly IDictionary<string, FAFile> Content = new Dictionary<string, FAFile>();
internal FAFolder(FAFolder parent, string name) : base(parent)
{
this.Name = name;
}
}
internal sealed class FADocument : FAFile
{
public readonly string Path;
public FADocument(FAFolder parent, string path): base(parent)
{
this.Path = path;
this.Name = System.IO.Path.GetFileNameWithoutExtension(path);
}
}
Have you tried an null check on folder.sortedContent ?
Usually ReSharper will prompt me that something like that should have a null check.
If you want to be sure, add the following line to your code, above the foreach loop:
if (folder.sortedContent == null) throw new Exception("It was null, dangit!");
On the line you mention:
item = new ListViewItem(file.Name, "Folder")
the only thing that can cause a NullReferenceException is if file is null (unless the exception is being thrown from within the ListViewItem constructor itself).
You don't provide the code for folder.sortedContent so I can't tell - but is it possible that one of the elements in this collection might be null under certain circumstances?
If the ListViewItem constructor is throwing the exception then you will need to use Reflector to look at the code, or download the reference source.
A co-worker of mine just found the answer(probably). I use a Thread to load the ImageList to the ListView from the HDD and this thread sometimes freezes and if i assign a ImageKey it fails. That's no answer why the exception is uncatchable or why it's thrown at this (unreachable) line. But i strongly belive that this is the cause of the problem.
That line is not unreachable. Because FAFolder derives from FAFile, it is possible that 'file is FAFolder' will return true.
However, that would imply that file is not null, unless it is being changed by another thread.
Edit: file can't be changed by another thread as it's a local reference. Can you provide a stack trace for the exception? This one has me intrigued now.
I just cannot help wondering is the FAFolder contain a '.' or a '..' for parent and subdirectory? and the sorting breaks as a result?
This answer will be edited accordingly if this turns out to be untrue?
Hope this helps,
Best regards,
Tom.
Is this exception reproducible on demand?
Can you show the the stack trace of the exception?
What other threads are running when the exception is thrown?
In general, there are two ways to debug this type of stuff. The first way is so-called "scientific" debugging:
Devise a theory to explain observed behaviour.
Devise an experiment to test the theory.
Run the experiment and observe the results.
The second way is by stripping-down the actual code piece by piece until the exception is no longer triggered. Then you have a significant clue for further investigation.
This brings me to the conclusion that the execption stacktrace is wrong....
It's usually easier to start by assuming that the problem is in your own code.
I get the message that the namespace can't be found when I use the code below. Where does the AccessDeniedException live?
try { ... }
catch (SomeKindOfException ex)
{
MessageBox.Show(ex.Message);
}
catch (AccessDeniedException ex)
{
//Do something else
}
Thanks
I don't think that's the exception you're looking for. The only one with this name (that I can find) is in a Sharepoint namespace. Try attaching the debugger and seeing exactly what the type of the thrown exception is.
The type of the exception is going to vary depending on your context. So for example, if it's an "access denied" when trying to open a file, it could be a FileLoadException, or something similar. If it's encountered because of Code Access Security, it will be SecurityException. And so on.
You may need to give the full namespace on the exception, or have a using statement at the top of your code file so .NET knows where to find the exception you're talking about. If that doesn't work, maybe you need to add the DLL that contains that exception to the "REFERENCES" list in your project.