Looping through a folder using system thread, how to ignore and continue if access to file was denied.
// Start thread.
System.Threading.ThreadStart start = delegate { scanner(#"C:\", "*.html;*.txt"); };
System.Threading.Thread thread = new System.Threading.Thread(start);
thread.Start();
private static string scanstatus = string.Empty;
private static void scanner(string folder, string patterns)
{
try
{
// Get the patterns.
string[] pattern_array = patterns.Split(';');
// Search.
foreach (string pattern in pattern_array)
{
foreach (string path in System.IO.Directory.GetFiles(folder, pattern, System.IO.SearchOption.AllDirectories))
{
// trim path
scanstatus = (path.Length > 60) ? "../" + path.Substring(path.Length - 59, 59) : path;
System.Threading.Thread.Sleep(5000);
}
}
}
catch (System.Exception excpt)
{
Console.WriteLine(excpt.Message);
}
finally
{
Console.WriteLine("*************DONE*************");
}
}
As Daniel mentioned in the comment, basically when you want to keep going with the next iteration, you need to move the try/catch to inside the loop. Currently your catch is outside the outer loop, so if an exception is thrown, execution can't continue. There's no concept of "continue from where you'd got to" within C#.
I'd strongly suggest that you also limit what you catch. For example:
foreach (string pattern in patternArray)
{
try
{
foreach (string path in Directory.GetFiles(...))
{
// ...
}
}
catch (IOException e)
{
// Log it or whatever
}
// Any other exceptions you want to catch?
}
Notes:
Catching Exception is almost always a bad idea, except as a final backstop at the top level of your request (or whatever) handling
Underscores in variable names aren't conventional in .NET; typically you'd use camelCase for variables (and PascalCase for methods, classes etc)
With using directives you can avoid putting the fully-qualified type names in your code, which would make it much easier to read
This method will end up being quite long - I'd suggest extracting the inner loop; possibly including the try/catch, or possibly not.
Related
I've been working on a sort of a directory info viewer.
1st stage was to create and populate a TreeView model and during coding I've nested a method to gather information about files on that dir.
All worked fine, values returned we're correct etc.
Now at the stage of code cleanup when I try to get that method out of TreeView creation one I get values that are not even close to original (like 90 MB instead of 1.2 TB).
Below code with issues marked:
private static int itemCount = 0;
private static long folderSizeInfo = 0;
public static void ListDirectory(string path)
{
(...)
var rootDirectoryInfo = new DirectoryInfo(path);
MainWindow.newWindowReport.Drzewko.Items.Add(CreateDirectoryNode(rootDirectoryInfo));
//this does not work if invoked from here <----------------- FIX ME!
//DirectoryMainOperation(rootDirectoryInfo);
//need to run this once more to get data from root
DirectoryContent_Operation(rootDirectoryInfo);
(...)
}
private static TreeViewItem CreateDirectoryNode(DirectoryInfo directoryInfo)
{
var directoryNode = new TreeViewItem { Header = directoryInfo.Name };
try
{
foreach (var directory in directoryInfo.GetDirectories())
{
if (!IsIgnorable(directory.Name))
{
directoryNode.Items.Add(CreateDirectoryNode(directory));
//this method somehow only works here <------------------------ FIX ME!
DirectoryContent_Operation(directory);
}
}
}
catch (UnauthorizedAccessException)
{
//Console.WriteLine("Path is not accessible: {0}", i);
}
return directoryNode;
}
//-------------------TO BE FIXED------------------
private static void DirectoryMainOperation(DirectoryInfo directoryInfo)
{
try
{
foreach (var directory in directoryInfo.GetDirectories())
{
if (!IsIgnorable(directory.Name))
{
DirectoryContent_Operation(directory);
}
}
}
catch (UnauthorizedAccessException)
{
//Console.WriteLine("Path is not accessible: {0}", i);
}
}
private static void DirectoryContent_Operation(DirectoryInfo targetDir)
{
try
{
foreach (var file in targetDir.EnumerateFiles("*", SearchOption.TopDirectoryOnly))
{
itemCount++;
folderSizeInfo += file.Length;
fileTable.Add(new FileExtension_List
{
FileFormat = file.Extension,
Category = extDB.Translation(file.Extension.ToUpper()),
Count = 1,
TotalSize = file.Length
});
}
}
catch (UnauthorizedAccessException)
{
}
catch (Exception ex)
{
}
}
The gist of it is that if I invoke "DirectoryContent_Operation(directory)" from:
"CreateDirectoryNode(DirectoryInfo directoryInfo)" it returns 1.2 TB (correct value)
"DirectoryMainOperation(DirectoryInfo directoryInfo)" it returns 90 MB.
From what it looks like DirectoryMainOperation returns prematurely due to an UnauthorizedAccessException, hence not returning all directories. In DirectoryContent_Operation you swallow every exception by catching Exception!
Please remove the try-catch (everywhere) to see what the (inner) exception message exactly is about and where the exception is thrown..
Note that swallowing exceptions is always a code smell and will likely introduce bugs, that can be really hard to identify.
If you can't handle the exception (put the application back into a stable state) the application must crash. Then fix the reason for the crash.
Before you think about if and how to handle an exception, think about how to avoid it.
Also from a performance perspective, it is highly recommended to avoid expensive exceptions.
Your problem shows how important it is to let exceptions crash the application in order to learn about implementation errors and also to prevent unwanted silent side effects like your incomplete directory list. Swallowing exceptions has put your application into an unpredictable state, which will lead to a lot faulty behavior, which may be unnoticed by users at first. This ca be very costly for a customer who uses your application to manage his business.
To avoid the UnauthorizedAccessException in your case, you can use DirectoryInfo.EnumerateDirectories(String, EnumerationOptions), which is available for .NET Core only (since version 2.1).
It avoids throwing an UnauthorizedAccessException exception by skipping forbidden directories by default.
Alternatively, only enumerate top level directories. Then check each child directory if it's forbidden, before you continue to recursively enumerate the child's top level directories. It is very likely that the following recursive enumeration will solve your problem.
public void ListDirectory(string path)
{
var rootDirectoryInfo = new DirectoryInfo(path);
var rootDirectoryNode = new TreeViewItem { Header = directoryInfo.Name };
MainWindow.newWindowReport.Drzewko.Items.Add(rootDirectoryNode);
CreateDirectoryNode(rootDirectoryInfo, rootDirectoryNode);
}
private static void CreateDirectoryNode(DirectoryInfo parentDirectory, TreeViewItem parentDirectoryNode)
{
foreach (DirectoryInfo childDirectory in parentDirectory.EnumerateDirectories("*", SearchOption.TopDirectoryOnly))
{
var childDirectoryNode = new TreeViewItem { Header = childDirectory.Name };
parentDirectoryNode.Items.Add(childDirectoryNode);
// Don't enter forbidden directories
// and optionally hidden directories too
if (childDirectory.Attributes.HasFlag(FileAttributes.System)
|| childDirectory.Attributes.HasFlag(FileAttributes.Hidden))
{
continue;
}
// Recursively iterate over child's subdirectories
CreateDirectoryNode(childDirectory, childDirectoryNode);
DirectoryContent_Operation(childDirectory);
}
}
private static void DirectoryMainOperation(DirectoryInfo parentDirectory)
{
foreach (DirectoryInfo childDirectory in parentDirectory.EnumerateDirectories("*", SearchOption.TopDirectoryOnly))
{
if (!IsIgnorable(childDirectory.Name))
{
DirectoryContent_Operation(childDirectory);
}
// Don't enter forbidden directories
// and optionally hidden directories too
if (childDirectory.Attributes.HasFlag(FileAttributes.System)
|| childDirectory.Attributes.HasFlag(FileAttributes.Hidden))
{
continue;
}
// Recursively iterate over child's subdirectories
DirectoryMainOperation(childDirectory);
}
}
Generally prefer DirectoryInfo.EnumerateDirectories over DirectoryInfo.GetDirectories.
I have the following method I'm working on:
private IEnumerable<TreeNode> GetChildNodes(TreeNode parent)
{
string path = parent.Tag.ToString();
// Add Directories
string[] subdirs = Directory.GetDirectories(path);
foreach (string subdir in subdirs)
{
yield return GetChildNode(subdir);
}
// Add Files
string[] files = Directory.GetFiles(path);
foreach (string file in files)
{
var child = GetChildNode(file);
fileNodeMap[file] = child;
yield return child;
}
}
This works fine with the exception of Directory.GetDirectories() and Directory.GetFiles() can both throw exceptions that I want to catch.
I can't catch the pieces of code which utilize those methods due to my use of yield (yields can't be placed within the body of a try if there is a catch). I know I could remove the yield and simply add to my children to a collection but I'm curious how someone would catch IOExceptions from both of those methods and still utilize yield?
How about something like (for the first part):
string[] subdirs;
try
{
subdirs = Directory.GetDirectories(path);
}
catch (IOException e)
{
// Do whatever you need here
subdirs = new string[0];
}
And similarly for the second. You don't need to yield within that try block. If this doesn't help, please write whatever code you would want to be valid, so that we can see what you're planning to do if an exception is thrown.
Could you not catch exceptions outside, in the code that calls them?
You could make helper methods that add your special error handling sauce:
private string[] GetSubdirectoriesWithSpecialSauce(string path)
{
string[] subdirectories;
try
{
subdirectories = Directory.GetDirectories(path);
}
catch (IOException ioe)
{
ShutdownWOPR();
CallDrFalken();
}
return subdirectories;
}
And obviously substitute the relevant calls. I of course assumed you wanted to yield even on errors, but I humbly accept that this assumption may be wrong :)
I would caution against using exceptions as a method of control flow - if you aren't sure that the directory or path is going to return a valid result, check for it first - almost all of those exceptions can be prevented by argument checking, something generally like the below.
private IEnumerable<TreeNode> GetChildNodes(TreeNode parent)
{
string path = parent.Tag.ToString();
if (String.IsNullOrEmpty (path) || String.IsNullOrWhiteSpace (path))
yield break;
// I'm not aware of a constant/enum for the maximum allowed path length here :(
if (path.Length > 260 || path.Any (Path.GetInvalidPathChars ().Contains))
yield break;
if (!Directory.Exists (path))
yield break;
Func<string[], Func<string[],string>,> SafeIO = (fn, arg) => {
try {
return fn (p);
} catch (IOException) {
return new string[0];
}
};
// Add Directories
string[] subdirs = SafeIO (Directory.GetDirectories, path);
foreach (string subdir in subdirs)
yield return GetChildNode(subdir);
// Add Files
string[] files = SafeIO (Directory.GetFiles, path);
foreach (string file in files) {
var child = GetChildNode(file);
fileNodeMap[file] = child;
yield return child;
}
}
Plenty of room for optimization there (and ripe for further decomposition), and the usual comments apply about race conditions and the lack of a guarantee for checking if a directory exists before it is deleted on another thread, so now you can make this more robust by wrapping a try/catch around the Get{Directories,Files} calls like Jon or xanatos suggested (EDIT: and that I've now wrapped up here as SafeIO) - but now you can catch only the specific exception that is susceptible to this (IOException or DirectoryNotFoundException) and reserve it for truly exceptional cases.
The exception will be throw by the call of GetDirectories and GetFiles, so you can try-catch THEM instead of the for-each,
I currently have a listview and a folder full of XML documents. I am using a foreach() loop to go through all the XML files and load data into the listview accordingly. My question is, how do I carry on with the foreach() loop if there is an error within in (example: if one of the XML files is not completely valid, contains errors, etc) and still add the data to the listview? I'm not asking how to parse the XML or how to load it into the listview, that much I know how to do, just not how to proceed with the loop if an error occurs.
Do you want:
foreach(var xml in xmls)
{
try
{
//import xml to listview
}
catch (SomeException e)
{
//deal with the exception here
}
}
Wrap the inner contents of the loop in a try ... catch block.
e.g.
foreach (var foo in iterableThing) {
try {
DoStuff(foo);
}
catch (AppropriateException) {
// Handle the exception (or ignore it)...
}
catch (SomeOtherException) {
// Handle the exception (or ignore it)...
}
}
wouldnt you do
foreach( loop )
{
try {
}
catch (Exception ex)
{
// all errors caught here, but the loop would continue
}
}
You can do the file processing in a try catch block and handle the error condition. You can handle the errors gracefully in catch and continue with loading of data.
I think you should do this:
foreach(var doc in docs)
{
//Make a function to evaluate the doc
if(isValid(doc))
{
//Logging or something
continue;
}
//Add data to listview
}
If your processing code throws exceptions, then use a try/catch block. If you're checking the results of some method with an if block, then use continue.
If you need to use this more often or if you just want to have more elegant code, you can use lambda expressions and delegates to create a new abstraction for this purpose:
static void SafeForEach<T>(this IEnumerable<T> source, Action<T> op) {
foreach(var el in source) {
try { op(el); }
catch (Exception e) { }
}
}
Then you can write just:
xmls.SafeForEach(xml => {
// Xml processing
});
However, using exceptions in situations where an error is expected is not the best programming style. If you can write a method, say IsValid that returns true if the document is valid, then you could write:
foreach(var xml in xmls.Where(x => x.IsValid)) {
// Xml processing
}
In Python, there is this useful exception handling code:
try:
# Code that could raise an exception
except Exception:
# Exception handling
else:
# Code to execute if the try block DID NOT fail
I think it's useful to be able to separate the code that could raise and exception from your normal code. In Python, this was possible as shown above, however I can't find anything like it in C#.
Assuming the feature or one like it doesn't exist, is it standard practice to put normal code in the try block or after the catch block?
The reason I ask is because I have the following code:
if (!IsReadOnly)
{
T newobj;
try
{
newobj = DataPortal.Update<T>(this);
List<string> keys = new List<string>(BasicProperties.Keys);
foreach (string key in keys)
{
BasicProperties[key] = newobj.BasicProperties[key];
}
}
catch (DataPortalException)
{
// TODO: Implement DataPortal.Update<T>() recovery mechanism
}
}
Which requires the normal code to be in the try block because otherwise if an exception was raised and subsequently handled, newobj would be unassigned, but it feels quite unnatural to have this much code in the try block which is unrelated to the DataPortalException. What to do?
Thanks
I would prefer to see the rest of the code outside the try/catch so it is clear where the exception you are trying to catch is coming from and that you don't accidentally catch an exception that you weren't trying to catch.
I think the closest equivalent to the Python try/catch/else is to use a local boolean variable to remember whether or not an exception was thrown.
bool success;
try
{
foo();
success = true;
}
catch (MyException)
{
recover();
success = false;
}
if (success)
{
bar();
}
But if you are doing this, I'd ask why you don't either fully recover from the exception so that you can continue as if there had been success, or else fully abort by returning an error code or even just letting the exception propagate to the caller.
Barbaric solution: create an Else class derived from Exception, throw an instance of it at the end of the try block, and use catch (Else) {...} to handle the other stuff.
I feel so dirty.
This will might get downvoted but doesn't c# have goto(note I have almost no c# knowledge so I have no idea if this works).
what about something like
try
{
...
}
catch(Exception ex)
{
...
goto Jump_past_tryelse
}
...//Code to execute if the try block DID NOT fail
Jump_past_tryelse:
...
C# does not have such a concept, so you are just left with three options,
put the else code inside the try.
put the else code outside the try catch block, use a local variable to indicate success or failure, and an if block around your else code.
put the else code in the finally block, use a local variable to indicate success or failure, and an if block arount you else code.
Allow me to repeat an idea from a similar StackOverflow question. You cannot do this directly, but you can write a method that encapsulates the behavior you need. Look at the original question to see how to implement the method (if you're not familiar with lambda expressions and Func delegates). The usage could look like this:
TryExceptRaise(() => {
// code that can throw exception
}, (Exception e) => {
// code to run in case of an exception
return (...);
}, () => {
// code to run if there is no exception
return (...);
});
Just put your "else" block before the catch. Then, it will only execute if code execution reaches that point:
try
{
fee();
fi();
foe();
fum();
/// put your "else" stuff here.
/// It will only be executed if fee-fi-foe-fum did not fail.
}
catch(Exception e)
{
// handle exception
}
Given that, I fail to see the use of try..catch...else unless there's something vital missing from the OP's description.
With C# version 7, you could use local functions to emulate this behaviour:
Example 1: (since C# version 7)
void Main()
{
void checkedCode()
{
try
{
foo();
}
catch (Exception ex)
{
recover();
return;
}
// ElseCode here
}
checkedCode();
}
If you prefer lambda syntax, you could also declare a run method
void Run(Action r) { r(); }
which only needs to be there once in your code, and then use the pattern for anonymous methods as follows
Example 2: (older C# versions and C# version 7)
Run(() => {
try
{
foo();
}
catch (Exception)
{
recover();
return;
}
// ElseCode here
});
whereever you need to enclose code in a safe context.
Try it in DotNetFiddle
Notes:
In both examples a function context is created so that we can use return; to exit on error.
You can find a similar pattern like the one used in Example 2 in JavaScript: Self-invoking anonymous functions (e.g. JQuery uses them). Because in C# you cannot self-invoke, the helper method Run is used.
Since Run does not have to be a local function, Example 2 works with older C# versions as well
You could do something like this:
if (!IsReadOnly)
{
T newobj = null;
try
{
newobj = DataPortal.Update<T>(this);
}
catch (DataPortalException)
{
// TODO: Implement DataPortal.Update<T>() recovery mechanism
}
if (newobj != null)
{
List<string> keys = new List<string>(BasicProperties.Keys);
foreach (string key in keys)
{
BasicProperties[key] = newobj.BasicProperties[key];
}
}
}
that would be the empty statement like hits
try
{
somethingThatCanThrow();
}
catch(Exception ex)
{
LogException(ex);
return;
}
ContinueFlow();
if (!IsReadOnly)
{
T newobj;
bool Done;
try
{
newobj = DataPortal.Update<T>(this);
List<string> keys = new List<string>(BasicProperties.Keys);
foreach (string key in keys)
{
BasicProperties[key] = newobj.BasicProperties[key];
}
Done = true;
}
catch (DataPortalException)
{
// TODO: Implement DataPortal.Update<T>() recovery mechanism
Done = false;
}
finally
{
if (newobj != null && Done == false)
{
List<string> keys = new List<string>(BasicProperties.Keys);
foreach (string key in keys)
{
BasicProperties[key] = newobj.BasicProperties[key];
}
}
}
}
I have a recursive method call. When any exception is thrown, I would like to see, where in the recursive call stack it happened. I have a field which holds a "path" which represents the recursion stack.
Now I would like to add the path information to any exception that could possibly be thrown in the recursive call.
void Recursive(int x)
{
// maintain the recursion path information
path.Push(x);
try
{
// do some stuff and recursively call the method
Recursive(x + 6);
}
catch(Exception ex)
{
if (ex is RecursionException)
{
// The exception is already wrapped
throw;
}
// wrap the exception, this should be done only once.
// save the path and original exception to the wrapper.
throw new RecursionException(path.ToString(), ex);
}
finally
{
// maintain the recursion path information
path.Pop()
}
}
It just looks too complicated. There is not only one method. There are probably twenty or even more places where I had to write this code.
Is there any simpler way to implement this?
Edit: To point this out: I would like to have a much simpler situation where there is not such an overhead to recursively call the method, because I have many such recursive calls, there is not only one method, there are a couple of methods recursively calling each other, which is complex enough.
So I would like to avoid the whole try - catch block, but I can't see any solution for this.
It is not a big problem for Exceptions thrown in my own code, because it could include the path from the beginning. But it is a problem with every other exception.
Edit: The Exceptions need to be wrapped in any other code, not only when calling the recursive method:
try
{
int a = 78 / x; // DivisionByZeroExeption
Recursive(x + 6);
this.NullReference.Add(x); // NullReferenceException
}
So wrapping only the call to Recusive does not work.
there are many such methods, having different signatures, doing different things, the only common thing is the exception handling.
Just simplifying (slightly) the exception handling:
void Recursive(int x)
{
// maintain the recursion path information
path.Push(x);
try
{
// do some stuff and recursively call the method
Recursive(x + 6);
}
catch( RecursionException )
{
throw;
}
catch( Exception )
{
throw new RecursionException(path.ToString(), ex);
}
finally
{
// maintain the recursion path information
path.Pop()
}
}
You get callstack info in with Exception if that's of any use to you, beyond that you could write this as a snippet then just insert that where you need to for re-usability.
There's also the following possibility, which would be slow but should work:
void DoStuff()
{
this.Recursive(1, this.RecursiveFunction1);
this.Recursive(2, this.RecursiveFunction2);
}
bool RecursiveFunction1(int x)
{
bool continueRecursing = false;
// do some stuff
return continueRecursing;
}
bool RecursiveFunction2(int y)
{
bool continueRecursing = false;
// do some other stuff here
return continueRecursing;
}
private void Recursive(int x, Func<int, bool> actionPerformer)
{
// maintain the recursion path information
path.Push(x);
try
{
// recursively call the method
if( actionPerformer(x) )
{
Recursive(x + 6, actionPerformer);
}
}
catch( RecursionException )
{
throw;
}
catch( Exception ex )
{
throw new RecursionException(path.ToString(), ex);
}
finally
{
// maintain the recursion path information
path.Pop();
}
}
What about yanking the catch handler out of the recursive function and just writing the recursion without less of the handling?
void StartRecursion(int x)
{
try
{
path.Clear();
Recursive(x);
}
catch (Exception ex)
{
throw new RecursionException(path.ToString(), ex);
}
}
void Recursive(int x)
{
path.Push(x);
Recursive(x + 6);
path.Pop();
}
void Main()
{
StartRecursion(100);
}
Your problem is in the exception handling. Wrapping an exception in your own exception is generally a bad idea because it puts a burden upon the caller of your code to have to handle your exception. A caller that suspects that they might, say, be causing a "path not found" exception by calling your code cannot wrap their call in a try-catch which catches IOException. They have to catch your RecursionException and then write a bunch of code to interrogate it to determine what kind of exception it really was. There are times when this pattern is justified, but I don't see that this is one of them.
The thing is, it's really unnecessary for you to use exception handling at all here. Here are some desirable aspects of a solution:
caller can catch whatever kinds of exception they want
in debug build, caller can determine information about what the recursive function was doing when an exception was thrown.
OK, great, if those are the design goals, then implement that:
class C
{
private Stack<int> path
#if DEBUG
= new Stack<int>();
#else
= null;
#endif
public Stack<int> Path { get { return path; } }
[Conditional("DEBUG")] private void Push(int x) { Path.Push(x); }
[Conditional("DEBUG")] private void Pop() { Path.Pop(); }
public int Recursive(int n)
{
Push(n);
int result = 1;
if (n > 1)
{
result = n * Recursive(n-1);
DoSomethingDangerous(n);
}
Pop();
return result;
}
}
And now the caller can deal with it:
C c = new C();
try
{
int x = c.Recursive(10);
}
catch(Exception ex)
{
#if DEBUG
// do something with c.Path
You see what we're doing here? We're taking advantage of the fact that an exception stops the recursive algorithm in its tracks. The last thing we want to do is clean up the path by popping in a finally; we want the pops to be lost on an exception!
Make sense?
I think you are trying to include the recursive path in the exception details so as to aid debugging.
What about trying this.
public void Recursive(int x)
{
try
{
_Recursive(x)
}
catch
{
throw new RecursionException(path.ToString(), ex);
clear path, we know we are at the top at this point
}
}
private void _Recursive(int x)
{
// maintain the recursion path information
path.Push(x);
_Recursive(x + 6);
//maintain the recursion path information
//note this is not in a catch so will not be called if there is an exception
path.Pop()
}
If you are using threading etc, you will may have to look at storing path in thread local storage.
If you don’t wish to force your caller to deal with RecursionException, you could make the “path” public so the caller can access it. (As par Eric Lippert later answer)
Or you could log the path to your error logging system when you catch the exception and then just re-throw the exception.
public void Recursive(int x)
{
try
{
_Recursive(x)
}
catch
{
//Log the path to your loggin sysem of choose
//Maybe log the exception if you are not logging at the top
// of your applicatoin
//Clear path, we know we are at the top at this point
}
}
This has the advantage that the caller does not need to know about the “path” at all.
It all comes down to what your caller needs, somehow I think you are the caller for this code, so there is no point us trying to 2nd guess what is needed at this level of deal.
void Recursive(int x)
{
// maintain the recursion path information
path.Push(x);
try
{
// do some stuff and recursively call the method
Recursive(x + 6);
}
finally
{
// maintain the recursion path information
path.Pop()
}
}
void Recursive2(int x)
{
try
{
Recursive(x);
}
catch()
{
// Whatever
}
}
That way you only handle once, if an exception raises Recursive2 handles it, the recursion is aborted.