Exclude System Hardlinks from File.Copy - c#

So my problem is that I want to export my user account.
But inside C:\%user%\AppData\Local\ are System Hardlinks e.g.: Application Data which I obviously have no right to use them.
Is there a way to exclude those System Hardlinks from the copying process?

I'm not sure what you mean with hard links, but this might help you
foreach (var dir in new DirectoryInfo(#"c:\users\xxxxxx\AppData\Local").GetDirectories())
{
if (dir.Attributes.HasFlag(FileAttributes.ReparsePoint))
{
Console.WriteLine(dir.Name + " is symbolic, skip it");
}
else
{
//do your copy here
}
}

So I fixed the issue with Exception handling, doing it this way:
FileInfo[] sourceFiles = null;
try {
sourceFiles = new DirectoryInfo(sourcePath).GetFiles();
} catch (Exception ex) {
WriteLog(LogPath, ex + "");
return;
}
Since I'm a bit new to exception handling, I couldn't work it out for the first few hours on this problem.

Related

Ignore UnauthorizedAccessException while getting Files and SubDirectories of a directory

I am using the code below to get the Files and the SubDirectories of a directory and then populate a TreeView control. I am getting an UnauthorizedAccessException exception. I tried to handle it using a try and catch but in vain...
void GetFilesAndSubDirs(DirectoryInfo root, TreeNodeCollection nodes)
{
FileInfo[] files = null;
DirectoryInfo[] subDirs = null;
try
{
files = root.GetFiles("*.*");
subDirs = root.GetDirectories();
}
catch (UnauthorizedAccessException e)
{
MessageBox.Show(e.Message);
}
catch (DirectoryNotFoundException e)
{
MessageBox.Show(e.Message);
}
TreeNode parent = FindNode(root.Name, nodes);
if (files != null)
{
foreach (FileInfo fiInfo in files)
{
TreeNode fileNode = new TreeNode(fiInfo.Name);
fileNode.ImageIndex = 1;
fileNode.SelectedImageIndex = 1;
parent.Nodes.Add(fileNode);
}
}
if (subDirs != null)
{
foreach (DirectoryInfo dirInfo in subDirs)
{
TreeNode dirNode = new TreeNode(dirInfo.Name);
dirNode.ImageIndex = 0;
dirNode.SelectedImageIndex = 0;
parent.Nodes.Add(dirNode);
GetFilesAndSubDirs(dirInfo, parent.Nodes);
}
}
}
UPDATE #1
When I comment the line of the recursive call, it works just fine.
Is this expected behavior or should you have rights to access this directory?
Have you tried running Visual Studio as an administrator? You as a user might have rights to view it but the application does not necessarily do.
Although the answer and comment are correct to some degree. They're not handling the issue at hand; you "try to catch but in vain" - of course it is in vain - you made it so.
At first you try to get the directory which is named root - you'll get the exception and still try to continue with that same "root" variable, which will be null or at least not set correctly.
When you receive an error message (and for some reason just relate that message to the user directly) you should stop the process. You have an exception (which is by all means a reason to stop processing - it's an unexpected error) - you could never assume the process after the exception is going to run as expected.
I suggest you (in this case) show the messagebox and "return" and don't go forward into the process.
Although it's not holy or sacred - I suggest you'd read up on "defensive programming (C#)"
EDIT #1
Alter the beginning of the method along the line of this:
void GetFilesAndSubDirs(DirectoryInfo root, TreeNodeCollection nodes)
{
FileInfo[] files = null;
DirectoryInfo[] subDirs = null;
try
{
files = root.GetFiles("*.*");
subDirs = root.GetDirectories();
}
catch (UnauthorizedAccessException e)
{
MessageBox.Show(e.Message);
return; // unexpected behavior : notice to user and stop
}
catch (DirectoryNotFoundException e)
{
MessageBox.Show(e.Message);
return; // unexpected behavior : notice to user and stop
}

Deleting Files with c#

I´m making a program to delete some files that I have on my PC. But when I try to do it, I get some error messages like this:
If you are attempting to access a file, make sure it is not ReadOnly.
Make Sure you have sufficient privileges to access this resource.
Get general Help for this exception.
foreach (string subFich in SubFicheiros)
{
listBox.Items.Add("- Deleting File: " + subFich.Substring(Pasta.Length + 1, subFich.Length - Pasta.Length - 1));
ficheirosEncontrador++;
}
try
{
Directory.Delete(Pasta, true);
}
catch (IOException)
{
Thread.Sleep(0);
//The Message Error appears here on this code right below:
Directory.Delete(Pasta, true);
}
catch (UnauthorizedAccessException)
{
Directory.Delete(Pasta, true);
}
}
I would like to get some help with this.
How do i ask the user, to let me get the privilegies to delete it.
Well.. what your code doing is: You're deleting the directory and if it gives any exception then you're again trying to do the same step where you got exception.
First of all error is because files are set to read only or because you dont have enough rights to delete the directory (or probably some process is using the files which you are trying to delete)
foreach (string subFich in SubFicheiros)
{
listBox.Items.Add("- Deleting File: " + subFich.Substring(Pasta.Length + 1, subFich.Length - Pasta.Length - 1));
ficheirosEncontrador++;
}
try
{
var di = new DirectoryInfo(Pasta);
di.Attributes &= ~FileAttributes.ReadOnly;
Directory.Delete(Pasta, true);
}
catch (Exception EE)
{
MessageBox.Show("Error: "+ EE.toString());
}
if this code still doesn't work check if you have admin rights to delete that folder
Sounds like your file is read-only, or you do not have the right to remove the file you want based on your user login.

Can not delete files from Recent folder

I am writing a Software that can delete Temporary files, Prefetch data, files in Recent folder and so on. My problem is I can delete files from Temp folder successfully, but when I try for Recent folder, an exception is thrown, "Access to path...is denied".
PS: According to some other questions, I have set File attributes to normal, but still no luck. Please help me on this issue. For your better understand, I put some code here:
public Boolean CleanRecentData()
{
isAllClean = true;
String SysRecentPath = System.Environment.GetEnvironmentVariable("USERPROFILE") + "\\Recent";
DirectoryInfo SysRecDir = new DirectoryInfo(SysRecentPath);
File.SetAttributes(SysRecentPath, FileAttributes.Normal);
foreach (FileInfo fi in SysRecDir.GetFiles()) //Access Denied
//Exception is thrown here
{
try
{
fi.Delete();
}
catch (Exception ex)
{
recentLogLines.AppendLine(ex.Message);
isAllClean = false;
}
}
foreach (DirectoryInfo dir in SysRecDir.GetDirectories())
{
try
{
dir.Delete(true);
}
catch (Exception ex)
{
recentLogLines.AppendLine(ex.Message);
isAllClean = false;
}
}
return isAllClean;
}
Are you able to access the Recent folder via Windows Explorer?
You could go ahead and change the permissions in your system, but NOT in your users systems.
Therefore you could handle this exception condition in two ways.
You need to check if you have file access before accessing, using FileIOPermission but this might be redundant and wasteful if you are doing it on too many files.
Just try to open the file and put your effort into a good exception handler if it fails
Reference

C# File Permission Exclusion

I was wondering if there is a way to solve the issue I have with this code:
DriveInfo[] dDrives = DriveInfo.GetDrives();
foreach(DriveInfo dDrive in dDrives)
{
try
{
string sDrive = dDrive.ToString();
string[] sSearch = Directory.GetFiles(sDrive, sFile, SearchOption.AllDirectories);
foreach(string sResult in sSearch)
{
textBox2.Text = sResult + Environment.NewLine;
}
}
catch
{
}
}
When it comes across a file that isn't accessible because of permissions, it will goto the catch and end. What I need it to do is if it comes across a file it can't access, go back to the try block and continue searching. Any help is much appreciated, thanks!
EDIT:
Removed original answer as incorrect.
See: UnauthorizedAccessException cannot resolve Directory.GetFiles failure for some suggested resolutions to your problem.
The code you have should work, though you really should rethink your logic, using exceptions for flow control is plain wrong.
This will work, though not best practice:
string sDrive = dDrive.ToString();
try
{
string[] sSearch = Directory.GetFiles(sDrive, sFile, SearchOption.AllDirectories);
}
catch {}
foreach(string sResult in sSearch)
{
textBox2.Text = sResult + Environment.NewLine;
}
Where exactly are you accessing files? I only see a call to list file names (Directory.GetFiles), and listing of the file names returned.

How to delete files while Traversing folder tree

I am not sure if I am doing this correctly or if my logic is correct.
I am trying to go down a folder structure delete files older than a certain number of days, this part I have correctly implemented, delete empty folders.
Can all this be done in one loop?
Where do I do the folder delete?
I want to delete empty folders up to 3 or 4 level down.
private static void TraverseTree(System.IO.DirectoryInfo folder, double days)
{
Stack<string> dirs = new Stack<string>();
if (!folder.Exists)
throw new ArgumentException();
dirs.Push(folder.FullName);
while (dirs.Count > 0)
{
string currentDir = dirs.Pop();
string[] subDirs;
try
{
subDirs = System.IO.Directory.GetDirectories(currentDir);
}
// An UnauthorizedAccessException exception will be thrown if we do not have
// discovery permission on a folder or file. It may or may not be acceptable
// to ignore the exception and continue enumerating the remaining files and
// folders. It is also possible (but unlikely) that a DirectoryNotFound exception
// will be raised. This will happen if currentDir has been deleted by
// another application or thread after our call to Directory.Exists. The
// choice of which exceptions to catch depends entirely on the specific task
// you are intending to perform and also on how much you know with certainty
// about the systems on which this code will run.
catch (UnauthorizedAccessException e)
{
Console.WriteLine(e.Message);
continue;
}
catch (System.IO.DirectoryNotFoundException e)
{
Console.WriteLine(e.Message);
continue;
}
string[] files = null;
try
{
files = System.IO.Directory.GetFiles(currentDir);
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine(e.Message);
continue;
}
catch (System.IO.DirectoryNotFoundException e)
{
Console.WriteLine(e.Message);
continue;
}
// Perform the required action on each file here.
// Modify this block to perform your required task.
foreach (string file in files)
{
try
{
// Perform whatever action is required in your scenario.
System.IO.FileInfo fi = new System.IO.FileInfo(file);
Console.WriteLine("{0}: {1}, {2}", fi.Name, fi.Length, fi.CreationTime);
// Delete old files
if (fi.LastWriteTime < DateTime.Now.AddDays(-days))
fi.Delete();
}
catch (System.IO.FileNotFoundException e)
{
// If file was deleted by a separate application
// or thread since the call to TraverseTree()
// then just continue.
Console.WriteLine(e.Message);
continue;
}
}
// Push the subdirectories onto the stack for traversal.
// This could also be done before handing the files.
foreach (string str in subDirs)
dirs.Push(str);
}
}
Code is from MSDN.
A recursive approach would probably be cleaner.
private static void DeleteOldFilesAndFolders(string path)
{
foreach (string directory in System.IO.Directory.GetDirectories(path))
{
DeleteOldFilesAndFolders(directory);
// If the directory is empty and old, delete it here.
}
foreach (string file in System.IO.Directory.GetFiles(path))
{
// Check the file's age and delete it if it's old.
}
}
Something that I notice about your code is that the dozens of lines of "mechanism" for walking the tree structure completely overwhelms the two lines of code that actually do the work. That makes it hard to read, understand, change, debug and maintain this code.
Here's what I would do instead.
You have only three high-level operations in your program: (1) get all the files, (2) filter to find the ones to delete, (3) delete each file. So write a program which does each of those in one statement.
For the first operation, I would factor out the mechanism above into its own function: a function which implements, say, IEnumerable, and all it does is keeps on yielding out information about files. It doesn't do anything with them; its only purpose is to keep spitting out file infos.
Once you have that mechanism then you can start writing queries on top of that sequence to attain the second operation. The third operation then follows directly from the second.
In short, the main line of your program should look something like this:
var allFiles = TraverseFolder(folder);
var filesToDelete = from file in allFiles where IsOld(file) select file;
foreach(var fileToDelete in filesToDelete) Delete(fileToDelete);
Is that clear?
There is almost the same question here:
How to delete all files and folders in a directory?
This is delete by name, but you could check other properties.
Here is a more general solution to the problem which gives you a file system walker implemented non-recursively as IEnumerable.
for which your solution can probably be implemented as:
List<string> directoriesToDelete = new List<string>();
DirectoryWalker walker = new DirectoryWalker(#"C:\pathToSource\src",
dir => {
if (Directory.GetFileSystemEntries(dir).Length == 0) {
directoriesToDelete.Add(dir);
return false;
}
return true;
},
file => {
if (FileIsTooOld(file)) {
return true;
}
return false;
}
);
foreach (string file in walker)
File.Delete(file);
foreach (string dir in directoriesToDelete)
Directory.Delete(dir);
I enhanced John's solution, implementing missing code, error handling and checks:
/* Given a directory path and a datetime,
* recursively delete all files and directories contained in such directory
* (given directory included) that are younger than the given date.
*/
private bool DeleteDirectoryTree(string dir, DateTime keepFilesYoungerThan)
{
//checks
if (String.IsNullOrEmpty(dir) || !Directory.Exists(dir))
return false;
//recurse on children directories
foreach (string childDir in Directory.GetDirectories(dir))
DeleteDirectoryTree(childDir, keepFilesYoungerThan);
//loop on children files
foreach (string file in Directory.GetFiles(dir))
{
//calculate file datetime
DateTime fileDT = new DateTime(Math.Max(File.GetCreationTime(file).Ticks, File.GetLastWriteTime(file).Ticks));
//if file is old, delete it
if (fileDT <= keepFilesYoungerThan)
try
{
File.Delete(file);
Log("Deleted file " + file);
}
catch (Exception e)
{
LogError("Could not delete file " + file + ", cause: " + e.Message);
}
}
//if this directory is empty, delete it
if (!Directory.EnumerateFileSystemEntries(dir).Any())
try
{
Directory.Delete(dir);
Log("Deleted directory " + dir);
}
catch (Exception e)
{
LogError("Could not delete directory " + dir + ", cause: " + e.Message);
}
return true;
}

Categories