Clearing an ObservableCollection after populating it with entries - c#

I have the following code to populate a Treeview with drives (RootDrive) and directories.
But how do I clear the directories collection after each loop? What happens now is that all directories in all drives are added to each drive.
When I use directories.Clear() in the Finally statement there are no directories added to each drive.
static public ObservableCollection<GetDrive> RootDrive = new ObservableCollection<GetDrive>();
public MainWindow()
{
InitializeComponent();
ObservableCollection<GetDirectory>directories = new ObservableCollection<GetDirectory>();
foreach (DriveInfo di in DriveInfo.GetDrives())
{
try
{
foreach (string s in Directory.GetDirectories(di.Name))
{
directories.Add(new GetDirectory(s));
}
}
catch (IOException) //drive is not ready, e.g. DVD drive
{
}
finally
{
RootDrive.Add(new GetDrive(di.Name, directories));
directories.Clear();
}
}
}
}
}

Simply put, use a local variable instead. And you are misusing the finally directive.
static public ObservableCollection<GetDrive> RootDrive = new ObservableCollection<GetDrive>();
public MainWindow()
{
InitializeComponent();
foreach (DriveInfo di in DriveInfo.GetDrives())
{
ObservableCollection<GetDirectory>directories = new ObservableCollection<GetDirectory>();
try
{
foreach (string s in Directory.GetDirectories(di.Name))
{
directories.Add(new GetDirectory(s));
}
}
catch (IOException) //drive is not ready, e.g. DVD drive
{
// Handle it?
}
RootDrive.Add(new GetDrive(di.Name, directories));
}
}

I think you have to change the code bit and add clear method after the first for loop. like below...
static public ObservableCollection<GetDrive> RootDrive = new ObservableCollection<GetDrive>();
public MainWindow()
{
InitializeComponent();
foreach (DriveInfo di in DriveInfo.GetDrives())
{
try
{
directories.Clear();
foreach (string s in Directory.GetDirectories(di.Name))
{
directories.Add(new GetDirectory(s));
}
}
catch (IOException) //drive is not ready, e.g. DVD drive
{
}
finally
{
RootDrive.Add(new GetDrive(di.Name, directories));
}
}
}
}

Related

How to continue from a UnauthorizedAccessException error in c# when searching for files

I am trying to figure out how to continue from a UnauthorizedAccessException error. I am trying to list all files in my drives and have used the try/ctch statements and continue but nothing seems to work.
Here is the code:
using System;
using System.IO;
using System.Linq;
public class Program
{
public static void Main(string[] args)
{
foreach(DriveInfo d in DriveInfo.GetDrives().Where(x = > x.IsReady))
{
try
{
string[] files = Directory.GetFiles(d.RootDirectory.FullName, #"*.*", SearchOption.AllDirectories).ToArray();
foreach(string file in files)
{
Console.Write(file);
}
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine(e.Message);
continue;
}
}
}
}
The exeception catches that I cannot access 'C:\Documents and Settings' but then terminates the code instead of listing the rest of the files that I can access. I have read up and know this is a problem/bug with net but cannot find out how to continue even after catching the exception.
You need to use recursion to query one directory at a time. This way you can catch any unauthorized exceptions and continue your search.
static void Main()
{
foreach (DriveInfo info in DriveInfo.GetDrives().Where(c => c.IsReady))
{
foreach (string file in DirSearch(info.RootDirectory.FullName))
{
Console.WriteLine(file);
}
}
Console.ReadKey(true);
}
private static IList<string> DirSearch(string path)
{
List<string> files = new List<string>();
try
{
foreach (string dir in Directory.GetDirectories(path))
{
foreach (string file in Directory.GetFiles(dir))
{
files.Add(file);
}
files.AddRange(DirSearch(dir));
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return files;
}

Object variable only showing the last value

The code below returns only the most recent value in the loop. What do I need to do for it to show all the values that are being iterated over? The reason I am using this method instead of SearchOption.AllDirectory is because there is a folder path I am not able to access. I did try using UnauthorizedAccessException with a try and catch, but that returns an empty value because it keeps on terminating the loop.
public void Main()
{
string path = #"drive"; // TODO
ApplyAllFiles(path, ProcessFile);
}
public void ProcessFile(string path)
{
/* ... */
}
public void ApplyAllFiles(string folder, Action<string> fileAction)
{
System.Collections.ArrayList FileList = new System.Collections.ArrayList();
List<string> logger = new List<string>();
DateTime DateFilter = DateTime.Now.AddMonths(-6);
foreach (string file in Directory.GetDirectories(folder))
{
fileAction(file);
}
foreach (string subDir in Directory.GetDirectories(folder))
{
string rootfolder = "root folder";
if (subDir.Contains(rootfolder))
{
FileList.Add(subDir);
Dts.Variables["User::objDirectoryList"].Value = FileList;
//MessageBox.Show(subDir);
}
try
{
ApplyAllFiles(subDir, fileAction);
}
catch (UnauthorizedAccessException e)
{
logger.Add(e.Message);
}
catch (System.IO.DirectoryNotFoundException e)
{
logger.Add(e.Message);
}
}
}
Try to remove the FileList declaration outside the function, also remove Dts.Variables["User::objDirectoryList"].Value = FileList; outside the loop:
System.Collections.ArrayList FileList = new System.Collections.ArrayList();
public void Main()
{
string path = #"drive"; // TODO
ApplyAllFiles(path, ProcessFile);
Dts.Variables["User::objDirectoryList"].Value = FileList;
}
public void ProcessFile(string path)
{
/* ... */
}
public void ApplyAllFiles(string folder, Action<string> fileAction)
{
List<string> logger = new List<string>();
DateTime DateFilter = DateTime.Now.AddMonths(-6);
foreach (string file in Directory.GetDirectories(folder))
{
fileAction(file);
}
foreach (string subDir in Directory.GetDirectories(folder))
{
string rootfolder = "root folder";
if (subDir.Contains(rootfolder))
{
FileList.Add(subDir);
//MessageBox.Show(subDir);
}
try
{
ApplyAllFiles(subDir, fileAction);
}
catch (UnauthorizedAccessException e)
{
logger.Add(e.Message);
}
catch (System.IO.DirectoryNotFoundException e)
{
logger.Add(e.Message);
}
}
}

How can i ignore access denied when searching to get all sub directories?

static IEnumerable<string> GetSubdirectoriesContainingOnlyFiles(string path)
{
try
{
return from subdirectory in Directory.GetDirectories(path, "*", SearchOption.AllDirectories)
where Directory.GetDirectories(subdirectory).Length == 0
select subdirectory;
}
catch
{
}
}
In this case i'm searching in c:\
So some directories are access denied. I added try and catch but now this method dosent have a return.
And how or should i handle at all it when it's getting to the catch ?
I want in the end to get a List of all sub directories so i can get all sub directories names and the Length(the number of sub directories).
UPDATE
I tried this in the class constructor:
if (m_pars.SearchDir != null)
{
ApplyAllFiles(m_pars.SearchDir,ProcessFile);
}
m_pars.SearchDir in this contain C:\
Then in ApplyAllFiles:
static List<string> allsubdirs = new List<string>();
static void ProcessFile(string path) {/* ... */}
public static void ApplyAllFiles(string folder, Action<string> fileAction)
{
foreach (string file in Directory.GetFiles(folder))
{
fileAction(file);
}
foreach (string subDir in Directory.GetDirectories(folder))
{
try
{
ApplyAllFiles(subDir, fileAction);
allsubdirs.Add(subDir);
}
catch
{
// swallow, log, whatever
}
}
}
But the List allsubdirs is empty.
Your problem might be that you don't visit (add to the list) the current directory before recursively visiting its subdirectories. So if you get an exception there, nothing will be added to the list.
The following works for me. (I've also made it a bit more generic by using callbacks and made the exception handling stricter.)
class DirectoryHelper
{
public static void Test()
{
DirectoryHelper.EnumerateSubDirectories(#"c:\windows\system32");
}
public static List<string> EnumerateSubDirectories(string path)
{
// Depending on your use case, it might be
// unecessary to save these in memory
List<string> allSubdirs = new List<string>();
EnumerateSubDirectories(path,
filePath => Console.WriteLine("Visited file: " + filePath),
dirPath => allSubdirs.Add(dirPath),
noAccessPath => Console.WriteLine("No access: " + noAccessPath)
);
return allSubdirs;
}
private static void EnumerateSubDirectories(string root, Action<string> fileAction, Action<string> subdirAction, Action<string> noAccessAction)
{
foreach (string file in Directory.GetFiles(root))
{
fileAction(file);
}
foreach (string dir in Directory.GetDirectories(root))
{
try
{
subdirAction(dir);
EnumerateSubDirectories(dir, fileAction, subdirAction, noAccessAction);
}
catch (UnauthorizedAccessException)
{
noAccessAction(dir);
}
}
}
}

Why does try catch error in recursive function C#

I've created a function used to populate a treeview with a targeted directory. However when I try to implement and error check to skip over folders which may have folder permission restrictions I get an error. Why do I get this error and how do i fix it?
Thank you in advance.
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace directoryBrowser
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
ListDirectory(treeView1, #"C:\Windows");
}
public void ListDirectory(TreeView treeView, string path)
{
treeView.Nodes.Clear();
var rootDirectoryInfo = new DirectoryInfo(path);
treeView.Nodes.Add(CreateDirectoryNode(rootDirectoryInfo));
}
public static TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo)
{
//try
//{
var directoryNode = new TreeNode(directoryInfo.Name);
foreach (var directory in directoryInfo.GetDirectories())
{
directoryNode.Nodes.Add(CreateDirectoryNode(directory));
}
foreach (var file in directoryInfo.GetFiles())
{
directoryNode.Nodes.Add(new TreeNode(file.Name));
}
return directoryNode;
//}
//catch (UnauthorizedAccessException) { }
}
}
}
You are answering your own question. You get an error because the user account which this function is running under doesn't have permission to access some of the folder.
You should then apply a try/catch statement WITHIN the for loop so if you get this exception, you function will keep on running for following folders.
public static TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo)
{
var directoryNode = new TreeNode(directoryInfo.Name);
foreach (var directory in directoryInfo.GetDirectories())
{
//try
{
directoryNode.Nodes.Add(CreateDirectoryNode(directory));
} catch {
// cannot access directory
}
}
foreach (var file in directoryInfo.GetFiles())
{
directoryNode.Nodes.Add(new TreeNode(file.Name));
}
return directoryNode;
}

Access Denied While Deleting .exe File

Summary Of Problem:
I have a console app that, after copying many folders and files over to a new location, a local drive, it then deletes certain files/folders. One of these filetypes it deletes is .exe files. When trying to delete said files it gives me a denied access error.(This also occurs while trying to delete other kinds of files and folders as well)
Other Notes:
I saw several questions, such as Unable to delete .exe file through c#. However the process was never running on my local machine nor on the source it was copied from. I am both a local administrator and a domain administrator on our domain, and I had ownership over all folders and files in the directories I'm working with. But it still denies me access when trying to delete the file from code. I am however able to delete such files/folders manually.(click delete key)
Problem:
As stated above I am looking for a way to get past this issue denying me access to delete these "Illegal" file types and delete them from my code.
My Code:(Updated)
#region Delete_Illegal_Items
public static void RemoveIllegalItems()
{
Console.Clear();
DirectoryInfo Libraries = new DirectoryInfo(Library.DestinationMain);
try
{
foreach (var Lib in Libraries.GetDirectories())
{
Console.WriteLine("Working On {0}.", Lib.Name);
Parallel.Invoke(
() =>
{
RemoveBadFiles(Lib);
},
() =>
{
DeleteEmptyFolders(Lib);
}
);
}
}
catch (AggregateException e)
{
Console.WriteLine("There Was An Unusual Error During Initialization Of Library Correction:\n{0}", e.InnerException.ToString());
}
}
private static string[] BadFiles = {
#".hta",
#".exe",
#".lnk",
#".tmp",
#".config",
#".ashx",
#".hta.",
#".hta::$DATA",
#".zip",
#".asmx",
#".json",
#".soap",
#".svc",
#".xamlx",
#".msi",
#".ops",
#".pif",
#".shtm",
#".shtml",
#"smt",
#".vb",
#".vbe",
#".vbs",
#".ds_store",
#".db",
#".ini",
#".tiff"
};
private static void RemoveBadFiles(DirectoryInfo directory)
{
DirectoryInfo[] dirs = null;
FileInfo[] files = null;
if (directory != null)
{
files = directory.GetFiles();
}
try
{
dirs = directory.GetDirectories();
}
catch (IOException) { }
catch (Exception e)
{
Console.WriteLine("\nError During Enumeration Of Items To Delete:\n{0}", e.Message);
}
if (files != null)
{
foreach (var file in files)
{
try
{
if (file.IsReadOnly)
{
file.IsReadOnly = false;
}
if (BadFiles.Contains(Path.GetExtension(file.FullName)))
{
File.Delete(file.FullName);
}
}
catch (Exception e)
{
Console.WriteLine("\nError During Removal Or Illegal Files:\n" + e.Message);
}
}
}
if (dirs != null)
{
foreach (var dir in dirs)
{
switch (dir.Name)
{
case ".TemporaryItems":
{
try
{
Directory.Delete(dir.FullName);
}
catch { }
break;
}
case "AI_RecycleBin":
{
try
{
Directory.Delete(dir.FullName);
}
catch { }
break;
}
case ".ToRemove":
{
try
{
Directory.Delete(dir.FullName);
}
catch { }
break;
}
default:
{
break;
}
}
RemoveBadFiles(dir);
}
}
}
private static void DeleteEmptyFolders(DirectoryInfo directory)
{
Program Main = new Program();
try
{
DirectoryInfo[] dirs = directory.GetDirectories();
foreach (var subDirectory in dirs)
{
int sum = Library.CountLibrary(subDirectory.FullName);
if (sum == 0)
{
Directory.Delete(subDirectory.FullName);
}
DeleteEmptyFolders(subDirectory);
}
}
catch { }
}
#endregion
Any help would be greatly appreciated. If this question has been directly answered elsewhere please feel free to mention it in the comment. As I stated above I have been looking through past question regarding this issue and have not found a solution as of yet. Otherwise thank you for your help.
Figured out the problem was with the files being marked as "Read-only" so I added a if statement before the deletion of the file to check if it was and remove the mark if need be. Here is the code that worked successfully for deleting all the wanted files.
#region Delete_Illegal_Items
public static void RemoveIllegalItems()
{
Console.Clear();
DirectoryInfo Libraries = new DirectoryInfo(Library.DestinationMain);
try
{
foreach (var Lib in Libraries.GetDirectories())
{
Console.WriteLine("Working On {0}.", Lib.Name);
Parallel.Invoke(
() =>
{
RemoveBadFiles(Lib);
},
() =>
{
DeleteEmptyFolders(Lib);
}
);
}
}
catch (AggregateException e)
{
Console.WriteLine("There Was An Unusual Error During Initialization Of Library Correction:\n{0}", e.InnerException.ToString());
}
}
private static string[] BadFiles = {
#".hta",
#".exe",
#".lnk",
#".tmp",
#".config",
#".ashx",
#".hta.",
#".hta::$DATA",
#".zip",
#".asmx",
#".json",
#".soap",
#".svc",
#".xamlx",
#".msi",
#".ops",
#".pif",
#".shtm",
#".shtml",
#"smt",
#".vb",
#".vbe",
#".vbs",
#".ds_store",
#"ds_store",
#"._.Trashes",
#".Trashes",
#".db",
#".dat",
#".sxw",
#".ini",
#".tif",
#".tiff"
};
private static void RemoveBadFiles(DirectoryInfo directory)
{
DirectoryInfo[] dirs = null;
FileInfo[] files = null;
if (directory != null)
{
try
{
files = directory.GetFiles();
}
catch (IOException) { }
}
try
{
dirs = directory.GetDirectories();
}
catch (IOException) { }
catch (Exception e)
{
Console.WriteLine("\nError During Enumeration Of Items To Delete:\n{0}", e.Message);
}
if (files != null)
{
foreach (var file in files)
{
try
{
if (file.IsReadOnly)
{
file.IsReadOnly = false;
}
if (BadFiles.Contains(Path.GetExtension(file.FullName)) || BadFiles.Contains(file.Name))
{
File.Delete(file.FullName);
}
}
catch (Exception e)
{
Console.WriteLine("\nError During Removal Or Illegal Files:\n" + e.Message);
}
}
}
if (dirs != null)
{
foreach (var dir in dirs)
{
switch (dir.Name)
{
case ".TemporaryItems":
{
try
{
Directory.Delete(dir.FullName);
}
catch { }
break;
}
case "TemporaryItems":
{
try
{
Directory.Delete(dir.FullName);
}
catch { }
break;
}
case "AI_RecycleBin":
{
try
{
Directory.Delete(dir.FullName);
}
catch { }
break;
}
case ".ToRemove":
{
try
{
Directory.Delete(dir.FullName);
}
catch { }
break;
}
default:
{
break;
}
}
RemoveBadFiles(dir);
}
}
}
private static void DeleteEmptyFolders(DirectoryInfo directory)
{
Program Main = new Program();
try
{
DirectoryInfo[] dirs = directory.GetDirectories();
foreach (var subDirectory in dirs)
{
int sum = Library.CountLibrary(subDirectory.FullName);
if (sum == 0)
{
Directory.Delete(subDirectory.FullName);
}
DeleteEmptyFolders(subDirectory);
}
}
catch { }
}
#endregion
Thank you to those that comment and helped. And hope this can help others in the future.

Categories