I am having a bit of trouble with this method.
When I loop through the FileInfo type objects in dragDropFiles and add each individually to the CLB I get the FullName property (full path to file, which is what I need) returned when the item is checked.
However with the hotFolderFiles instead of the path it gives me just the file name.
I do not understand this because they are adding the same object type in the same manner.
(I also tried getting the FileInfo for hot folder files using the DirectoryInfo instead of my Dictionary with same results)
Why is this behavior inconsistent?
(and how can I get it to return the fileInfo fullName instead of Name?)
public frmFilesFound(string hotFolderPath, Dictionary<string, FileInfo> dragDropFiles, Dictionary<string, FileInfo> hotFolderFiles, bool ReadOnly)
{
try
{
InitializeComponent();
readOnly = ReadOnly;
btnSelectAll.Visible = true;
clbSelectFilesFound.Visible = true;
clbSelectFilesFound.FormattingEnabled = true;
clbSelectFilesFound.Format += (s, e) => { e.Value = string.Format("{0}", ((FileInfo)e.ListItem).Name); };
foreach (FileInfo fileInfo in dragDropFiles.Values)
{
if (!clbSelectFilesFound.Items.Contains(fileInfo))
{
try
{
// If file not already present, add it to listbox
clbSelectFilesFound.Items.Add(fileInfo);
}
catch (Exception ex) { MessageBox.Show("Error: " + ex.Message); }
}
}
//intended to be hot folder path
if (!String.IsNullOrEmpty(hotFolderPath))
{
DirectoryInfo dirInfo = new DirectoryInfo(hotFolderPath);
foreach (FileInfo fileInfo in dirInfo.GetFiles())
//foreach (FileInfo fileInfo in hotFolderFiles.Values)
{
if (!clbSelectFilesFound.Items.Contains(fileInfo))
{
try
{
clbSelectFilesFound.Items.Add(fileInfo);
}
catch (Exception ex) { MessageBox.Show("Error: " + ex.Message); }
}
}
}
lblDisplayedSelectMessage.Text = "More than one file is waiting. Please select the files you would like to use.";
}
catch (Exception ex)
{ MessageBox.Show(ex.ToString()); }
}
That is because the DirectoryInfo.GetFiles method only fills in the name of the file, and not the full path.
Try this formatter if you only want to show the name of the file in all cases:
clbSelectFilesFound.Format += (s, e) => {
e.Value = Path.GetFileNameWithoutExtension(((FileInfo)e.ListItem).Name);
};
Why don't you just always Add(fileInfo.FullName) ?
Related
I want to get the full path of the file named wampmanager.conf on disk D. I coded the following for this:
private static string Scan(string path, string file)
{
try
{
foreach (var dir in Directory.EnumerateDirectories(path))
{
foreach (var fl in Directory.EnumerateFiles(dir, file))
{
if (!string.IsNullOrEmpty(fl))
{
return fl;
}
}
}
}
catch (Exception)
{
// ignored
}
return null;
}
var wmc = Scan(#"D:\", "wampmanager.conf");
MessageBox.Show(wmc);
It always returns null even though the wampmanager.conf file exists on the disk D. I guess it goes to a directory like d:\recovery\ that I don't have access to, then it crashes into a catch and returns null. But when I don't use try catch I always get access authorization error. How can I deal with this problem?
For each directory you must use SearchOption.AllDirectories to Includes the current directory and all its subdirectories in a search operation. Try this function:
private static string Scan(string path, string file)
{
foreach (var dir in Directory.EnumerateDirectories(path))
try
{
string[] files = Directory.GetFiles(dir, file, SearchOption.AllDirectories);
if (files.Length > 0)
{
return files[0];
}
}
catch (Exception e)
{
string s = e.Message;
}
return "not found!";
}
In constructor. filePathList is List
filePathList = SearchAccessibleFilesNoDistinct(rootDirectory, null).ToList();
And the SearchAccessibleFilesNoDistinct method
IEnumerable<string> SearchAccessibleFilesNoDistinct(string root, List<string> files)
{
if (files == null)
files = new List<string>();
if (Directory.Exists(root))
{
foreach (var file in Directory.EnumerateFiles(root))
{
string ext = Path.GetExtension(file);
if (!files.Contains(file) && ext == textBox2.Text)
{
files.Add(file);
}
}
foreach (var subDir in Directory.EnumerateDirectories(root))
{
try
{
SearchAccessibleFilesNoDistinct(subDir, files);
files.Add(subDir);
}
catch (UnauthorizedAccessException ex)
{
// ...
}
}
}
return files;
}
Then i make loop over the List filePathList
foreach (string file in filePathList)
{
try
{
_busy.WaitOne();
if (worker.CancellationPending == true)
{
e.Cancel = true;
return;
}
bool reportedFile = false;
for (int i = 0; i < textToSearch.Length; i++)
{
if (File.ReadAllText(file).IndexOf(textToSearch[i], StringComparison.InvariantCultureIgnoreCase) >= 0)
{
resultsoftextfound.Add(file + " " + textToSearch[i]);
if (!reportedFile)
{
numberoffiles++;
MyProgress myp = new MyProgress();
myp.Report1 = file;
myp.Report2 = numberoffiles.ToString();
myp.Report3 = textToSearch[i];
backgroundWorker1.ReportProgress(0, myp);
reportedFile = true;
}
}
}
numberofdirs++;
label1.Invoke((MethodInvoker)delegate
{
label1.Text = numberofdirs.ToString();
label1.Visible = true;
});
}
catch (Exception)
{
restrictedFiles.Add(file);
numberofrestrictedFiles ++;
label11.Invoke((MethodInvoker)delegate
{
label11.Text = numberofrestrictedFiles.ToString();
label11.Visible = true;
});
continue;
}
The problem is that in the catch part the restrictedFiles is just directories not files. Since filePathList contain files and directories and when it's trying to search in a directory it's getting to the catch. It's not a restricted file it's just directory and not file at all.
That's why i think the method SearchAccessibleFilesNoDistinct should return only files without directories as items.
For example in filePathList i see in index 0:
c:\temp
And in index 1
c:\temp\help.txt
The first item in index 0 will go to the catch as restricted file and the second item will not.
You have this loop to search search the subdirectories:
foreach (var subDir in Directory.EnumerateDirectories(root))
{
try
{
SearchAccessibleFilesNoDistinct(subDir, files);
files.Add(subDir); <--- remove this line
}
catch (UnauthorizedAccessException ex)
{
// ...
}
}
Remove the line that adds the subdirectory to the list of files. I've marked it in the code above.
Is it you looking for:
Directory.GetFiles(rootDir,"*.*", SearchOption.AllDirectories);
? Change . to mask form textbox only.
I have this function to delete files older than X amount of months, but it doesn't seem to delete them when I run the code: any guesses to why? When I check folder they are still there.
public static void deleteFiles()
{
try
{
DirectoryInfo ddi = new DirectoryInfo(destination_path);
if (ddi.Exists)
{
logFile.WriteLine("Log Entry: {0}", String.Format("{0:f}", dt) + System.Environment.NewLine);
foreach (var filename in ddi.EnumerateFiles())
{
FileInfo fi = new FileInfo(filename.ToString());//(destination_path + "\\" + filename);
if (fi.CreationTime < dt.AddMonths(-1) )
{
try
{
fi.Delete();
logFile.WriteLine("{0} was deleted successfully.", destination_path + "\\" + filename);
}
catch (Exception ex)
{
logFile.WriteLine("The deletion process failed: {0}", ex.Message);
}
}
}
logFile.WriteLine(String.Concat(Enumerable.Repeat("-------", 25)));
logFile.WriteLine();
}
}
catch (DirectoryNotFoundException ex)
{
logFile.WriteLine("Log Entry: {0}", String.Format("{0:f}", dt) + System.Environment.NewLine);
logFile.WriteLine("Could not delete files from specified directory: {0}", ex.Message);
logFile.WriteLine(String.Concat(Enumerable.Repeat("-------", 25)));
logFile.WriteLine();
}
}
As "Alessandro D'Andria" points out the documentation says:
https://msdn.microsoft.com/en-us/library/system.io.fileinfo.delete(v=vs.110).aspx
"If the file does not exist, this method does nothing."
This makes you think that the file delete has worked and is masking the issue.
If you look at the line:
foreach (var filename in ddi.EnumerateFiles())
this is returning a FileInfo object which is basically a link to the file you want to delete.
But the next line, creates a new FileInfo object based on the filename.
FileInfo fi = new FileInfo(filename.ToString());
But the filename.ToString() is just returning the filename, there is no path information in here.
If you run through the debugger you will see that the fi object will have a pathname (fi.Directory) which is not your destination_path, but is in fact the path of your running executable.
Therefore, fi.Delete() does not actually find the file, so it does nothing (as per the documentation) but you still write a 'success' message to your log file and no exception is thrown, so you wrongly think that everything has worked.
So you actually want something more like this;
if (filename.CreationTime < dt.AddMonths(-1))
{
try
{
if (!filename.Exists)
throw new Exception("File does not exist");
filename.Delete();
WriteLine("{0} was deleted successfully.", destination_path + "\\" + filename);
}
catch (Exception ex)
{
WriteLine("The deletion process failed: {0}", ex.Message);
}
}
Try with the full path:
string path = Path.Combine(destination_path,filename.ToString());
FileInfo fi = new FileInfo(path);
Try something like.... (Ive left out some of your logic but the principle is the same....)
You don't need to use fileinfo as far as I can see.
{
string[] files = Directory.GetFiles(destination_path);
foreach (string filename in files)
{
if (File.Exists(destination_path + "\\" + filename))
{
try
{
File.Delete(destination_path + "\\" + filename);
}
catch (Exception ex)
{
logFile.WriteLine("The deletion process failed: {0}", ex.Message);
}
}
}
}
I created folder with no name using (alt + 0160) while I search with c# it stuck in infinite loop and create exception of "Stack Over Flow"
My method is given which i am using for Search.
public void getTotatFoldersAndFilesCount(DirectoryInfo objDirs, System.ComponentModel.BackgroundWorker worker)
{
try{
if (worker.CancellationPending == true)
{ return; }
FileInfo[] objFiles = null;
numFoldersCount++;
if ((objDirs.Attributes & FileAttributes.ReparsePoint) != 0)
{ return;}
try
{
objFiles = objDirs.GetFiles(searchPatteren);
}
catch (UnauthorizedAccessException e)
{ }
catch (System.IO.DirectoryNotFoundException e)
{ }
catch (System.StackOverflowException ex)
{ }
if (objFiles != null)
{
foreach (FileInfo objFile in objFiles)
{
numFilesCount++;
}
foreach (DirectoryInfo objDir in objDirs.GetDirectories())
{
getTotatFoldersAndFilesCount(objDir, worker);
}
}
objFiles = null;
}
catch (Exception ex)
{
ErrorLogger("Error in Total Folder and File Count - Directory Name: " + objDirs.Name);
ErrorLogger(ex.Message);
}
}
This can be avoided by a simple change:
In the directory enumeration code, change the for loop to:
foreach (DirectoryInfo objDir in new DirectoryInfo(objDirs.FullName + Path.DirectorySeparatorChar).GetDirectories(searchPatteren))
{
getTotatFoldersAndFilesCount(objDir, worker);
}
When enumerating blank folder, the directory name is a white space. When initializing the DirectoryInfo object, the whitespace is trimmed causing the function to always loop trough the same directory. Adding the DirectorySeperatorChar ("\") in most of the cases solves the issue.
I google this question and find the solution by given link.
by adding single slash at the end of the directory path it will not go into infinite loop.
first i was doing this.
getTotatFoldersAndFilesCount(objDir, worker);
and now replace it with this. It solved my problem,
DirectoryInfo nDI = new DirectoryInfo(objDir.FullName + #"\");
getTotatFoldersAndFilesCount(nDI, worker);
link is given.
http://tiku.io/questions/4277530/getdirectories-fails-to-enumerate-subfolders-of-a-folder-with-255-name
I have below code to retrieve all pdf files from MyComputer. But i am getting error like below. Is it possible to retrive all pdf files from one computer using C# code.
string path = Environment.GetFolderPath(Environment.SpecialFolder.MyComputer);
System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(path); // Error : The path is not of a legal form.
IEnumerable<System.IO.FileInfo> fileList = dir.GetFiles("*.pdf", System.IO.SearchOption.AllDirectories);
You can get all drives and then get all files.
EDIT: You can also use Directory.EnumerateFiles method which would let you get the file path and you can add that in your list. This would give you a List<string> for all the file paths. Like:
List<string> filePathList = new List<string>();
foreach (DriveInfo drive in DriveInfo.GetDrives())
{
try
{
var filenames = Directory.EnumerateFiles(drive.Name, "*.pdf", SearchOption.AllDirectories);
foreach (string fileName in filenames)
{
filePathList.Add(fileName);
}
}
catch (FieldAccessException ex)
{
//Log, handle Exception
}
catch (UnauthorizedAccessException ex)
{
//Log, handle Exception
}
catch (Exception ex)
{
//log , handle all other exceptions
}
}
Old Answer.
List<FileInfo> fileList = new List<FileInfo>();
foreach (var drive in System.IO.DriveInfo.GetDrives())
{
try
{
DirectoryInfo dirInfo = new DirectoryInfo(drive.Name);
foreach (var file in dirInfo.GetFiles("*.pdf", SearchOption.AllDirectories))
fileList.Add(file);
}
catch (FieldAccessException ex)
{
//Log, handle Exception
}
catch (UnauthorizedAccessException ex)
{
//Log, handle Exception
}
catch (Exception ex)
{
//log , handle all other exceptions
}
}
You can use the System.IO.DriveInfo class to loop through all drives available on the machine (call DriveInfo.GetDrives() to get a list of all drives). You will probably have to do this for each drive and combine the results from all of them. My guess with what is wrong with your current code is that giving it the MyComputer folder isn't enough to tell it to loop through all drives.