I am trying to search the C:\ drive for all files with a certain extension. I am using the following code which is working fine, however when it encounters an error the whole process stops rather than continuing with the scan. (running in backgroundworker, hence the invoke)
Private Sub ScanFiles(ByVal rootFolder As String, ByVal fileExtension As String)
'Determine if the current folder contains any sub folders
Dim subFolders() As String = System.IO.Directory.GetDirectories(rootFolder)
For Each subFolder As String In subFolders
ScanFiles(subFolder, fileExtension)
Next
For Each file As String In System.IO.Directory.GetFiles(rootFolder, fileExtension)
lb.BeginInvoke(New AddValue(AddressOf AddItems), file)
Next
End Sub
How can I make this code continue once an error is encountered?
If you don't have access to explore C drive itself then you are out of luck. but if you are getting an exception because you don't have access to some child folder in the tree, you can avoid it by putting your code in an try-catch block.
Private Sub ScanFiles(ByVal rootFolder As String, ByVal fileExtension As String)
'Determine if the current folder contains any sub folders '
try
Dim subFolders() As String = System.IO.Directory.GetDirectories(rootFolder)
For Each subFolder As String In subFolders
ScanFiles(subFolder, fileExtension)
Next
For Each file As String In System.IO.Directory.GetFiles(rootFolder, fileExtension)
lb.BeginInvoke(New AddValue(AddressOf AddItems), file)
Next
catch (Ex As UnauthorizedAccessException)
'Ignore Access Errors '
end try
End Sub
Related
I am working on a program that will move files to a database, text files to be exact. The user will have a starting directory and inside will multiple sub folders and files and so on. I want to go through each Folder and sub folder looking for the text files and add them accordingly to the database so it resembles a directory structure in a way. In the program the files are organized such as the folders are "Categories" that are displayed into a tree view.I am only adding the folder names(as Categories) that do contain text files and their subs and so forth. As well I need to figure out where to plug in the adding of the "Category". As of right now I am using a couple of listboxes for my output until I can get it all figured out.
lstfiles.Items.Add(Dir)
For Each file In System.IO.Directory.GetFiles(Dir)
Dim fi As System.IO.FileInfo = New IO.FileInfo(file)
If fi.Extension = ".txt" Then
If lstRootFolderFiles.Items.Contains(file) = False Then
lstfiles.Items.Add(file)
AddFile(file, Gennumber(9999))
End If
End If
Next
For Each folder In System.IO.Directory.GetDirectories(Dir)
lstfiles.Items.Add(folder)
For Each file In System.IO.Directory.GetFiles(folder)
Dim fi As System.IO.FileInfo = New IO.FileInfo(file)
If fi.Extension = ".txt" Then
If lstRootFolderFiles.Items.Contains(file) = False Then
lstfiles.Items.Add(file)
End If
End If
Next
Next
I have gotten so far as to iterate through the directory and get files but it returns folders that are empty. And I need to figure out where I need to put in my addcategory function. And also remember the last one that was added so they can be added as a subcategory.
I think I am making a big mess of it all, or over thinking the whole thing.
Any assistance or guidance would be appreciated.Thank you
The end result that I came up with was much different from my original posting, as it was my way of thinking of how it was going to work. I split up the two main functions. Retrieving the Folders and retrieving the files.
DirEx is the Import Directory, CatID is the Tag of the selected Treenode where the folders are going to added in.
Private Sub DirImport_GetSubDirectories(ByVal DirEx As String, ByVal CatID As Integer)
Try
Dim ClsData As New clsNoteData
'Set the DatabaseFile Property of the class
ClsData.Database = LoadedLibraryDatabase
' Get all subdirectories
Dim subdirectoryEntries() As String = Directory.GetDirectories(DirEx)
' Loop through them to see if they have any other subdirectories
Dim subdirectory As String
For Each subdirectory In subdirectoryEntries
'If the Directory is not Empty
If Not Directory.GetFileSystemEntries(subdirectory).Length = 0 Then
Dim di As DirectoryInfo = New DirectoryInfo(subdirectory)
'Creating Random Number
Dim NewCatID As Integer = GenNumber(9999)
'Call for a new Sub Category
ClsData.NewSubCategoryNode(LoadedLibraryDatabase, NewCatID, CatID, di.Name, -1)
'Get files in the current Directory
DirImport_GetFiles(subdirectory, NewCatID)
'Get the next set of Subfolders
DirImport_GetSubDirectories(subdirectory, NewCatID)
End If
Next
Catch ex As Exception
End Try
End Sub
Private Sub DirImport_GetFiles(ByVal DirEx As String, ByVal CatID As Integer)
Dim Files() As String = Directory.GetFiles(DirEx, "*.txt")
Dim file As String
For Each file In Files
Dim clsNoteData As New clsNoteData
Dim fi As FileInfo = New FileInfo(file)
clsNoteData.Database = LoadedLibraryDatabase
clsNoteData.NewNote_ID = GenNumber(99999)
clsNoteData.NewNote_CatID = CatID
clsNoteData.NewNote_Title = Path.GetFileNameWithoutExtension(file)
clsNoteData.NewNote(False, file)
Next
End sub
So here it is for anyone who may want to do something similar.
i'm trying to create a simple anti-cheat which detects external cheats in all the C drive, but i don't know how to check if a determinate file exists in all the C drive, any help?
Here is code that I adapted from How to: Iterate Through a Directory Tree. In the example, the FileExists() function returns True if the file bit32.txt is found anywhere on the C drive. Not all files and directories may be accessible. In that case, the function display the paths of these files and directories. You may want to adapt the code to do whatever you want in these cases.
Imports System.IO
Module Module1
Private Sub Main(ByVal args() As String)
Dim exists As Boolean = FileExists(New DriveInfo("C").RootDirectory, "bit32.txt")
End Sub
Private Function FileExists(ByVal root As DirectoryInfo, ByVal filename As String) As Boolean
Dim files() As FileInfo = Nothing
Dim subDirs() As DirectoryInfo = Nothing
' First, process all the files directly under this folder
Try
files = root.GetFiles("*.*")
Catch e As Exception
' This code just writes out the message and continues to recurse.
' You may decide to do something different here. For example, you
' can try to elevate your privileges and access the file again.
Console.WriteLine(e.Message)
End Try
If (Not (files) Is Nothing) Then
For Each fi As FileInfo In files
' In this example, we only access the existing FileInfo object. If we
' want to open, delete or modify the file, then
' a try-catch block is required here to handle the case
' where the file has been deleted since the call to TraverseTree().
'Console.WriteLine(fi.FullName);
If (fi.Name = filename) Then
Return True
End If
Next
End If
Try
' Now find all the subdirectories under this directory.
subDirs = root.GetDirectories
For Each dirInfo As DirectoryInfo In subDirs
' Resursive call for each subdirectory.
If FileExists(dirInfo, filename) Then
Return True
End If
Next
Catch e As Exception
' This code just writes out the message and continues to recurse.
' You may decide to do something different here. For example, you
' can try to elevate your privileges and access the file again.
Console.WriteLine(e.Message)
End Try
Return False
End Function
End Module
You can have an extension on DirectoryInfo that non-recursively iterates through the root directory looking for files.
<Extension()>
Public Iterator Function GetFilesDepthFirst(ByVal root As DirectoryInfo, ByVal Optional dirPattern As String = "*", ByVal Optional filePattern As String = "*.*") As IEnumerable(Of FileInfo)
Dim stack = New Stack(Of DirectoryInfo)()
stack.Push(root)
While stack.Count > 0
Dim current = stack.Pop()
Dim files = Enumerable.Empty(Of FileInfo)()
Dim dirs = Enumerable.Empty(Of DirectoryInfo)()
Try
dirs = current.EnumerateDirectories(searchPattern:=dirPattern)
files = current.EnumerateFiles(searchPattern:=filePattern)
Catch ex1 As UnauthorizedAccessException
Catch ex2 As PathTooLongException
End Try
For Each file As FileInfo In files
Yield file
Next
For Each dir As DirectoryInfo In dirs
stack.Push(dir)
Next
End While
End Function
You could then call it fairly easily like this:
Dim dInfo = New DirectoryInfo("C:\")
Dim matches = dInfo.GetFilesDepthFirst(filePattern:="somefile.dll")
Dim exists = matches.Any()
Also, the more specific you are at the starting directory, the quicker it will run. Usually searching from the root of C:\ is a very slow and bad idea.
I want to move multiple files from one directoy to anoher. I use 'My.Computer.FileSystem.MoveFile' and that works fine but it handles one file at a time. So, for every already existing file in that directory I get a warning (ie. 'File already exists') instead of one warning for the batch. Is it posible to get one warning for all the moved files?
For i = .Items.Count - 1 To 0 Step -1
Dim map = .Items.Item(i).SubItems(COL_MAP).Text
Dim bestandHernoemd = .Items.Item(i).SubItems(COL_HERNOEMD).Text
Dim bestandOrigineel = .Items.Item(i).SubItems(COL_ORIGINEEL).Text
Try
My.Computer.FileSystem.MoveFile(map & bestandOrigineel, My.Settings.OPTIE_OvernemenStandaardMapNaam & bestandHernoemd, Microsoft.VisualBasic.FileIO.UIOption.AllDialogs, Microsoft.VisualBasic.FileIO.UICancelOption.ThrowException)
.Items.RemoveAt(i)
Catch ex As Exception
foutLijst.Add(bestandOrigineel & ": " & ex.Message)
End Try
Next
And if you want to copy files recursively ( all folders, subfolders, files or subfiles ) from one source to destination, you can use the below sub procedure. No Warning applied and shall overwrite the destination.
Public Sub CopyDirectory(ByVal sourcePath As String, ByVal destinationPath As String)
Dim sourceDirectoryInfo As New System.IO.DirectoryInfo(sourcePath)
'If the destination folder doesn't exist then create it'
If Not System.IO.Directory.Exists(destinationPath) Then
'Obs, folder doesn't exist, create one please :)'
System.IO.Directory.CreateDirectory(destinationPath)
End If
Dim fileSystemInfo As System.IO.FileSystemInfo
For Each fileSystemInfo In sourceDirectoryInfo.GetFileSystemInfos
Dim destinationFileName As String = System.IO.Path.Combine(destinationPath, fileSystemInfo.Name)
'Now check whether its a file or a folder and take action accordingly
If TypeOf fileSystemInfo Is System.IO.FileInfo Then
System.IO.File.Copy(fileSystemInfo.FullName, destinationFileName, True)
Else
' Recursively call the method to copy all the nested folders
CopyDirectory(fileSystemInfo.FullName, destinationFileName)
End If
Next
End Sub
I should know better than to not give enough information/good information when asking for help. I have another question which I need to delete/link or merge here... any comment on how to do that would be great.
So the problem is I am trying to write a simple app (yeah, right) to locate a specific file on the local HDD. There WILL be multiple instances of the file (backups etc.) and I want to find each. Issues are that I cannot know how many local hdd there are and I cannot know what directory the file might be in.
So I wanted to
iterate through all fixed HDD
search the hdd for the file (I always know the name of the file)
I search HDD like this...
For Each drive As IO.DriveInfo In IO.DriveInfo.GetDrives
If drive.DriveType.ToString = "Fixed" Then
So if the found hdd is fixed I do this...
Try
For Each filename As String In IO.Directory.GetFiles(hdd, "user.config", IO.SearchOption.AllDirectories)
The issue is that I throw an exception, I have the for block above in a try catch, the exception is caught and the code exits.
OK, so I guess this is to be expected. Any suggestions on how to avoid this? Meaning I know I will run across files/directories I do not have permission for, how do I carry on and ignore what I don't care about?
FULL CODE LISTING
Private Sub Command1_Click(sender As System.Object, e As System.EventArgs) Handles Command1.Click
'variable to hold each hdd name eg: c:\
Dim hdd As String
Dim directories As Integer = 0
Dim files As Integer = 0
Try
For Each drive As IO.DriveInfo In IO.DriveInfo.GetDrives
If drive.DriveType.ToString = "Fixed" Then
'asign the variable hdd a name for this run through
hdd = drive.Name
'assign label value for directories
directories = directories + 1
Label6.Text = directories.ToString
Me.Refresh()
'search the hdd for the file user.config
Try
For Each filename As String In IO.Directory.GetFiles(hdd, "user.config", IO.SearchOption.AllDirectories)
Me.Refresh()
' 'assign label value for files
files = files + 1
Label2.Text = files.ToString
Me.Refresh()
' 'variable to hold the path for each found file
Dim file As String = IO.Path.GetFullPath(filename)
' 'update file checking label
Label4.Text = file.ToString
' 'add each found file to the list
List1.Items.Add(file)
Next
Catch ex As Exception
End Try
End If
Next
Catch ex As Exception
MsgBox(ex.ToString)
End Try
'iterate through each found drive
End Sub
You need to write it out long-wise because you need to handle the IO security issues. And of course a recursive function.
Called by:
FindFileOnAllDrivesOfType(System.IO.DriveType.Fixed, "test.txt")
Methods:
Public Function FindFileOnAllDrivesOfType(ByVal DriveType As System.IO.DriveType, ByVal FileToFind As String) As List(Of String)
Dim AllLocations As New List(Of String)
For Each drive As IO.DriveInfo In IO.DriveInfo.GetDrives
If drive.DriveType = DriveType Then
AllLocations = FindFile(drive.ToString(), FileToFind)
End If
Next
Return AllLocations
End Function
Public Function FindFile(ByVal StartDirectory As String, ByVal FileToFind As String) As List(Of String)
Dim AllLocations As New List(Of String)
Try
For Each dirname As String In IO.Directory.GetDirectories(StartDirectory)
AllLocations.AddRange(FindFile(dirname, FileToFind))
Next
For Each filename As String In IO.Directory.GetFiles(StartDirectory, FileToFind, IO.SearchOption.TopDirectoryOnly)
AllLocations.Add(filename)
Next
Catch ex As Exception
' MessageBox.Show(ex.Message)
'Do nothing as we can't get a directory listing
End Try
Return AllLocations
End Function
I'm trying to create a list of all directories and their sub-directories in a given path in visual studio 2012.
It's a very long time since I've been in touch with visual basic. I hope somebody can show a simple way for this task.
Any kind of help is much appreciated. :)
In the System.IO namespace
Directory.GetDirectories(string, string, SearchOptions)
A good example from MSDN
Dim dirs As String() = Directory.GetDirectories("c:\", "*.*", SearchOption.AllDirectories)
Console.WriteLine("The number of directories starting with p is {0}.", dirs.Length)
Dim dir As String
For Each dir In dirs
Console.WriteLine(dir)
Next
Catch e As Exception
Console.WriteLine("The process failed: {0}", e.ToString())
End Try
However keep in mind that some directories could have particular access permissions and your code could fail with an IOException. (That's particularly true for the system directories)
Another option is through the use of Directory.EnumerateDirectories that is preferable when you work with many directories and you don't need to have the string array with names filled.
EnumerateDirectories start immediately without waiting to filling the array and is very useful in situation where your code loops over the enumeration
For Each dirName in Directory.EnumerateDirectories("C:\", "p*", SearchOptions.AllDirectories)
..... do something with the directory here ....
Next
Dim path as string ="c:\DirectoryTest"
Dim result = Directory.EnumerateDirectories(path, "*", System.IO.SearchOption.AllDirectories)
This recursive method will get all directories & its sub-directories from a given path:
Option 1#
Public Shared Sub ProcessDirectory(ByVal targetDirectory As String)
Dim subdirectoryEntries As String() =
Directory.GetDirectories(targetDirectory)
' Recurse into subdirectories of this directory.
Dim subdirectory As String
For Each subdirectory In subdirectoryEntries
ProcessDirectory(subdirectory)
Next subdirectory
End Sub
Option 2#
Module Module1
Sub Main()
Try
Dim dirPath As String = "c:\\myDirctory"
Dim dirs As List(Of String) = New List(Of String)(Directory.EnumerateDirectories(dirPath))
For Each folder In dirs
Console.WriteLine("{0}", folder.Substring(folder.LastIndexOf("\") + 1))
Next
Console.WriteLine("{0} directories found.", dirs.Count)
Catch UAEx As UnauthorizedAccessException
Console.WriteLine(UAEx.Message)
Catch PathEx As PathTooLongException
Console.WriteLine(PathEx.Message)
End Try
End Sub
End Module
You can refer MSDN for further details:
http://msdn.microsoft.com/en-us/library/c1sez4sc.aspx
http://msdn.microsoft.com/en-us/library/dd383304.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2