String userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
String dr = #"C:\Users\" + userName + #"\AppData\temp";
DirectoryInfo dir = new DirectoryInfo(#dr);
foreach (FileInfo file in dir.GetFiles())
{
file.Delete();
}
foreach (DirectoryInfo dire in dir.GetDirectories())
{
dire.Delete(true);
}
i was using this for deleting contents of a folder and that should be depending upon the username of the computer & i have provided the admin privilege
but when any file doesnt delete it stops working at that file. i want this process to complete
String userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
String dr = #"C:\Users\" + userName + #"\AppData\temp";
DirectoryInfo dir = new DirectoryInfo(#dr);
foreach (FileInfo file in dir.GetFiles())
{
try
{
file.Delete();
}
catch (IOException ex)
{//Log ex.message
continue;
}
}
foreach (DirectoryInfo dire in dir.GetDirectories())
{
try
{
dire.Delete();
}
catch (IOException ex)
{ //Log ex.message
continue;
}
}
Moreover, I suggest you better use Path.Combine() instead of concatenating Strings.
You'll have to add try/catch blocks around the file deletion statement, so that your loops continue even if you get an exception. I would recommend logging the list of files which have thrown exceptions when you call delete.
If one of the files won't delete, the call to file.Delete() will throw an exception.
If you want to handle it, you must wrap it in a try/catch as follows:
foreach (FileInfo file in dir.GetFiles())
{
try
{
file.Delete();
}
catch (IOException exception)
{
// Here you should log the exception.Message
}
}
Related
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 am trying to move a file if it contains a certain string, Code below
foreach (FileInfo file in files)
{
//reads the file contents
string MessageContents = File.ReadAllText(file.FullName);
//checks if the textwords are present in the file
foreach (string Keyword in textwords)
{
//if they are file is moved to quarantine messages
if (MessageContents.Contains(Keyword))
{
try
{
File.Move(file.FullName, File_quarantine);
}
catch (IOException cannot_Move_File)
{
MessageBox.Show("The process has failed: {0}", cannot_Move_File.ToString());
}
break;
}
//else it is moved To valid messages
else
{
try
{
File.Move(file.FullName, File_Valid);
}
catch (IOException cannot_Move_File)
{
MessageBox.Show("The process has failed: {0}", cannot_Move_File.ToString());
}
break;
}
}
}
}
However the process always fails with the error A first chance exception of type 'System.IO.IOException' occurred in mscorlib.dll
I am unsure as to why this is happening, any help would be greatly appreciated.
You still have a lock on the file, because you opened a stream to it. Move your logic of moving the file out of the reading of the file.
This should produce the desired result;
foreach (FileInfo file in files)
{
String messageContents = File.ReadAllText(file.FullName);
bool toQuarantine = textwords.Any(keyWord => messageContents.Contains(keyWord));
try
{
File.Move(file.FullName, toQuarantine ? File_quarantine : File_Valid);
}
catch (IOException cannot_Move_File)
{
MessageBox.Show("The process has failed: {0}", cannot_Move_File.ToString());
}
}
Basically you have a lock on the file. You can't move it while you're reading it.
If the files are relatively small, you can use a technique like this:
String content = File.ReadAllText( filename );
// at this point, the file is not locked, unlike the
// way it is in your question. you are free to move it
foreach (String keyword in keywords) {
if (content.Contains(keyword)) {
// Move file
break;
}
}
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.
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) ?