Results 1 to 17 of 17

Thread: .NET Find Most Recently Modified File incl. Recursively/Subfolder Support

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Oct 1999
    Posts
    104

    Question .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!

  2. #2
    Lively Member Grant Swinger's Avatar
    Join Date
    Jul 2015
    Posts
    64

    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.

  3. #3

    Thread Starter
    Lively Member
    Join Date
    Oct 1999
    Posts
    104

    Re: .NET Find Most Recently Modified File incl. Recursively/Subfolder Support

    Grant, thank you for your reply. And advice taken, both books ordered today!

  4. #4
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    23,562

    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

  5. #5

    Thread Starter
    Lively Member
    Join Date
    Oct 1999
    Posts
    104

    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

  6. #6
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    23,562

    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)

  7. #7

    Thread Starter
    Lively Member
    Join Date
    Oct 1999
    Posts
    104

    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.

  8. #8

    Thread Starter
    Lively Member
    Join Date
    Oct 1999
    Posts
    104

    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.'

  9. #9
    Frenzied Member PlausiblyDamp's Avatar
    Join Date
    Dec 2016
    Location
    Newport, UK
    Posts
    1,279

    Re: .NET Find Most Recently Modified File incl. Recursively/Subfolder Support

    Quote Originally Posted by swambast View Post
    .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

  10. #10

    Thread Starter
    Lively Member
    Join Date
    Oct 1999
    Posts
    104

    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

  11. #11
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    23,562

    Re: .NET Find Most Recently Modified File incl. Recursively/Subfolder Support

    Code:
    Catch ex As UnauthorizedAccessException
    Have a look at the Properties for the UnauthorizedAccessException Class

  12. #12

    Thread Starter
    Lively Member
    Join Date
    Oct 1999
    Posts
    104

    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.

  13. #13
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    23,562

    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.

  14. #14

    Thread Starter
    Lively Member
    Join Date
    Oct 1999
    Posts
    104

    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).

  15. #15
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    23,562

    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...

  16. #16
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    23,562

    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

  17. #17

    Thread Starter
    Lively Member
    Join Date
    Oct 1999
    Posts
    104

    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
  •  



Click Here to Expand Forum to Full Width