I am currently developing a C# application to search a file in the computer. The GUI has two text fields: one for input(the name for the file to be searched) and one for displaying the path to the file (if it's found).
Now, the problem is that my application is skipping my logical C: drive. Here is some piece of code:
foreach (string s in Directory.GetLogicalDrives() )
{
if (list.Count == 0)
{
foreach (string f in Directory.GetFiles(s, file))
{
textBox2.Text = f;
list.Add(f);
}
if (list.Count == 0)
{
search(s);
}
}
}
And the search method:
private void search(string sDir)
{
try
{
foreach (string d in Directory.GetDirectories(sDir))
{
if (list.Count == 0)
{
Console.WriteLine(d);
foreach (string f in Directory.GetFiles(d, file))
{
textBox2.Text = f;
list.Add(f);
}
if (list.Count == 0)
{
search(d);
}
}
}
}
catch (System.Exception excpt)
{
Console.WriteLine(excpt.Message);
}
}
Here is some output:
C:\$Recycle.Bin
C:\$Recycle.Bin\S-1-5-21-1794489696-3002174507-1726058468-1000
C:\Config.Msi
C:\de cautat
C:\de cautat\database
C:\de cautat\fut_bot
C:\de cautat\helper
C:\de cautat\images
C:\de cautat\itemiinfo
C:\de cautat\JSONs
C:\de cautat\JSONs\PLAYER
C:\de cautat\JSONs\USER
C:\de cautat\requests
C:\Documents and Settings
A first chance exception of type 'System.UnauthorizedAccessException' occurred in mscorlib.dll
Access to the path 'C:\Documents and Settings' is denied.
D:\$RECYCLE.BIN
D:\$RECYCLE.BIN\S-1-5-21-1794489696-3002174507-1726058468-1000
D:\$RECYCLE.BIN\S-1-5-21-2637989945-465084399-3498881169-1000
etc
Can anyone help me and tell what is the problem when accesing those folders? Thanks!
Note: I am using Microsoft Visual Studio 2010 on Windows 7 x64 (.NET Framework 2.0).
The problem is you are hitting a folder you do not have read privileges to. You will need to either run your program as administrator or will need to have it skip over files and folders you do not have read rights to. Using Directory.EnumerateFiles will let you simplify your code and it should not try to open folders it does not have read rights to.
foreach (string s in Directory.GetLogicalDrives())
{
if (list.Count == 0)
{
foreach (string f in Directory.EnumerateFiles(s, file, SerchOption.AllDirectories))
{
try
{
textBox2.Text = f;
list.Add(f);
}
catch (System.Exception excpt)
{
Console.WriteLine(excpt.Message);
}
}
}
}
Move your try catch into the foreach (string d in Directory.GetDirectories(sDir)) loop so it continues to process on error.
I know it's an old thread, but it ranked quite high in Google, so I thought I would clarify a free things for others that stumble across it..
First of all: the programme cannot access C:\Documents and Settings because it doesn't exist on a windows 7. It's a symbolic link without any actual content except a pointer. But the programme doesn't know that since it sees it as a regular directory. That is why it fails...
I would wrap the whole thing in a try, catch (without any action in the catch part)..
Hope it helps someone from trying any of the proposed answers..
Related
I am trying to program a Windows service that automatically deletes the file from a specific folder. But I encountered an error:
Cannot access the file. The file is currently in use by another process/program.
I tried to do the following, but still get the same error.
string[] files = Directory.GetFiles(#"C:\Users\ASIM\AppData\Local\Temp");
// string[] directories = Directory.GetDirectories(#"C:\Users\ASIM\AppData\Local\Temp", "p*", SearchOption.TopDirectoryOnly);
if (files != null || files.Length != 0)
{
{
foreach (string f in files)
{
try
{
File.Delete(f);
}
finally { }
}
}
}
so how to skip deleting a file if it is in use?
There is no point checking if the file is deletable before deleting it because there will be a small window of opportunity between your check and the delete, where another process will open the file. The best idea is to try and delete it and handle the exception if it occurrs.
Your try/finally should be try/catch with the appropriate exception:
try
{
File.Delete(f);
}
catch(IOException ex)
{
// Probably some logging here
}
trying to write a small windows application for my company. the part i am stuck at the moment is trying to search the computer for ".myox" files (or say any file type). Below pasted is the code i have worked out. I am an amateur programmer trying to get started with coding. The issue am having at the moment with the code below is its skipping almost all locations on the computer with the exception coming up as "access denied". I have run the VS as admin, and i am an admin on the computer as well. Not sure what i am missing, but if someone can point me in the right direction, that would be amazing.
private void FindAllFiles()
{
int drvCount;
int drvSearchCount = 0;
DriveInfo[] allDrives = DriveInfo.GetDrives();
drvCount = allDrives.Count();
foreach (DriveInfo dr in allDrives)
{
lbAllFiles.Items.Clear();
drvSearchCount++;
//removable drives
if (!dr.IsReady)
break;
foreach (string dir in Directory.GetDirectories(dr.ToString()))
{
try
{
foreach (string files in Directory.GetFiles(dir, "*.myox"))
{
lbAllFiles.Items.Add(files);
}
}
catch (Exception Error)
{
}
}
if (drvSearchCount == drvCount)
break;
}
MessageBox.Show("Done searching your computer");
}
Thanks in Advance.
-Manu
I see few "potential" issues and will list them below.
First is that you're doing this on main ( UI ) thread which will block whole application giving you no feedback about current state. You can use Thread to get rid of this problem. Outcome from this operation will produce another issue which is accessing lbAllFiles because ( as i think ) it's part of the UI. You can easily get rid of this problem making a List<string> that can be filled during FindAllFiles operation and then assigned into lbAllFiles.Items.
Second issue is :
foreach (string files in Directory.GetFiles(dir, "*.myox"))
{
lbAllFiles.Items.Add(files);
}
Directory.GetFiles(...) will return only the files that are matching your pattern parameter so you can simply do :
var files = Directory.GetFiles(dir, "*.myox");
if ( files != null && files.Length > 0 )
lblAllFiles.Items.AddRange(files);
And finaly to get ( or check ) permission you can Demand() permissions as I've posted in the comment :
foreach (string dir in Directory.GetDirectories(dr.ToString()))
{
FileIOPermission permission = new FileIOPermission(FileIOPermissionAccess.Read, dir);
try
{
permission.Demand();
var files = Directory.GetFiles(dir, "*.myox");
if ( files != null && files.Length > 0 )
lblAllFiles.Items.AddRange(files);
}
catch (Exception Error)
{
}
}
Let me know if that helped you. If not I'll try to update my answer with another solution.
One thing i noticed in your code, is that you're not navigating through ALL directories and sub-directories. For that, where you call the GetDirectories function, not only send the path, but use the enumerator Alldirectories:
foreach (string dir in Directory.GetDirectories(dr.ToString(),System.IO.SearchOption.AllDirectories))
I've got quite a big problem. I have a drive with nearly 600,000 files on it within various levels of folders and I need to create an SQL table with a list of filepaths but not for all of the files.
The structure is:
J:/
J:/test
J:/XCR
J:/554
J:/B1
I need to keep all the files in the folders test & XCR but only files within certain directories in the other folders. I have a list of these folders uploaded to an SQL table.
I've written a recursive function that uses Directory.GetFiles() and Directory.GetDirectories but I encounter problems when the directory levels increase and the filenames get longer. I've also have the following error that I'm not sure about...
System.IO.IOException: Element not found. at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath
I think I'm going about this the wrong way. Can someone point me in the right direction?
Any help would be greatly appreciated!
EDIT:
public void copyFiles(string dirName, int level)
{
try
{
if (level == 1)
{
foreach (string f in Directory.GetFiles(dirName))
{
Response.Write(f + "<br />");
// insTbl.Rows.Add(f);
}
}
foreach (string d in Directory.GetDirectories(dirName))
{
foreach (string f in Directory.GetFiles(d))
{
Response.Write(f + "<br />");
// insTbl.Rows.Add(f);
}
level++;
copyFiles(d,level);
}
}
catch (Exception ex)
{
Response.Write(ex);
}
}
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.
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);
}
}