I'm looking for the simplest way to display all drives, files, and subfolders in a treeview. If someone's got a snippet of code to do this that they don't mind sharing I would really appreciate it.
The closest I've gotten was this code I tried using, but it gave me a "IOException was unhandled" error saying "The device is not ready." error at runtime (after about 5-10 sec) on the line below
Dim folders() As String = IO.Directory.GetDirectories(dir)
underneath is the rest of the code
Private Sub Main_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim drives As System.Collections.ObjectModel.ReadOnlyCollection(Of IO.DriveInfo) = My.Computer.FileSystem.Drives
Dim rootDir As String = String.Empty
For i As Integer = 0 To drives.Count - 1
rootDir = drives(i).Name
TreeView1.Nodes.Add(rootDir)
PopulateTreeView(rootDir, TreeView1.Nodes(i))
Next
End Sub
Private Sub PopulateTreeView(ByVal dir As String, ByVal parentNode As TreeNode)
Dim folder As String = String.Empty
Try
Dim folders() As String = IO.Directory.GetDirectories(dir)
If folders.Length <> 0 Then
Dim childNode As TreeNode = Nothing
For Each folder In folders
childNode = New TreeNode(folder)
parentNode.Nodes.Add(childNode)
PopulateTreeView(folder, childNode)
Next
End If
Catch ex As UnauthorizedAccessException
parentNode.Nodes.Add(folder & ": Access Denied")
End Try
End Sub
Seems like you're off to a good start. The IOException you receive is most likely caused by your procedure trying to list contents on an empty disc drive, which is obviously impossible.
The fix is simple:
For i As Integer = 0 To drives.Count - 1
If Not drives(i).IsReady Then
Continue For
End If
rootDir = drives(i).Name
TreeView1.Nodes.Add(rootDir)
PopulateTreeView(rootDir, TreeView1.Nodes(i))
Next
Besides that, I recommend not loading folder contents until a node is clicked. Limit the recursive call to 1 level (current directory + content of all its subdirectories). That way, you get the best performance while still being able to determine whether a subdirectory should have the treeview expand button.
Related
Trying to create a login form,
My coding is currently:
Imports System
Imports System.IO
Public Class frmLogin
Dim username As String
Dim password As String
Dim fileReader As String
Dim folderpath As String
Dim files As Integer
Dim filepath As String
Public Structure info
Dim U As String
Dim P As String
End Structure
Dim details As info
Private Sub btnlogin_Click(sender As Object, e As EventArgs) Handles btnlogin.Click
If txtusername.Text = details.U And txtpassword.Text = details.P Then
MessageBox.Show("Correct!")
frmmenu.Show()
Me.Hide()
Else
MessageBox.Show("wrong")
txtusername.Clear()
txtpassword.Clear()
End If
End Sub
Private Sub btncreate_Click(sender As Object, e As EventArgs) Handles btncreate.Click
frmcreate.Show()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
files = files + 1
filepath = "C:\Users\TheGlove\Desktop\Alex's Program\loginfile" & files & ".txt"
Dim di As DirectoryInfo = New DirectoryInfo("C:\Users\TheGlove\Desktop\Alex's Program")
folderpath = "C:\Users\TheGlove\Desktop\Alex's Program"
files = System.IO.Directory.GetFiles(folderpath, "*.txt").Count
For Each fi In di.GetFiles()
MsgBox(fi.Name)
Dim FILE = System.IO.File.ReadAllLines("C:\Users\TheGlove\Desktop\Alex's Program\loginfile" & files & ".txt")
Dim myArray As String() = FILE
details.U = myArray(0)
details.P = myArray(1)
Next
End Sub
End Class
Button 1 will be merged with btnlogin when i get it working and for now is currently just a seperate button to read each textfile.
When each button is pressed (Button 1 -> btnlogin), only the last created textfile is correct.
By the looks of things, your code does read all the text files, but keeps overwriting details.u and details.p with the value retrieved from each file. So, when the loop gets to the last file, those values are what ends up in the details object.
I'm assuming that you want to read all the usernames and passwords into a list and check the details in the TextBoxes against that list, so .. Your code should probably be something like the code below (see the code comments for an explanation of some of the differences.
Before we get to the code, can give you a couple of pointers.
Firstly, always try to use names that are meaningful. Defining your structure as Info is not as meaningful as it could be. For example, you would be better calling it UserInfo and rather than use P and U, you would be better using Password and UserName. It may not matter so much right now, but when you start writing larger more complex programs, and have to come back to them in 6 months time to update them, info.P or details.P aren't as informative as the suggested names.
Secondly, as #ajd mentioned. Don't use magic strings. Create one definition at the beginning of your code which can be used throughout. Again it makes maintenance much easier if you only have to change a string once instead of multiple times, and reduces the chance of mistakes.
Finally, several of the variables you have defined aren't used in your code at all. Again, at this level, it isn't a major issue, but with large programs, you could end up with a bigger memory footprint than you want.
Dim username As String
Dim password As String
Dim fileReader As String
Dim folderpath As String = "C:\Users\TheGlove\Desktop\Alex's Program"
Dim files As Integer
Dim filepath As String
Public Structure UserInfo
Dim Name As String
Dim Password As String
End Structure
'Change details to a list of info instead of a single instance
Dim userList As New List(Of UserInfo)
Private Sub Btnlogin_Click(sender As Object, e As EventArgs) Handles btnlogin.Click
'Iterate through the list of details, checking each instance against the textboxes
For Each tempUserInfo As UserInfo In userList
If txtusername.Text = tempUserInfo.Name And txtpassword.Text = tempUserInfo.Password Then
MessageBox.Show("Correct!")
frmmenu.Show()
Me.Hide()
'This is here, because after your form has opened an closed, the loop
'that checks usernames and passwords will continue. The line below exits the loop safely
Exit For
Else
MessageBox.Show("wrong")
txtusername.Clear()
txtpassword.Clear()
End If
Next
End Sub
Private Sub Btncreate_Click(sender As Object, e As EventArgs) Handles btncreate.Click
frmcreate.Show()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'clear the list of user details otherwise, if the files are loaded a second time,
'you'll get the same details added again
userList.Clear()
'This line replaces several lines in your code that searches the folder for files
'marching the search pattern
Dim fileList() As FileInfo = New DirectoryInfo(folderpath).GetFiles("loginfile*.txt")
For Each fi As FileInfo In fileList
MsgBox(fi.Name)
Dim userDetails() As String = System.IO.File.ReadAllLines(fi.FullName)
Dim tempInfo As New UserInfo With {.Name = userDetails(0), .Password = userDetails(1)}
'An expanded version of the above line is
'Dim tempInfo As New info
'tempInfo.U = userDetails(0)
'tempInfo.P = userDetails(1)
userList.Add(tempInfo)
Next
files = fileList.Count
End Sub
Just trying to learn VB.net.
Making something that lists all files an folders in folder and subfolder.
Got a testfolder in root C:\ with a 2 subfolders and som files in al folders.
On execution listbox is filled with al files an folders including subfolders an files in subfolders.
But..
If id choose a folder on G:\ things get strange, and I only get A few folders or files listed
This is my first question here,so if if screw up in telling you, I am sorry
Public Class Form1
Dim R As IO.StreamReader
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
ListBox1.Items.Clear()
Me.FolderBrowserDialog1.ShowDialog()
Listfiles(Me.FolderBrowserDialog1.SelectedPath)
End Sub
Public Sub Listfiles(ByVal Pad As String)
Dim DirInfo As New IO.DirectoryInfo(Pad)
Dim FileObject As IO.FileSystemInfo
Dim strBESTAND As String
For Each FileObject In DirInfo.GetFileSystemInfos
'if FileObject is a folder
If FileObject.Attributes = IO.FileAttributes.Directory Then '
Listfiles(FileObject.FullName)
Me.ListBox1.Items.Add(FileObject.FullName)
Else
strBESTAND = (FileObject.FullName)
Dim information = My.Computer.FileSystem.GetFileInfo(strBESTAND)
' If extention matches ..........
Dim strEXTENTIE As String
'if extentie is tikt in checkedlistbox
For i As Integer = 0 To (CheckedListBoxEXTENTIES.CheckedItems.Count - 1) ' iterate on checked items
'only us ticked items
strEXTENTIE = ((CheckedListBoxEXTENTIES.GetItemText(CheckedListBoxEXTENTIES.CheckedItems(i)).ToString))
If information.Extension = "." & strEXTENTIE Then
strBESTAND = information.Name
Me.ListBox1.Items.Add(FileObject.Name)
End If
Next
End If
Next
MessageBox.Show("Done!")
End Sub
The string comparisons are case sensitive by default. You will miss extensions having another case as in the CheckedListBox. Use
If String.Compare(information.Extension, "." & strEXTENTIE, _
StringComparison.OrdinalIgnoreCase) = 0 Then
But it would be more efficient if you prepared the extensions before browsing the folders
'Outside of subroutines
Dim extensions As New HashSet(Of String)()
'In Button1_Click before calling Listfiles
For i As Integer = 0 To CheckedListBoxEXTENTIES.CheckedItems.Count - 1
extensions.Add("." & _
CheckedListBoxEXTENTIES.CheckedItems(i).ToString().ToLowerInvariant())
Next
Then you can check the extensions like this, without having to loop through the CheckedListBox for each file.
If extensions.Contains(information.Extension.ToLowerInvariant()) Then
I want to list all JPG files from all drives in a computer with there full path.
So I tried following code but it only list few random files, it wont search all files. i got this from here: Searching a drive with vb.net
Public Sub DirSearch(ByVal sDir As String)
Dim fl As String
Try
For Each dir As String In Directory.GetDirectories(sDir)
For Each fl In Directory.GetFiles(dir, "*.jpg")
listbox1.Items.Add(fl)
Next
DirSearch(dir)
Next
Catch ex As Exception
Debug.WriteLine(ex.Message)
End Try
End Sub
'form1 load event
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
DirSearch("c:\")
DirSearch("d:\")
DirSearch("e:\")
DirSearch("f:\")
DirSearch("g:\")
DirSearch("h:\")
DirSearch("i:\")
DirSearch("j:\")
DirSearch("k:\")
'DirSearch("so on.....")
savetxtfile()
End Sub
Save searched result to text file in system drive
Sub savetxtfile()
Dim systemdrv As String = Mid(Environment.GetFolderPath(Environment.SpecialFolder.System), 1, 3)
TextBox1.Text = listbox1.Items.Count
Dim w As IO.StreamWriter
Dim r As IO.StreamReader
Dim i As Integer
w = New IO.StreamWriter(systemdrv + "temp\test.txt")
For i = 0 To listbox1.Items.Count - 1
w.WriteLine(listbox1.Items.Item(i))
Next
w.Close()
End Sub
You're ignoring your exception...
Debug.WriteLine(ex.Message)
Use this instead (so you can't miss it for debugging)...
MessageBox.Show(ex.Message)
Knowing that what's happening is probably a folder access error, you need to handle that accordingly.
For Each dir As String In Directory.GetDirectories(sDir)
Try
For Each fl In Directory.GetFiles(dir, "*.jpg")
lstbxTest.Items.Add(fl)
Next
Catch ex As Exception
Continue For
End Try
Next
Effectively, continue if you get an error, because you don't really care in this case.
You might want to add some exceptions in there (If dir = "whatever" Then Continue For) so you're not trying to go through every single system folder in operating system.
Visual Studio 2008 (vb.net)
I made simple anivirus but when I make Full scan by this code:
FolderBrowserDialog1.SelectedPath = ("C:\")
'first scan:************************************
Try
For Each strDir As String In
System.IO.Directory.GetDirectories(FolderBrowserDialog1.SelectedPath)
For Each strFile As String In System.IO.Directory.GetFiles(strDir)
ListBox1.Items.Add(strFile)
Next
Next
'Start the timer:
Catch ex As Exception
End Try
Timer1.Start()`
Just scan the first 6 files ...
I think the problem from Windows Folder permissions (Windows - Program Files ...etc)
So how to fix it?
Put a Console.WriteLine(ex) in your catch block so you can see any exceptions that are thrown. You'll probably see your problem then. Most likely permissions.
You could try the following:
For Each strFile As String In System.IO.Directory.GetFiles(strDir, "*", IO.SearchOption.AllDirectories)
Edit:
You could try the last solution found in this thread:
http://www.vbforums.com/showthread.php?t=624969
I tried this myself and it was super slow, but worked fine.
Public Class Form1
Private Sub foo(ByVal aDir As String)
Try
Dim di As New IO.DirectoryInfo(aDir)
Dim aryFiles() As IO.FileInfo = di.GetFiles("*.*")
Dim aryDirs() As IO.DirectoryInfo = di.GetDirectories()
For Each fi As IO.FileInfo In aryFiles
rslts.Add(fi.FullName)
Next
For Each d As IO.DirectoryInfo In aryDirs
foo(d.FullName)
Next
Catch ex As Exception
'Stop 'the catch should be more specific
End Try
End Sub
Dim rslts As List(Of String)
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
rslts = New List(Of String)
foo("C:\")
ListBox1.Items.Clear()
ListBox1.Items.AddRange(rslts.ToArray)
End Sub
End Class
It looks like your solution essentially loops through the first folder it can find and stops there. This solution is a bit different as it will recursively go through all the files and folders based on the start location.
Dim de As New System.DirectoryServices.DirectoryEntry()
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
de.Path = "WinNT://*****".Replace("*****", ActiveDirectory.Domain.GetCurrentDomain.Name)
Dim Mystream As Object
MsgBox("Please choose the place you want the file")
If savefileDialog1.ShowDialog() = DialogResult.OK Then Mystream = savefileDialog1.FileName
Dim UserFile As String = savefileDialog1.FileName & ".txt"
Dim fileExists As Boolean = File.Exists(UserFile)
Using sw As New StreamWriter(File.Open(UserFile, FileMode.OpenOrCreate))
For Each d As DirectoryEntry In de.Children()
sw.WriteLine(d.Name)
Next
End Using
End Sub
I am getting a large number of entries written out to the text file. The bottom half of the file is all that I really need. The bottom half seems to be the list of all machine names on the domain and the first half is filled with names or printers, and other names that i cannot "pushd \" into.
I am unable to figure out what will cut down this user list and give me only the machine names.
You might find something here...look at "Enumerate Objects in an OU"
Public Function EnumerateOU(OuDn As String) As ArrayList
Dim alObjects As New ArrayList()
Try
Dim directoryObject As New DirectoryEntry("LDAP://" + OuDn)
For Each child As DirectoryEntry In directoryObject.Children
Dim childPath As String = child.Path.ToString()
alObjects.Add(childPath.Remove(0, 7))
'remove the LDAP prefix from the path
child.Close()
child.Dispose()
Next
directoryObject.Close()
directoryObject.Dispose()
Catch e As DirectoryServicesCOMException
Console.WriteLine("An Error Occurred: " + e.Message.ToString())
End Try
Return alObjects
End Function
I'm not sure if there is much difference in our active directory setups, but I ran the following code in a console application and it only output the AD Names (as expected):
Module Module1
Sub Main()
Using de As New System.DirectoryServices.DirectoryEntry
de.Path = "WinNT://*****".Replace("*****", System.DirectoryServices.ActiveDirectory.Domain.GetCurrentDomain.Name)
For Each d As System.DirectoryServices.DirectoryEntry In de.Children()
If d.SchemaEntry.Name = "User" Then
Console.WriteLine(d.Name)
End If
Next
Console.ReadKey()
End Using
End Sub
End Module
EDIT:
Code change to only output members with the SchemaType of "User"