I can do this task in a normal form application but i am brand new to working with WPF applications.
I want to enter a directory path in a TextBox, then click a Button which validates and recursively searches that path, and displays all the files in a ListBox.
I have already looked at this article but i don't understand it fully because again, i'm very new to this.
Any help would be appreciated.
Try this.
DirectoryInfo dir = new DirectoryInfo("your path");
dir.GetFiles("*.*", SearchOption.AllDirectories);
Or this;
void DirSearch(string sDir)
{
try
{
foreach (string d in Directory.GetDirectories(sDir))
{
foreach (string f in Directory.GetFiles(d, txtFile.Text))
{
lstFilesFound.Items.Add(f);
}
DirSearch(d);
}
}
catch (System.Exception excpt)
{
Console.WriteLine(excpt.Message);
}
}
Related
The folder C:\Users contain 3 subfolders :
C:\Users\hacen
C:\Users\_rafi_000
C:\Users\Public
However, when I call :
DirSearch(#"C:\Users\", "*.jpg");
It outputs all jpg filenames from Public and hacen, but not from _rafi_000 which is the folder of current user.
Here is the function :
static void DirSearch(string dir, string pattern)
{
try
{
foreach (string f in Directory.GetFiles(dir, pattern))
{
Console.WriteLine(f);
}
foreach (string d in Directory.GetDirectories(dir))
{
DirSearch(d, pattern);
}
}
catch (System.Exception ex)
{
//MessageBox.Show(ex.Message);
}
}
EDIT:
I tried with the code below and it works. So it isn't an access denied problem :
DirSearch("C:\Users\_rafi_000\","*.jpg");
What I noticed so far is that unlike other subfolders, the folder _rafi_000 cannot be ranamed when I press F2
Would this work?
void DirSearch(string dir, "*.JPG")
{
foreach (string f in Directory.GetFiles(dir, "*.JPG"))
{
Console.WriteLine(f);
}
foreach (string d in Directory.GetDirectories(dir))
{
DirSearch(d);
}
}
Could be related to where the jpg are stored and how reparse points work in later windows version.
I suggest looking at:
Directory Searching: http://msdn.microsoft.com/en-us/library/bb513869.aspx
Reparse Point Info: http://msdn.microsoft.com/en-us/library/aa365503(VS.85).aspx
I ran your code and it works fine in windows XP:
C:\Users\hacen\bar.jpg
C:\Users\Public\bar1.jpg
C:\Users\_rafi_000\bar2.jpg
Your code is correct.
Perhaps Process Monitor can help?
If the code is fine, it must be something else. I understand that you can run the code directly against the directory which is causing you a problem (which is surprising) - but I think Process Mon could help.
Ok, i have some code that will scan my computer and find .txt files and display them in a listbox:
private void button2_Click(object sender, EventArgs e)
{
IEnumerable<string> files = System.IO.Directory.EnumerateFiles(#"C:\", "*.txt*", System.IO.SearchOption.AllDirectories);
foreach (var f in files)
{
listBox1.Items.Add(String.Format("{0}", f));
}
}
I get an error every time i run this. It says i do not authorization to the trash bin. I do not care weather it scans the trash or not. It there any way to exclude the trash bin out of the scan? Also, can someone help me improve my code, if you see anything wrong! Thanks!
Quickest way is to put them under a try-catch block because EnumerateFiles function does not have access to the restricted files because of the operating system permissions.
private void SearchDrives()
{
foreach (String drive in Directory.GetLogicalDrives())
{
try
{
// Search for folders into the drive.
SearchFolders(drive);
}
catch (Exception) { }
}
}
//---------------------------------------------------------------------------
private void SearchFolders(String prmPath)
{
try
{
foreach (String folder in Directory.GetDirectories(prmPath))
{
// Recursive call for each subdirectory.
SearchFolders(folder);
// Create the list of files.
SearchFiles(folder);
}
}
catch (Exception) { }
}
//---------------------------------------------------------------------------
private void SearchFiles(String prmPath)
{
try
{
foreach (String file in Directory.GetFiles(prmPath))
{
FileInfo info = new FileInfo(file);
if (info.Extension == ".txt")
{
listBox1.Items.Add(info.Name);
}
}
}
catch (Exception) { }
}
//---------------------------------------------------------------------------
Not just the recycle bin, it will also fail to read the file header of several files into your system direcotry.
In general you can do it so that you do recursive calls for every folder and just use try/catch blocks to see witch ones you can or can't access. But as Andras suggested I would also go with what allready exists will save you time
Another aproach on your example
I am creating a backup application where c# scans a directory. Before I use to have something like this in order to get all the files and subfiles in a directory:
DirectoryInfo di = new DirectoryInfo("A:\\");
var directories= di.GetFiles("*", SearchOption.AllDirectories);
foreach (FileInfo d in directories)
{
//Add files to a list so that later they can be compared to see if each file
// needs to be copid or not
}
The only problem with that is that sometimes a file could not be accessed and I get several errors. an example of an error that I get is:
As a result I created a recursive method that will scan all files in the current directory. If there where directories in that directory then the method will be called again passing that directory. The nice thing about this method is that I could place the files inside a try catch block giving me the option to add those files to a List if there where no errors and adding the directory to another list if I had errors.
try
{
files = di.GetFiles(searchPattern, SearchOption.TopDirectoryOnly);
}
catch
{
//info of this folder was not able to get
lstFilesErrors.Add(sDir(di));
return;
}
So this method works great the only problem is that when I scan a large directory it takes to much times. How could I speed up this process? My actual method is this in case you need it.
private void startScan(DirectoryInfo di)
{
//lstFilesErrors is a list of MyFile objects
// I created that class because I wanted to store more specific information
// about a file such as its comparePath name and other properties that I need
// in order to compare it with another list
// lstFiles is a list of MyFile objects that store all the files
// that are contained in path that I want to scan
FileInfo[] files = null;
DirectoryInfo[] directories = null;
string searchPattern = "*.*";
try
{
files = di.GetFiles(searchPattern, SearchOption.TopDirectoryOnly);
}
catch
{
//info of this folder was not able to get
lstFilesErrors.Add(sDir(di));
return;
}
// if there are files in the directory then add those files to the list
if (files != null)
{
foreach (FileInfo f in files)
{
lstFiles.Add(sFile(f));
}
}
try
{
directories = di.GetDirectories(searchPattern, SearchOption.TopDirectoryOnly);
}
catch
{
lstFilesErrors.Add(sDir(di));
return;
}
// if that directory has more directories then add them to the list then
// execute this function
if (directories != null)
foreach (DirectoryInfo d in directories)
{
FileInfo[] subFiles = null;
DirectoryInfo[] subDir = null;
bool isThereAnError = false;
try
{
subFiles = d.GetFiles();
subDir = d.GetDirectories();
}
catch
{
isThereAnError = true;
}
if (isThereAnError)
lstFilesErrors.Add(sDir(d));
else
{
lstFiles.Add(sDir(d));
startScan(d);
}
}
}
Ant the problem if I try to handle the exception with something like:
DirectoryInfo di = new DirectoryInfo("A:\\");
FileInfo[] directories = null;
try
{
directories = di.GetFiles("*", SearchOption.AllDirectories);
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("There was an error with UnauthorizedAccessException");
}
catch
{
Console.WriteLine("There was antother error");
}
Is that if an exception occurs then I get no files.
This method is much faster. You can only tel when placing a lot of files in a directory. My A:\ external hard drive contains almost 1 terabit so it makes a big difference when dealing with a lot of files.
static void Main(string[] args)
{
DirectoryInfo di = new DirectoryInfo("A:\\");
FullDirList(di, "*");
Console.WriteLine("Done");
Console.Read();
}
static List<FileInfo> files = new List<FileInfo>(); // List that will hold the files and subfiles in path
static List<DirectoryInfo> folders = new List<DirectoryInfo>(); // List that hold direcotries that cannot be accessed
static void FullDirList(DirectoryInfo dir, string searchPattern)
{
// Console.WriteLine("Directory {0}", dir.FullName);
// list the files
try
{
foreach (FileInfo f in dir.GetFiles(searchPattern))
{
//Console.WriteLine("File {0}", f.FullName);
files.Add(f);
}
}
catch
{
Console.WriteLine("Directory {0} \n could not be accessed!!!!", dir.FullName);
return; // We alredy got an error trying to access dir so dont try to access it again
}
// process each directory
// If I have been able to see the files in the directory I should also be able
// to look at its directories so I dont think I should place this in a try catch block
foreach (DirectoryInfo d in dir.GetDirectories())
{
folders.Add(d);
FullDirList(d, searchPattern);
}
}
By the way I got this thanks to your comment Jim Mischel
In .NET 4.0 there's the Directory.EnumerateFiles method which returns an IEnumerable<string> and is not loading all the files in memory. It's only once you start iterating over the returned collection that files will be returned and exceptions could be handled.
There is a long history of the .NET file enumeration methods being slow. The issue is there is not an instantaneous way of enumerating large directory structures. Even the accepted answer here has its issues with GC allocations.
The best I've been able to do is wrapped up in my library and exposed as the FindFile (source) class in the CSharpTest.Net.IO namespace. This class can enumerate files and folders without unneeded GC allocations and string marshalling.
The usage is simple enough, and the RaiseOnAccessDenied property will skip the directories and files the user does not have access to:
private static long SizeOf(string directory)
{
var fcounter = new CSharpTest.Net.IO.FindFile(directory, "*", true, true, true);
fcounter.RaiseOnAccessDenied = false;
long size = 0, total = 0;
fcounter.FileFound +=
(o, e) =>
{
if (!e.IsDirectory)
{
Interlocked.Increment(ref total);
size += e.Length;
}
};
Stopwatch sw = Stopwatch.StartNew();
fcounter.Find();
Console.WriteLine("Enumerated {0:n0} files totaling {1:n0} bytes in {2:n3} seconds.",
total, size, sw.Elapsed.TotalSeconds);
return size;
}
For my local C:\ drive this outputs the following:
Enumerated 810,046 files totaling 307,707,792,662 bytes in 232.876 seconds.
Your mileage may vary by drive speed, but this is the fastest method I've found of enumerating files in managed code. The event parameter is a mutating class of type FindFile.FileFoundEventArgs so be sure you do not keep a reference to it as it's values will change for each event raised.
I know this is old, but... Another option may be to use the FileSystemWatcher like so:
void SomeMethod()
{
System.IO.FileSystemWatcher m_Watcher = new System.IO.FileSystemWatcher();
m_Watcher.Path = path;
m_Watcher.Filter = "*.*";
m_Watcher.NotifyFilter = m_Watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
m_Watcher.Created += new FileSystemEventHandler(OnChanged);
m_Watcher.EnableRaisingEvents = true;
}
private void OnChanged(object sender, FileSystemEventArgs e)
{
string path = e.FullPath;
lock (listLock)
{
pathsToUpload.Add(path);
}
}
This would allow you to watch the directories for file changes with an extremely lightweight process, that you could then use to store the names of the files that changed so that you could back them up at the appropriate time.
(copied this piece from my other answer in your other question)
Show progress when searching all files in a directory
Fast files enumeration
Of course, as you already know, there are a lot of ways of doing the enumeration itself... but none will be instantaneous. You could try using the USN Journal of the file system to do the scan. Take a look at this project in CodePlex: MFT Scanner in VB.NET... it found all the files in my IDE SATA (not SSD) drive in less than 15 seconds, and found 311000 files.
You will have to filter the files by path, so that only the files inside the path you are looking are returned. But that is the easy part of the job!
Maybe it will be helpfull for you.
You could use "DirectoryInfo.EnumerateFiles" method and handle UnauthorizedAccessException as you need.
using System;
using System.IO;
class Program
{
static void Main(string[] args)
{
DirectoryInfo diTop = new DirectoryInfo(#"d:\");
try
{
foreach (var fi in diTop.EnumerateFiles())
{
try
{
// Display each file over 10 MB;
if (fi.Length > 10000000)
{
Console.WriteLine("{0}\t\t{1}", fi.FullName, fi.Length.ToString("N0"));
}
}
catch (UnauthorizedAccessException UnAuthTop)
{
Console.WriteLine("{0}", UnAuthTop.Message);
}
}
foreach (var di in diTop.EnumerateDirectories("*"))
{
try
{
foreach (var fi in di.EnumerateFiles("*", SearchOption.AllDirectories))
{
try
{
// Display each file over 10 MB;
if (fi.Length > 10000000)
{
Console.WriteLine("{0}\t\t{1}", fi.FullName, fi.Length.ToString("N0"));
}
}
catch (UnauthorizedAccessException UnAuthFile)
{
Console.WriteLine("UnAuthFile: {0}", UnAuthFile.Message);
}
}
}
catch (UnauthorizedAccessException UnAuthSubDir)
{
Console.WriteLine("UnAuthSubDir: {0}", UnAuthSubDir.Message);
}
}
}
catch (DirectoryNotFoundException DirNotFound)
{
Console.WriteLine("{0}", DirNotFound.Message);
}
catch (UnauthorizedAccessException UnAuthDir)
{
Console.WriteLine("UnAuthDir: {0}", UnAuthDir.Message);
}
catch (PathTooLongException LongPath)
{
Console.WriteLine("{0}", LongPath.Message);
}
}
}
You can use this to get all directories and sub-directories. Then simply loop through to process the files.
string[] folders = System.IO.Directory.GetDirectories(#"C:\My Sample Path\","*", System.IO.SearchOption.AllDirectories);
foreach(string f in folders)
{
//call some function to get all files in folder
}
i made C# program that open and show xml files.
how to make (on my program installation) that all *.xml files
that in my computer will opened with my program ?
thanks in advance
As detailed in this question, you need to change the value of the registry key HKEY_CLASSES_ROOT\xmlfile\shell\open\command on the user's machine.
This could be achieved programatically by code such as (untested):
// Get App Executable path
string appPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
RegistryKey rkShellOpen = Registry.ClassesRoot.OpenSubKey(#"xmlfile\shell\open", true);
rkShellOpen.SetValue("command", appPath);
I think he is wanting a way to search the hard drive for all xml files, so that he can then manage them in some sort of tree for easy opening and closing.
You could do something similar to this...
void RecursiveDirectorySearch(string sDir, string patternToMatch)
{
// Where sDir would be the drive you want to search, I.E. "C:\"
// Where patternToMatch has the extension, I.E. ".xml"
try
{
foreach (string d in Directory.GetDirectories(sDir))
{
foreach (string f in Directory.GetFiles(d, txtFile.Text))
{
if(f.Contains(patternToMatch)
{
lstFilesFound.Items.Add(f);
}
}
DirSearch(d);
}
}
catch (System.Exception excpt)
{
Console.WriteLine(excpt.Message);
}
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to recursively list all the files in a directory in C#?
I want to list the "sub-path" of files and folders for the giving folder (path)
let's say I have the folder C:\files\folder1\subfolder1\file.txt
if I give the function c:\files\folder1\
I will get
subfolder1
subfolder1\file.txt
You can use the Directory.GetFiles method to list all files in a folder:
string[] files = Directory.GetFiles(#"c:\files\folder1\",
"*.*",
SearchOption.AllDirectories);
foreach (var file in files)
{
Console.WriteLine(file);
}
Note that the SearchOption parameter can be used to control whether the search is recursive (SearchOption.AllDirectories) or not (SearchOption.TopDirectoryOnly).
Try something like this:
static void Main(string[] args)
{
DirSearch(#"c:\temp");
Console.ReadKey();
}
static void DirSearch(string dir)
{
try
{
foreach (string f in Directory.GetFiles(dir))
Console.WriteLine(f);
foreach (string d in Directory.GetDirectories(dir))
{
Console.WriteLine(d);
DirSearch(d);
}
}
catch (System.Exception ex)
{
Console.WriteLine(ex.Message);
}
}
String[] subDirectories;
String[] subFiles;
subDirectories = System.IO.Directory.GetDirectories("your path here");
subFiles = System.IO.Directory.GetFiles("your path here");
Use the System.IO.Directory class and its methods
I remember solving a similar problem not too long ago on SO, albeit it was in VB. Here's the question.