-
Oct 23rd, 2020, 09:27 AM
#1
Thread Starter
Lively Member
.NET Find Most Recently Modified File incl. Recursively/Subfolder Support
Hi everyone,
I am a rusty VB6 programmer trying to finally take a serious plunge into .NET. I apologize for this basic request in advance. Here’s what I’m trying to accomplish under VB.NET:
* Assume “MyFileTest.ini” can occur in multiple subfolders
Loop through a series of folders/subfolders looking for a specific file name: “MyFileTest.txt” for example.
Found file results might look like this:
C:\MyFileTest.txt
C:\A_Directory\MyFileTest.txt
C:\A_Directory\ABDirectory\MyFileTest.txt
C:\F_Directory\MyFileTest.txt
And have a variable (function?) return only the most recently modified file found (e.g., “newest” version of MyFileTest.txt from any location)
Bonus Request: Dump each file found result (“MyFileTest.ini”) into a List Box with column headings – File Name, File Extension, File Path, Last Date Modified (historically I use 10Tec.com iGrid ActiveX grid control which is just awesome but want to start off more simply here).
Thank you for any general guidance or sample code sets - kind of getting excited about delving into .NET but have a lot to learn.
As an aside - any maybe should be for a different post... But if anyone has come across a particularly good help/support resource that kind of structures things like "In VB6 you used to do this, in VB.NET it's now done like this) please let me know.
Thank you!
-
Oct 23rd, 2020, 11:14 AM
#2
Lively Member
Re: .NET Find Most Recently Modified File incl. Recursively/Subfolder Support
But if anyone has come across a particularly good help/support resource that kind of structures things like "In VB6 you used to do this, in VB.NET it's now done like this) please let me know.
Let me highly recommend a book or two for you. Many, many people have told me that the first one was the book that got them over the hump of .NET development.
It's "The Book of Visual Basic 2005" by Matthew MacDonald published by No Starch Press. You can still find good used copies of it on Amazon and elsewhere. The book's subtitle is ".NET Insight for Classical VB Developers" and the cover shows a suitcase with ".NET OR BUST!" on it. It's exactly what you're looking for.
You should also look at "Pro .NET 2.0 Windows Forms and Custom Controls in VB 2005" by the same author and published by Apress.
While these books only cover up to .NET 2.0 they will give you a firm foundation in .NET development. Read them and the world of .NET will make a lot more sense.
-
Oct 23rd, 2020, 03:49 PM
#3
Thread Starter
Lively Member
Re: .NET Find Most Recently Modified File incl. Recursively/Subfolder Support
Grant, thank you for your reply. And advice taken, both books ordered today!
-
Oct 23rd, 2020, 08:46 PM
#4
Re: .NET Find Most Recently Modified File incl. Recursively/Subfolder Support
To find the files, and the newest last write time...
Code:
Dim files() as String = IO.Directory.EnumerateFiles("C:\", "MyFileTest.txt", SearchOption.AllDirectories)
files = files.OrderBy(function(f) IO.Directory.GetLastWriteTime(f)).ToArray
Dim newestFile as String = files.FirstOrDefault
Dump each file found result (“MyFileTest.ini”) into a List Box with column headings – File Name, File Extension, File Path, Last Date Modified
Code:
DataGridView1.ColumnCount = 4
DataGridView1.Columns(0).Name = "File Name"
DataGridView1.Columns(1).Name = "File Extension"
DataGridView1.Columns(2).Name = "File Path"
DataGridView1.Columns(3).Name = "Last Date Modified"
For Each file as string in files
DataGridView1.Rows.Add(IO.Path.GetFileNameWithoutExtension(file), _
IO.Path.GetExtension(file), _
IO.Path.GetDirectoryName(file), _
IO.Directory.GetLastWriteTime(file))
Next
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Oct 23rd, 2020, 09:23 PM
#5
Thread Starter
Lively Member
Re: .NET Find Most Recently Modified File incl. Recursively/Subfolder Support
.paul - wow, thanks as this looks really encouraging. Unfortunately I'm getting an error with the first line (Dim files() as String = IO.Directory.EnumerateFiles("C:", "MyFileTest.txt", SearchOption.AllDirectories)
The error is: System.InvalidCastException: 'Unable to cast object of type 'System.IO.FileSystemEnumerableIterator`1[System.String]' to type 'System.String[]'.'
Error Details:
System.InvalidCastException
HResult=0x80004002
Message=Unable to cast object of type 'System.IO.FileSystemEnumerableIterator`1[System.String]' to type 'System.String[]'.
Source=TestWindowsApp1
StackTrace:
at TestWindowsApp1.Form1.Button1_Click_1(Object sender, EventArgs e) in C:\Users\StevenSwamba\source\repos\TestWindowsApp1\TestWindowsApp1\Form1.vb:line 80
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoCompo nentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
at TestWindowsApp1.My.MyApplication.Main(String[] Args) in :line 81
-
Oct 23rd, 2020, 09:29 PM
#6
Re: .NET Find Most Recently Modified File incl. Recursively/Subfolder Support
use this...
Code:
Dim files() as String = IO.Directory.GetFiles("C:\", "MyFileTest.txt", SearchOption.AllDirectories)
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Oct 23rd, 2020, 09:58 PM
#7
Thread Starter
Lively Member
Re: .NET Find Most Recently Modified File incl. Recursively/Subfolder Support
.Paul = Looks like it's working now - you rock m8, THANK YOU!
Just need to do some extensive testing on it and evaluate a bit more. I really appreciate this - I learn best by taking working code sets and "reverse engineering" them to better understand them. I'm already getting up to speed now with the power of IO.Directory and learning more about the features of the DataGrid views all thanks to you.
-
Oct 23rd, 2020, 10:13 PM
#8
Thread Starter
Lively Member
Re: .NET Find Most Recently Modified File incl. Recursively/Subfolder Support
.Paul (others)? > Any advice on how to handle "protected directories" (e.g., System.UnauthorizedAccessException: 'Access to the path 'C:\$Recycle.Bin\' is denied.'
-
Oct 24th, 2020, 03:52 AM
#9
Re: .NET Find Most Recently Modified File incl. Recursively/Subfolder Support
Originally Posted by swambast
.Paul (others)? > Any advice on how to handle "protected directories" (e.g., System.UnauthorizedAccessException: 'Access to the path 'C:\$Recycle.Bin\' is denied.'
Easiest way is probably to just catch and ignore any UnauthorizedAccessExceptions
-
Oct 24th, 2020, 11:57 AM
#10
Thread Starter
Lively Member
Re: .NET Find Most Recently Modified File incl. Recursively/Subfolder Support
OK, I'm understanding this is set up as a Try...Catch...Finally...End Try. So, seem to be close with this code here but what am I missing? Also, I'm finding the examples and language reference guides on VB.NET terrible. I must not be looking in the right place, as I'm spending like 10-15 mins on each topic googling various sites. I mean, any good example of a loop should show a way to error trap - but instead I get vague implications like "A Try...Catch...Finally statement catches an exception. You might use Exit For at the end of the Finally block" without a real world example. Again, beyond hard copy book references - if there are better online references please do let me know, thanks again.
Code:
For Each file As String In files
Try
DataGridView1.Rows.Add(IO.Path.GetFileNameWithoutExtension(file),
IO.Path.GetExtension(file),
IO.Path.GetDirectoryName(file),
IO.Directory.GetLastWriteTime(file))
Catch ex As Exception
FileOut_Errors = FileOut_Errors & " * ERROR " & vbCrLf
End Try
Next
-
Oct 24th, 2020, 12:20 PM
#11
Re: .NET Find Most Recently Modified File incl. Recursively/Subfolder Support
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Oct 24th, 2020, 03:05 PM
#12
Thread Starter
Lively Member
Re: .NET Find Most Recently Modified File incl. Recursively/Subfolder Support
Thanks - but what I'm having difficulty with (and this seemed a lot easier under VB6) is what seems to be the error handling logic. Meaning, even if there is an error thrown, keep looping and try the other folders/subfolders. Right now the error is thrown and the program/loop stops. I'm trying to get down the logic that 1) captures all error messages in a string (e.g., System.UnauthorizedAccessException: 'Access to the path 'C:\$Recycle.Bin\' is denied., Next One, etc.) 2) AND EVEN IF THE ERROR IS THROWN, KEEPS THE LOOP ACTIVE all subfolders searches are completed.
-
Oct 24th, 2020, 03:52 PM
#13
Re: .NET Find Most Recently Modified File incl. Recursively/Subfolder Support
Ok. You need manual recursion through the folders in that case...
Code:
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
DataGridView1.ColumnCount = 4
DataGridView1.Columns(0).Name = "File Name"
DataGridView1.Columns(1).Name = "File Extension"
DataGridView1.Columns(2).Name = "File Path"
DataGridView1.Columns(3).Name = "Last Date Modified"
Dim path = "c:\"
Dim find = "readme.txt"
Dim runProcess As ProcessFileDelegate = AddressOf ProcessFile
Dim t As New Threading.Thread(AddressOf SearchForFiles)
Dim o As Object = New Object() {path, find, runProcess}
t.Start(o)
End Sub
Delegate Sub ProcessFileDelegate(ByVal path As String)
Private Sub ProcessFile(ByVal file As String)
If DataGridView1.InvokeRequired Then
DataGridView1.Invoke(New ProcessFileDelegate(AddressOf ProcessFile), file)
Else
DataGridView1.Rows.Add(IO.Path.GetFileNameWithoutExtension(file), _
IO.Path.GetExtension(file), _
IO.Path.GetDirectoryName(file), _
IO.Directory.GetLastWriteTime(file))
End If
End Sub
' This is the recursive procedure that traverse all the directory and'
' pass each filename to the delegate that adds the file to the listbox'
Private Sub SearchForFiles(ByVal o As Object)
Dim obj() As Object = DirectCast(o, Object())
Dim folder As String = obj(0).ToString
Dim searchFor As String = obj(1).ToString
Dim fileAction As ProcessFileDelegate = DirectCast(obj(2), ProcessFileDelegate)
For Each file In IO.Directory.GetFiles(folder, searchFor)
fileAction.Invoke(file)
Next
For Each subDir In IO.Directory.GetDirectories(folder)
Try
SearchForFiles(New Object() {subDir, searchFor, fileAction})
Catch ex As Exception
' Console.WriteLine(ex.Message)'
' Or simply do nothing '
End Try
Next
End Sub
End Class
Last edited by .paul.; Oct 24th, 2020 at 04:00 PM.
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Oct 25th, 2020, 11:08 AM
#14
Thread Starter
Lively Member
Re: .NET Find Most Recently Modified File incl. Recursively/Subfolder Support
Thanks .Paul - thank you and interesting. I believe this runs more in a separate thread. If so, how and where do I determine when the actual search is "complete" so I can do other things. For example, initially for performance reasons I would want to hide the GridView (e.g., DataGridView1.Visible = False), conduct the search, and once the search is over autosize the grid view columns ( DataGridView1.AutoResizeColumns()) and make it visible again (DataGridView1.Visible = True).
-
Oct 25th, 2020, 12:46 PM
#15
Re: .NET Find Most Recently Modified File incl. Recursively/Subfolder Support
I’ve been re writing my example. In my case, with a 2TB C:\ drive, searching takes a long time. I can look at writing the rows to a 2D array to later load into the dgv. That would make the searching faster. I did put it in a background thread, so as not to freeze the GUI thread. I’ll look into the thread completion event when i can get back to my workstation and have another look at it...
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Oct 25th, 2020, 02:02 PM
#16
Re: .NET Find Most Recently Modified File incl. Recursively/Subfolder Support
Ok i rewrote it. Code takes about 8 minutes to search my 2TB C:\ drive...
Code:
Public Class Form1
Dim newestDate As Date = CDate("January 1, 0001")
Dim newest As String
Dim t As Threading.Thread
Dim rows As New List(Of Object())
Dim startTime As Integer
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
DataGridView1.ColumnCount = 4
DataGridView1.Columns(0).Name = "File Name"
DataGridView1.Columns(1).Name = "File Extension"
DataGridView1.Columns(2).Name = "File Path"
DataGridView1.Columns(3).Name = "Last Date Modified"
Dim path = "c:\"
Dim find = "readme.txt"
Dim runProcess As ProcessFileDelegate = AddressOf ProcessFile
t = New Threading.Thread(AddressOf SearchForFiles)
Dim o As Object = New Object() {path, find, runProcess}
t.Start(o)
startTime = Environment.TickCount
Dim t2 As New Threading.Thread(AddressOf DetectCompleted)
t2.Start()
End Sub
Delegate Sub ProcessFileDelegate(ByVal path As String)
Private Sub ProcessFile(ByVal file As String)
rows.Add(New Object() {IO.Path.GetFileNameWithoutExtension(file), _
IO.Path.GetExtension(file), _
IO.Path.GetDirectoryName(file), _
IO.Directory.GetLastWriteTime(file)})
If IO.Directory.GetLastWriteTime(file) > newestDate Then
newestDate = IO.Directory.GetLastWriteTime(file)
newest = file
End If
End Sub
' This is the recursive procedure that traverse all the directory and'
' pass each filename to the delegate that adds the file to the listbox'
Private Sub SearchForFiles(ByVal o As Object)
Dim obj() As Object = DirectCast(o, Object())
Dim folder As String = obj(0).ToString
Dim searchFor As String = obj(1).ToString
Dim fileAction As ProcessFileDelegate = DirectCast(obj(2), ProcessFileDelegate)
For Each file In IO.Directory.GetFiles(folder, searchFor)
fileAction.Invoke(file)
Next
For Each subDir In IO.Directory.GetDirectories(folder)
Try
SearchForFiles(New Object() {subDir, searchFor, fileAction})
Catch ex As Exception
' Console.WriteLine(ex.Message)'
' Or simply do nothing '
End Try
Next
End Sub
Private Sub DetectCompleted()
While t.IsAlive
' do nothing
End While
WorkerCompleted()
End Sub
Delegate Sub WorkerCompletedDelegate()
Private Sub WorkerCompleted()
If DataGridView1.InvokeRequired Then
DataGridView1.Invoke(New WorkerCompletedDelegate(AddressOf WorkerCompleted))
ElseIf Label1.InvokeRequired Then
Label1.Invoke(New WorkerCompletedDelegate(AddressOf WorkerCompleted))
Else
DataGridView1.Rows.Add(rows.Count)
For x As Integer = 0 To rows.Count - 1
DataGridView1.Rows(x).SetValues(rows(x))
Next
Label1.Text = "Newest: " & newest
DataGridView1.AutoResizeColumns()
MsgBox(Environment.TickCount - startTime)
End If
End Sub
End Class
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Oct 27th, 2020, 11:54 AM
#17
Thread Starter
Lively Member
Re: .NET Find Most Recently Modified File incl. Recursively/Subfolder Support
Gees Paul, amazing really - thank you very much. I will give it a test this weekend and report back, again my sincere thanks so far for all of your help on this.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|