ファイルの検索

VBA「ファイルの検索」VB.NET版です。
VBA「ファイルの検索」は遅い!?....     VBAではFileSearchオブジェクトが利用できなくなったため、ファイルの検索では全ファイルを検索しながら、 該当のファイルをLIKE判定するなどで判定させる方法になっています。
Office2007以降でこの「FileSearchオブジェクト」が実装されなくなっっており、当方の環境でももう旧バージョンとの比較はできないのですが、 大量なファイル数のなかから少数のファイルを検索する用途だと、現在の方法は「FileSearchオブジェクト」に比べてかなり遅いようです。
そこでですが、VB.NETはフォルダ内のファイルの抽出(Directory.GetFiles)で、サーチパターンの指定ができることから、 現在のVBAでやっている「ファイルの検索」の方法もVB.NETでも行なえるので、 処理時間の比較を行なってみようと思います。
かつての「FileSearchオブジェクト」がVB.NETの「ファイルの抽出(Directory.GetFiles)」と同等の処理速度なのかは現在では不明なのですが、 それでも「FileSearchオブジェクト」より「かなり速い」のであればここでの方法は参考になると思います。
このページのサンプルはVBA「ファイルの検索」とほぼ同様にExcelワークシートに検索結果を出力するものなので、 このような処理であればVBAにこだわらずにVB.NETに移行させてみてはいかがでしょうか。
サンプルを実行して試してみて下さい。

ファイルの検索
(画像をクリックすると、このサンプルがダウンロードできます)
なお、各処理の処理時間は、起動初回と2回目以降で相当異なります。 初回に選択した方法が遅かったとしても2回目以降に選択した方法がキャッシュ利用で速い可能性があるため、 各方法とも2回以上試して確認して下さい。
当方の環境ではローカルディスク(HDD)の環境で、複数の階層のフォルダに合計で16千ファイルがあるところから、数十ファイルを探索する状態で Cは6秒強かかるのですが、Bだと0.7秒程度という速さでした。

以下は「ファイル探索手段」の@〜Cそれぞれに対応したクラスモジュールのソースコードの紹介です。

@My.Computer.FileSystem.FindInFiles
My.Computer.FileSystem.FindInFiles」はVB.NETでワイルドカードを使ったファイル検索の方法として、 Web検索では真っ先に出てくる方法です。 ですが、数万件のファイル数からの検索をやってみると意外に遅く、オブジェクトからコレクションを取得する先頭行のところで結果が得られないままタイムアウトしてしまいました。

'***************************************************************************************************
'   ファイルを検索してExcelに一覧出力(サンプル@)              clsSearchFilesTEST1(Class)
'
'   ※My.Computer.FileSystem.FindInFiles
'
'   作成者:井上治  URL:http://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
' 変更日付 Rev   変更履歴内容---------------------------------------------------------------------->
' 17/12/02(1.0.0)新規作成
'***************************************************************************************************
Imports System.IO
Friend Class clsSearchFilesTEST1
    '===============================================================================================
    ' 親フォームとの受け渡し変数
    Private g_strRootPath As String = ""                        ' ルートフォルダ
    Private g_strSearchWord As String = ""                      ' 検索文字列
    Private g_blnUseLimitDate As Boolean = False                ' 更新日時指定有無
    Private g_dteLimitDate As Date                              ' 更新日時指定
    Private g_strMSG As String = ""                             ' メッセージ

    '***********************************************************************************************
    ' ■■■ 呼び出しプロシージャ ■■■
    '***********************************************************************************************
    '* 処理名 :SearchFiles
    '* 機能  :ファイルの探索
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :処理結果(Boolean)       ※0=未処理、1=処理成功、9=エラー
    '* 引数  :Arg1 = 処理シート(Object)
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年12月02日
    '* 作成者 :井上 治
    '* 更新日 :2017年12月02日
    '* 更新者 :井上 治
    '* 機能説明:
    '* 注意事項:サンプルという都合上、エラー(例外)処理は行なっていません
    '***********************************************************************************************
    Friend Function SearchFiles(ByRef objSH As Object) As Integer
        '-------------------------------------------------------------------------------------------
        Dim dteStrTime As Date = Now                                ' 探索開始日時
        Dim tblFiles As System.Collections.ObjectModel.ReadOnlyCollection(Of String) = _
            My.Computer.FileSystem.FindInFiles(g_strRootPath, _
                                               g_strSearchWord, _
                                               True, _
                                               FileIO.SearchOption.SearchAllSubDirectories, _
                                               New String() {"*.*"}) ' 探索ファイル群
        '-------------------------------------------------------------------------------------------
        ' 探索ファイル無しは終了
        If ((tblFiles Is Nothing) OrElse (tblFiles.Count = 0)) Then
            Dim dteEndTime2 As Date = Now                           ' 探索終了日時
            g_strMSG = "条件に当てはまるファイルが見つかりませんでした。" & ControlChars.CrLf
            g_strMSG &= " 探索時間秒=" & (dteEndTime2 - dteStrTime).ToString
            Return 9
        End If
        '-------------------------------------------------------------------------------------------
        Dim tblRec() As Object                                      ' JAG配列テーブル
        Dim intTblIx As Integer = -1                                ' テーブルINDEX
        ReDim tblRec(intTblIx)
        ' 探索ファイル群を探索
        For Each strFile As String In tblFiles
            Dim objFileInfo As New FileInfo(strFile)                ' FileInfo
            ' 更新日時判定
            If Not g_blnUseLimitDate OrElse objFileInfo.LastWriteTime >= g_dteLimitDate Then
                ' 検索対象なのでテーブルに格納
                Dim tblFld(2) As Object                             ' レコードテーブル
                tblFld(0) = objFileInfo.Name
                tblFld(1) = objFileInfo.LastWriteTime.ToOADate
                tblFld(2) = objFileInfo.Directory.FullName
                ' JAG配列テーブルに格納
                intTblIx += 1
                ReDim Preserve tblRec(intTblIx)
                tblRec(intTblIx) = tblFld
            End If
        Next strFile
        Dim dteEndTime As Date = Now                                ' 探索終了日時
        '-------------------------------------------------------------------------------------------
        ' 探索ファイル無しは終了
        If intTblIx < 0 Then
            g_strMSG = "条件に当てはまるファイルが見つかりませんでした。" & ControlChars.CrLf
            g_strMSG &= " 探索時間秒=" & (dteEndTime - dteStrTime).ToString
            Return 9
        End If
        '-------------------------------------------------------------------------------------------
        Dim intIx As Integer = 0                                    ' テーブルINDEX
        Dim tblRec2(intTblIx, 2) As Object                          ' 2次元配列テーブル
        ' JAG配列テーブルを2次元配列テーブルに差し替え
        Do While intIx <= intTblIx
            ' 列方向
            For intIx2 As Integer = 0 To 2
                tblRec2(intIx, intIx2) = tblRec(intIx)(intIx2)
            Next intIx2
            ' 次へ
            intIx += 1
        Loop
        '-------------------------------------------------------------------------------------------
        Dim intRow As Integer = intTblIx + 5                        ' 最終行INDEX
        ' ワークシートに展開
        With objSH
            ' 2次元配列テーブルをセル範囲に貼り付け
            .Range(.Cells(5, 1), .Cells(intRow, 3)).Value = tblRec2
            ' 見出し
            .Cells(1, 2).Value = g_strRootPath
            .Cells(2, 2).Value = g_strSearchWord
            ' 更新日時指定有無
            If g_blnUseLimitDate Then
                .Cells(3, 2).Value = g_dteLimitDate
            End If
        End With
        ' メッセージ編集
        g_strMSG = "処理が終了しました。" & ControlChars.CrLf
        g_strMSG &= " ファイル数=" & (intTblIx + 1).ToString & ControlChars.CrLf
        g_strMSG &= " 探索時間秒=" & (dteEndTime - dteStrTime).ToString
        Return 1
    End Function

    '***********************************************************************************************
    ' ■■■ プロパティ ■■■
    '***********************************************************************************************
    ' ルートフォルダ(String)
    '-----------------------------------------------------------------------------------------------
    Friend WriteOnly Property prpRootPath As String
        Set(value As String)
            g_strRootPath = value
        End Set
    End Property

    '===============================================================================================
    ' 検索文字列(String)
    '-----------------------------------------------------------------------------------------------
    Friend WriteOnly Property prpSearchWord As String
        Set(value As String)
            g_strSearchWord = value
        End Set
    End Property

    '===============================================================================================
    ' 更新日時指定有無(Boolean)
    '-----------------------------------------------------------------------------------------------
    Friend WriteOnly Property prpUseLimitDate As Boolean
        Set(value As Boolean)
            g_blnUseLimitDate = value
        End Set
    End Property

    '===============================================================================================
    ' 更新日時指定(Date)
    '-----------------------------------------------------------------------------------------------
    Friend WriteOnly Property prpLimitDate As Date
        Set(value As Date)
            g_dteLimitDate = value
        End Set
    End Property

    '===============================================================================================
    ' メッセージ(String)
    '-----------------------------------------------------------------------------------------------
    Friend ReadOnly Property prpReturnMSG As String
        Get
            Return g_strMSG
        End Get
    End Property

    '----------------------------------------<< End of Source >>------------------------------------
End Class

ASystem.IOの通常のファイル探索(再帰動作)+SearchPattern
AとBは「System.IO」の通常のファイル探索(Directory.GetFiles)なのですが、 Aの方はサブフォルダの探索はこのプログラム上で再帰動作で記述して、1フォルダ内のファイル探索のみパターン検索させています。 Bの方は先頭フォルダのファイル探索(Directory.GetFiles)でサブフォルダまで探索させるオプションを指定しています。

'***************************************************************************************************
'   ファイルを検索してExcelに一覧出力(サンプルA)              clsSearchFilesTEST2(Class)
'
'   System.IOの通常のファイル探索(再帰動作)
'
'   作成者:井上治  URL:http://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
' 変更日付 Rev   変更履歴内容---------------------------------------------------------------------->
' 17/12/09(1.0.0)新規作成
'***************************************************************************************************
Imports System.IO
Friend Class clsSearchFilesTEST2
    '===============================================================================================
    ' 親フォームとの受け渡し変数
    Private g_strRootPath As String = ""                        ' ルートフォルダ
    Private g_strSearchWord As String = ""                      ' 検索文字列
    Private g_blnUseLimitDate As Boolean = False                ' 更新日時指定有無
    Private g_dteLimitDate As Date                              ' 更新日時指定
    Private g_strMSG As String = ""                             ' メッセージ

    '***********************************************************************************************
    ' ■■■ 呼び出しプロシージャ ■■■
    '***********************************************************************************************
    '* 処理名 :SearchFiles
    '* 機能  :ファイルの探索
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :処理結果(Boolean)       ※0=未処理、1=処理成功、9=エラー
    '* 引数  :Arg1 = 処理シート(Object)
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年12月09日
    '* 作成者 :井上 治
    '* 更新日 :2017年12月09日
    '* 更新者 :井上 治
    '* 機能説明:
    '* 注意事項:サンプルという都合上、エラー(例外)処理は行なっていません
    '***********************************************************************************************
    Friend Function SearchFiles(ByRef objSH As Object) As Integer
        '-------------------------------------------------------------------------------------------
        Dim dteStrTime As Date = Now                                ' 探索開始日時
        Dim tblRec() As Object                                      ' JAG配列テーブル
        Dim intTblIx As Integer = -1                                ' テーブルINDEX
        ReDim tblRec(intTblIx)
        '-------------------------------------------------------------------------------------------
        ' ルートフォルダから探索開始
        Call GP_SearchFilesSub(g_strRootPath, intTblIx, tblRec)
        Dim dteEndTime As Date = Now                                ' 探索終了日時
        '-------------------------------------------------------------------------------------------
        ' 探索ファイル無しは終了
        If intTblIx < 0 Then
            g_strMSG = "条件に当てはまるファイルが見つかりませんでした。" & ControlChars.CrLf
            g_strMSG &= " 探索時間秒=" & (dteEndTime - dteStrTime).ToString
            Return 9
        End If
        '-------------------------------------------------------------------------------------------
        Dim intIx As Integer = 0                                    ' テーブルINDEX
        Dim tblRec2(intTblIx, 2) As Object                          ' 2次元配列テーブル
        ' JAG配列テーブルを2次元配列テーブルに差し替え
        Do While intIx <= intTblIx
            ' 列方向
            For intIx2 As Integer = 0 To 2
                tblRec2(intIx, intIx2) = tblRec(intIx)(intIx2)
            Next intIx2
            ' 次へ
            intIx += 1
        Loop
        '-------------------------------------------------------------------------------------------
        Dim intRow As Integer = intTblIx + 5                        ' 最終行INDEX
        ' ワークシートに展開
        With objSH
            ' 2次元配列テーブルをセル範囲に貼り付け
            .Range(.Cells(5, 1), .Cells(intRow, 3)).Value = tblRec2
            ' 見出し
            .Cells(1, 2).Value = g_strRootPath
            .Cells(2, 2).Value = g_strSearchWord
            ' 更新日時指定有無
            If g_blnUseLimitDate Then
                .Cells(3, 2).Value = g_dteLimitDate
            End If
        End With
        ' メッセージ編集
        g_strMSG = "処理が終了しました。" & ControlChars.CrLf
        g_strMSG &= " ファイル数=" & (intTblIx + 1).ToString & ControlChars.CrLf
        g_strMSG &= " 探索時間秒=" & (dteEndTime - dteStrTime).ToString
        Return 1
    End Function

    '***********************************************************************************************
    '* 処理名 :GP_SearchFilesSub
    '* 機能  :ファイルの探索サブ処理(フォルダ単位)
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :(なし)
    '* 引数  :Arg1 = 現在フォルダ(String)
    '*      Arg2 = テーブルINDEX(Integer)
    '*      Arg3 = JAG配列テーブル(Array:Object)
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年12月09日
    '* 作成者 :井上 治
    '* 更新日 :2017年12月09日
    '* 更新者 :井上 治
    '* 機能説明:再帰動作
    '* 注意事項:
    '***********************************************************************************************
    Private Sub GP_SearchFilesSub(ByVal strPathname As String, _
                                  ByRef intTblIx As Integer, _
                                  ByRef tblRec() As Object)
        '-------------------------------------------------------------------------------------------
        ' 本フォルダ配下のサブフォルダを探索
        For Each strSubFolder As String In Directory.GetDirectories(strPathname)
            ' ファイルの探索サブ処理(フォルダ単位)
            Call GP_SearchFilesSub(strSubFolder, intTblIx, tblRec)
        Next strSubFolder
        '-------------------------------------------------------------------------------------------
        ' 更新日時判定使用
        If g_blnUseLimitDate Then
            ' 本フォルダのファイルを探索
            For Each strFilename As String In Directory.GetFiles(strPathname, _
                                                                 g_strSearchWord, _
                                                                 SearchOption.TopDirectoryOnly)
                Dim objFileInfo As New FileInfo(strFilename)            ' FileInfo
                ' 更新日時判定
                If objFileInfo.LastWriteTime >= g_dteLimitDate Then
                    ' 検索対象なのでテーブルに格納
                    Dim tblFld(2) As Object                             ' レコードテーブル
                    tblFld(0) = objFileInfo.Name
                    tblFld(1) = objFileInfo.LastWriteTime.ToOADate
                    tblFld(2) = objFileInfo.Directory.FullName
                    ' JAG配列テーブルに格納
                    intTblIx += 1
                    ReDim Preserve tblRec(intTblIx)
                    tblRec(intTblIx) = tblFld
                End If
            Next strFilename
        Else
            ' 本フォルダのファイルを探索
            For Each strFilename As String In Directory.GetFiles(strPathname, _
                                                                 g_strSearchWord, _
                                                                 SearchOption.TopDirectoryOnly)
                Dim objFileInfo As New FileInfo(strFilename)            ' FileInfo
                ' 検索対象なのでテーブルに格納
                Dim tblFld(2) As Object                                 ' レコードテーブル
                tblFld(0) = objFileInfo.Name
                tblFld(1) = objFileInfo.LastWriteTime.ToOADate
                tblFld(2) = objFileInfo.Directory.FullName
                ' JAG配列テーブルに格納
                intTblIx += 1
                ReDim Preserve tblRec(intTblIx)
                tblRec(intTblIx) = tblFld
            Next strFilename
        End If
    End Sub

    '***********************************************************************************************
    ' ■■■ プロパティ ■■■
    '***********************************************************************************************
    ' ルートフォルダ(String)
    '-----------------------------------------------------------------------------------------------
    Friend WriteOnly Property prpRootPath As String
        Set(value As String)
            g_strRootPath = value
        End Set
    End Property

    '===============================================================================================
    ' 検索文字列(String)
    '-----------------------------------------------------------------------------------------------
    Friend WriteOnly Property prpSearchWord As String
        Set(value As String)
            g_strSearchWord = value
        End Set
    End Property

    '===============================================================================================
    ' 更新日時指定有無(Boolean)
    '-----------------------------------------------------------------------------------------------
    Friend WriteOnly Property prpUseLimitDate As Boolean
        Set(value As Boolean)
            g_blnUseLimitDate = value
        End Set
    End Property

    '===============================================================================================
    ' 更新日時指定(Date)
    '-----------------------------------------------------------------------------------------------
    Friend WriteOnly Property prpLimitDate As Date
        Set(value As Date)
            g_dteLimitDate = value
        End Set
    End Property

    '===============================================================================================
    ' メッセージ(String)
    '-----------------------------------------------------------------------------------------------
    Friend ReadOnly Property prpReturnMSG As String
        Get
            Return g_strMSG
        End Get
    End Property

    '----------------------------------------<< End of Source >>------------------------------------
End Class

BSystem.IOの通常のファイル探索(非再帰動作)+SearchPattern
Aのところで説明してしまいましたが、先頭フォルダの段階でサブフォルダまで探索するオプション「SearchOption.AllDirectories」を指定しており、 「GP_SearchFilesSub」プロシージャは再帰動作ではありません。
大抵の場合、一番速度が速く、おそらくはVBAの「FileSearch」に一番近い方法だろうと思います。

'***************************************************************************************************
'   ファイルを検索してExcelに一覧出力(サンプルB)              clsSearchFilesTEST3(Class)
'
'   System.IOの通常のファイル探索(非再帰動作)
'
'   作成者:井上治  URL:http://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
' 変更日付 Rev   変更履歴内容---------------------------------------------------------------------->
' 17/12/10(1.0.0)新規作成
'***************************************************************************************************
Imports System.IO
Friend Class clsSearchFilesTEST3
    '===============================================================================================
    ' 親フォームとの受け渡し変数
    Private g_strRootPath As String = ""                        ' ルートフォルダ
    Private g_strSearchWord As String = ""                      ' 検索文字列
    Private g_blnUseLimitDate As Boolean = False                ' 更新日時指定有無
    Private g_dteLimitDate As Date                              ' 更新日時指定
    Private g_strMSG As String = ""                             ' メッセージ

    '***********************************************************************************************
    ' ■■■ 呼び出しプロシージャ ■■■
    '***********************************************************************************************
    '* 処理名 :SearchFiles
    '* 機能  :ファイルの探索
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :処理結果(Boolean)       ※0=未処理、1=処理成功、9=エラー
    '* 引数  :Arg1 = 処理シート(Object)
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年12月10日
    '* 作成者 :井上 治
    '* 更新日 :2017年12月10日
    '* 更新者 :井上 治
    '* 機能説明:
    '* 注意事項:サンプルという都合上、エラー(例外)処理は行なっていません
    '***********************************************************************************************
    Friend Function SearchFiles(ByRef objSH As Object) As Integer
        '-------------------------------------------------------------------------------------------
        Dim dteStrTime As Date = Now                                ' 探索開始日時
        Dim tblRec() As Object                                      ' JAG配列テーブル
        Dim intTblIx As Integer = -1                                ' テーブルINDEX
        ReDim tblRec(intTblIx)
        '-------------------------------------------------------------------------------------------
        ' ルートフォルダから探索開始
        Call GP_SearchFilesSub(g_strRootPath, intTblIx, tblRec)
        Dim dteEndTime As Date = Now                                ' 探索終了日時
        '-------------------------------------------------------------------------------------------
        ' 探索ファイル無しは終了
        If intTblIx < 0 Then
            g_strMSG = "条件に当てはまるファイルが見つかりませんでした。" & ControlChars.CrLf
            g_strMSG &= " 探索時間秒=" & (dteEndTime - dteStrTime).ToString
            Return 9
        End If
        '-------------------------------------------------------------------------------------------
        Dim intIx As Integer = 0                                    ' テーブルINDEX
        Dim tblRec2(intTblIx, 2) As Object                          ' 2次元配列テーブル
        ' JAG配列テーブルを2次元配列テーブルに差し替え
        Do While intIx <= intTblIx
            ' 列方向
            For intIx2 As Integer = 0 To 2
                tblRec2(intIx, intIx2) = tblRec(intIx)(intIx2)
            Next intIx2
            ' 次へ
            intIx += 1
        Loop
        '-------------------------------------------------------------------------------------------
        Dim intRow As Integer = intTblIx + 5                        ' 最終行INDEX
        ' ワークシートに展開
        With objSH
            ' 2次元配列テーブルをセル範囲に貼り付け
            .Range(.Cells(5, 1), .Cells(intRow, 3)).Value = tblRec2
            ' 見出し
            .Cells(1, 2).Value = g_strRootPath
            .Cells(2, 2).Value = g_strSearchWord
            ' 更新日時指定有無
            If g_blnUseLimitDate Then
                .Cells(3, 2).Value = g_dteLimitDate
            End If
        End With
        ' メッセージ編集
        g_strMSG = "処理が終了しました。" & ControlChars.CrLf
        g_strMSG &= " ファイル数=" & (intTblIx + 1).ToString & ControlChars.CrLf
        g_strMSG &= " 探索時間秒=" & (dteEndTime - dteStrTime).ToString
        Return 1
    End Function

    '***********************************************************************************************
    '* 処理名 :GP_SearchFilesSub
    '* 機能  :ファイルの探索サブ処理
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :(なし)
    '* 引数  :Arg1 = 現在フォルダ(String)
    '*      Arg2 = テーブルINDEX(Integer)
    '*      Arg3 = JAG配列テーブル(Array:Object)
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年12月10日
    '* 作成者 :井上 治
    '* 更新日 :2017年12月10日
    '* 更新者 :井上 治
    '* 機能説明:
    '* 注意事項:
    '***********************************************************************************************
    Private Sub GP_SearchFilesSub(ByVal strPathname As String, _
                                  ByRef intTblIx As Integer, _
                                  ByRef tblRec() As Object)
        '-------------------------------------------------------------------------------------------
        ' 更新日時判定使用
        If g_blnUseLimitDate Then
            ' 本フォルダのファイルを探索
            For Each strFilename As String In Directory.GetFiles(strPathname, _
                                                                 g_strSearchWord, _
                                                                 SearchOption.AllDirectories)
                Dim objFileInfo As New FileInfo(strFilename)            ' FileInfo
                ' 更新日時判定
                If objFileInfo.LastWriteTime >= g_dteLimitDate Then
                    ' 検索対象なのでテーブルに格納
                    Dim tblFld(2) As Object                             ' レコードテーブル
                    tblFld(0) = objFileInfo.Name
                    tblFld(1) = objFileInfo.LastWriteTime.ToOADate
                    tblFld(2) = objFileInfo.Directory.FullName
                    ' JAG配列テーブルに格納
                    intTblIx += 1
                    ReDim Preserve tblRec(intTblIx)
                    tblRec(intTblIx) = tblFld
                End If
            Next strFilename
        Else
            ' 本フォルダのファイルを探索
            For Each strFilename As String In Directory.GetFiles(strPathname, _
                                                                 g_strSearchWord, _
                                                                 SearchOption.AllDirectories)
                Dim objFileInfo As New FileInfo(strFilename)            ' FileInfo
                ' 検索対象なのでテーブルに格納
                Dim tblFld(2) As Object                                 ' レコードテーブル
                tblFld(0) = objFileInfo.Name
                tblFld(1) = objFileInfo.LastWriteTime.ToOADate
                tblFld(2) = objFileInfo.Directory.FullName
                ' JAG配列テーブルに格納
                intTblIx += 1
                ReDim Preserve tblRec(intTblIx)
                tblRec(intTblIx) = tblFld
            Next strFilename
        End If
    End Sub

    '***********************************************************************************************
    ' ■■■ プロパティ ■■■
    '***********************************************************************************************
    ' ルートフォルダ(String)
    '-----------------------------------------------------------------------------------------------
    Friend WriteOnly Property prpRootPath As String
        Set(value As String)
            g_strRootPath = value
        End Set
    End Property

    '===============================================================================================
    ' 検索文字列(String)
    '-----------------------------------------------------------------------------------------------
    Friend WriteOnly Property prpSearchWord As String
        Set(value As String)
            g_strSearchWord = value
        End Set
    End Property

    '===============================================================================================
    ' 更新日時指定有無(Boolean)
    '-----------------------------------------------------------------------------------------------
    Friend WriteOnly Property prpUseLimitDate As Boolean
        Set(value As Boolean)
            g_blnUseLimitDate = value
        End Set
    End Property

    '===============================================================================================
    ' 更新日時指定(Date)
    '-----------------------------------------------------------------------------------------------
    Friend WriteOnly Property prpLimitDate As Date
        Set(value As Date)
            g_dteLimitDate = value
        End Set
    End Property

    '===============================================================================================
    ' メッセージ(String)
    '-----------------------------------------------------------------------------------------------
    Friend ReadOnly Property prpReturnMSG As String
        Get
            Return g_strMSG
        End Get
    End Property

    '----------------------------------------<< End of Source >>------------------------------------
End Class

CFileSystemObject(VBA同様の再帰動作)+ファイル名Like判定
VBAFileSystemObjectを使って再帰動作でファイル探索する方法をそのままVB.NETで再現させてみたものです。 他の方法との速度比較に用いて下さい。

'***************************************************************************************************
'   ファイルを検索してExcelに一覧出力(サンプルC)              clsSearchFilesTEST4(Class)
'
'   FileSystemObject
'
'   作成者:井上治  URL:http://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
' 変更日付 Rev   変更履歴内容---------------------------------------------------------------------->
' 17/12/02(1.0.0)新規作成
'***************************************************************************************************
Imports Scripting
Imports System.Runtime.InteropServices
Friend Class clsSearchFilesTEST4
    '===============================================================================================
    ' 親フォームとの受け渡し変数
    Private g_strRootPath As String = ""                        ' ルートフォルダ
    Private g_strSearchWord As String = ""                      ' 検索文字列
    Private g_blnUseLimitDate As Boolean = False                ' 更新日時指定有無
    Private g_dteLimitDate As Date                              ' 更新日時指定
    Private g_strMSG As String = ""                             ' メッセージ

    '***********************************************************************************************
    ' ■■■ 呼び出しプロシージャ ■■■
    '***********************************************************************************************
    '* 処理名 :SearchFiles
    '* 機能  :ファイルの探索
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :処理結果(Boolean)       ※0=未処理、1=処理成功、9=エラー
    '* 引数  :Arg1 = 処理シート(Object)
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年12月09日
    '* 作成者 :井上 治
    '* 更新日 :2017年12月09日
    '* 更新者 :井上 治
    '* 機能説明:
    '* 注意事項:サンプルという都合上、エラー(例外)処理は行なっていません
    '***********************************************************************************************
    Friend Function SearchFiles(ByRef objSH As Object) As Integer
        '-------------------------------------------------------------------------------------------
        Dim objFSO As FileSystemObject                              ' FileSystemObject
        Dim dteStrTime As Date = Now                                ' 探索開始日時
        Dim tblRec() As Object                                      ' JAG配列テーブル
        Dim intTblIx As Integer = -1                                ' テーブルINDEX
        ReDim tblRec(intTblIx)
        objFSO = New FileSystemObject
        '-------------------------------------------------------------------------------------------
        ' ルートフォルダから探索開始
        Call GP_SearchFilesSub(objFSO, objFSO.GetFolder(g_strRootPath), intTblIx, tblRec)
        ' COMオブジェクトの解放
        Call GP_ReleaseComObject(objFSO)
        Dim dteEndTime As Date = Now                                ' 探索終了日時
        '-------------------------------------------------------------------------------------------
        ' 探索ファイル無しは終了
        If intTblIx < 0 Then
            g_strMSG = "条件に当てはまるファイルが見つかりませんでした。" & ControlChars.CrLf
            g_strMSG &= " 探索時間秒=" & (dteEndTime - dteStrTime).ToString
            Return 9
        End If
        '-------------------------------------------------------------------------------------------
        Dim intIx As Integer = 0                                    ' テーブルINDEX
        Dim tblRec2(intTblIx, 2) As Object                          ' 2次元配列テーブル
        ' JAG配列テーブルを2次元配列テーブルに差し替え
        Do While intIx <= intTblIx
            ' 列方向
            For intIx2 As Integer = 0 To 2
                tblRec2(intIx, intIx2) = tblRec(intIx)(intIx2)
            Next intIx2
            ' 次へ
            intIx += 1
        Loop
        '-------------------------------------------------------------------------------------------
        Dim intRow As Integer = intTblIx + 5                        ' 最終行INDEX
        ' ワークシートに展開
        With objSH
            ' 2次元配列テーブルをセル範囲に貼り付け
            .Range(.Cells(5, 1), .Cells(intRow, 3)).Value = tblRec2
            ' 見出し
            .Cells(1, 2).Value = g_strRootPath
            .Cells(2, 2).Value = g_strSearchWord
            ' 更新日時指定有無
            If g_blnUseLimitDate Then
                .Cells(3, 2).Value = g_dteLimitDate
            End If
        End With
        ' メッセージ編集
        g_strMSG = "処理が終了しました。" & ControlChars.CrLf
        g_strMSG &= " ファイル数=" & (intTblIx + 1).ToString & ControlChars.CrLf
        g_strMSG &= " 探索時間秒=" & (dteEndTime - dteStrTime).ToString
        Return 1
    End Function

    '***********************************************************************************************
    '* 処理名 :GP_SearchFilesSub
    '* 機能  :ファイルの探索サブ処理(フォルダ単位)
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :(なし)
    '* 引数  :Arg1 = FileSystemObject(Object)
    '*      Arg2 = Folder(Object)
    '*      Arg3 = テーブルINDEX(Integer)
    '*      Arg4 = JAG配列テーブル(Array:Object)
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年12月09日
    '* 作成者 :井上 治
    '* 更新日 :2017年12月09日
    '* 更新者 :井上 治
    '* 機能説明:再帰動作
    '* 注意事項:
    '***********************************************************************************************
    Private Sub GP_SearchFilesSub(ByRef objFSO As FileSystemObject, _
                                  ByVal objFolder As Folder, _
                                  ByRef intTblIx As Integer, _
                                  ByRef tblRec() As Object)
        '-------------------------------------------------------------------------------------------
        ' 本フォルダ配下のサブフォルダを探索
        For Each objFolder2 As Folder In objFolder.SubFolders
            ' ファイルの探索サブ処理(フォルダ単位)
            Call GP_SearchFilesSub(objFSO, objFolder2, intTblIx, tblRec)
        Next objFolder2
        '-------------------------------------------------------------------------------------------
        ' 更新日時判定使用
        If g_blnUseLimitDate Then
            ' 本フォルダのファイルを探索
            For Each objFile As File In objFolder.Files
                Dim strFileU As String = objFile.Name.ToUpper       ' ファイル名(大文字)
                ' LIKE判定
                If strFileU Like g_strSearchWord Then
                    ' 更新日時判定
                    If objFile.DateLastModified >= g_dteLimitDate Then
                        ' 検索対象なのでテーブルに格納
                        Dim tblFld(2) As Object                     ' レコードテーブル
                        With objFile
                            Dim strPath As String = _
                                Left(.Path, Len(.Path) - Len(.Name) - 1) ' フォルダ名
                            tblFld(0) = .Name
                            tblFld(1) = .DateLastModified
                            tblFld(2) = strPath
                        End With
                        ' JAG配列テーブルに格納
                        intTblIx += 1
                        ReDim Preserve tblRec(intTblIx)
                        tblRec(intTblIx) = tblFld
                    End If
                End If
            Next objFile
        Else
            ' 本フォルダのファイルを探索
            For Each objFile As File In objFolder.Files
                Dim strFileU As String = objFile.Name.ToUpper       ' ファイル名(大文字)
                ' LIKE判定
                If strFileU Like g_strSearchWord Then
                    ' 検索対象なのでテーブルに格納
                    Dim tblFld(2) As Object                         ' レコードテーブル
                    With objFile
                        Dim strPath As String = _
                            Left(.Path, Len(.Path) - Len(.Name) - 1) ' フォルダ名
                        tblFld(0) = .Name
                        tblFld(1) = .DateLastModified
                        tblFld(2) = strPath
                    End With
                    ' JAG配列テーブルに格納
                    intTblIx += 1
                    ReDim Preserve tblRec(intTblIx)
                    tblRec(intTblIx) = tblFld
                End If
            Next objFile
        End If
    End Sub

    '***********************************************************************************************
    ' ■■■ 共通サブ処理 ■■■
    '***********************************************************************************************
    '* 処理名 :GP_ReleaseComObject
    '* 機能  :COMオブジェクトの解放
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :(なし)
    '* 引数  :Arg1 = COMオブジェクト(Object)
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年12月09日
    '* 作成者 :井上 治
    '* 更新日 :2017年12月09日
    '* 更新者 :井上 治
    '* 機能説明:
    '* 注意事項:Imports System.Runtime.InteropServices
    '***********************************************************************************************
    Friend Sub GP_ReleaseComObject(ByRef objCOM As Object)
        '-------------------------------------------------------------------------------------------
        ' 明示的にCOMオブジェクトへの参照を解放する
        Try
            ' ランタイム呼び出し可能ラッパーの参照カウントをデクリメント
            If ((Not objCOM Is Nothing) AndAlso (Marshal.IsComObject(objCOM))) Then
                Marshal.FinalReleaseComObject(objCOM)
            End If
        Finally
            ' 参照を解除する
            objCOM = Nothing
        End Try
    End Sub

    '***********************************************************************************************
    ' ■■■ プロパティ ■■■
    '***********************************************************************************************
    ' ルートフォルダ(String)
    '-----------------------------------------------------------------------------------------------
    Friend WriteOnly Property prpRootPath As String
        Set(value As String)
            g_strRootPath = value
        End Set
    End Property

    '===============================================================================================
    ' 検索文字列(String)
    '-----------------------------------------------------------------------------------------------
    Friend WriteOnly Property prpSearchWord As String
        Set(value As String)
            g_strSearchWord = value.ToUpper
        End Set
    End Property

    '===============================================================================================
    ' 更新日時指定有無(Boolean)
    '-----------------------------------------------------------------------------------------------
    Friend WriteOnly Property prpUseLimitDate As Boolean
        Set(value As Boolean)
            g_blnUseLimitDate = value
        End Set
    End Property

    '===============================================================================================
    ' 更新日時指定(Date)
    '-----------------------------------------------------------------------------------------------
    Friend WriteOnly Property prpLimitDate As Date
        Set(value As Date)
            g_dteLimitDate = value
        End Set
    End Property

    '===============================================================================================
    ' メッセージ(String)
    '-----------------------------------------------------------------------------------------------
    Friend ReadOnly Property prpReturnMSG As String
        Get
            Return g_strMSG
        End Get
    End Property

    '----------------------------------------<< End of Source >>------------------------------------
End Class