NonSoft

ごみ箱の中のファイルやフォルダの一覧
を取得するサンプル(VB.NET)


 サンプル(ソース/コード)
<このサンプルの概要>
ごみ箱の中のファイルやフォルダの一覧を取得するサンプル(VB.NET)です。
ShellClassで一覧を取得し、INFO(またはINFO2)ファイルから削除元ファイル名や削除日時を取得します。

※WindowsVista(Windows7/Windows8)以降にはINFO(またはINFO2)ファイルが無いので、
※INFO(またはINFO2)ファイルを使用しないサンプルも用意しました。

参照設定で「Microsoft Shell Controls And Automation」というCOMを追加しています。

<INFO(またはINFO2)ファイルについての補足>
ごみ箱の中にはINFO(またはINFO2)という隠しファイルがあり、削除元のPATHを保存しています。
このファイルは「ごみ箱を空にする(B)」という操作を行なうまで拡大を続けますので、
年に1回ぐらいは「ごみ箱を空にする(B)」を実行した方が良いと思います。
INFO(またはINFO2)には以下の項目が保存してあります。
・ヘッダー部分
  (1)バージョン(INFO=1、INFO2=4or5...)
  (2)ファイル数(...)
  (3)ファイルINDEX(...)
  (4)INFOファイルのファイルやフォルダ部分のサイズ(280or800)
  (5)ゴミ箱のディスクサイズ(...)
・ファイルやフォルダごとの部分
 (1)元の場所PATH(ショート、SHIFT-JIS)
 (2)ファイルやフォルダINDEX
 (3)ドライブ番号(C=2、D=3...)
 (4)削除日時
 (5)ファイルやフォルダのディスクサイズ
 (6)元の場所PATH(ロング、UNICODE)

C#.NET版はこちら「ごみ箱の中のファイルやフォルダの一覧を取得するサンプル(C#.NET)」です。

関連情報:
古いごみ削除ツール(NonRccDel)
スタートアップやタスクに登録してごみ箱の中の古い(指定日数を経過)ファイルやフォルダを削除

★標準モジュール(Module1.vb)
Imports System.IO
Imports Shell32

Module Module1
    ''' <summary>
    ''' ごみ箱の中のファイルやフォルダの一覧(配列)を取得
    ''' </summary>
    ''' <returns>ごみ箱の中の一覧(配列</returns>
    ''' <remarks></remarks>
    Public Function GetRecyclerList() As String(,)
        Dim rtnAry As String(,) = New String(1, -1) {}
        Dim sr As Stream = Nothing
        Dim br As BinaryReader = Nothing
        Try
            ' 処理中のINFOファイルPATH
            Dim inf As String = ""

            ' INFOファイル読込用
            Dim dat() As Byte = New Byte(-1) {}

            ' Shell32の宣言
            Dim shl As New ShellClass()

            ' ゴミ箱フォルダの情報取得
            Dim fol As Folder = shl.NameSpace(10)

            For Each FolderItem As FolderItem In fol.Items()
                ' ゴミ箱内のファイルやフォルダ毎の処理
                Dim sumi As Boolean = False
                Dim rpt As String = FolderItem.Path
                Dim rfn As String = Path.GetFileNameWithoutExtension(rpt)
                Dim rif As String = Path.GetDirectoryName(rpt) & "\INFO2"
                If File.Exists(rif) = False Then
                    rif = Path.GetDirectoryName(rpt) & "\INFO"
                End If
                ' INFOファイルが存在しなければ終了
                If File.Exists(rif) = False Then
                    Continue For
                End If

                ' 処理中のINFOチェック
                If inf <> rif Then
                    ' 処理中のINFOファイルのPATH設定
                    inf = rif
                    ' INFOファイル読込
                    sr = File.Open(inf, FileMode.Open, FileAccess.Read)
                    br = New BinaryReader(sr)
                    ReDim dat(sr.Length - 1)
                    dat = br.ReadBytes(sr.Length)
                    If br Is Nothing = False Then br.Close()
                    If sr Is Nothing = False Then sr.Close()
                End If

                ' INFOファイルのフォーマットが不正の時は終了
                If dat.Length < 20 Then
                    Continue For
                End If

                ' INFOファイル解析(ヘッダー部分)
                ' バージョン(INFO=1、INFO2=4or5...)
                Dim p As Integer = 0
                Dim version As UInteger = _
                    CType(dat(p + 3), UInteger) * 256 * 256 * 256 + _
                    CType(dat(p + 2), UInteger) * 256 * 256 + _
                    CType(dat(p + 1), UInteger) * 256 + _
                    CType(dat(p + 0), UInteger)
                ' ファイル数(...)
                p += 4
                Dim pathCount As UInteger = _
                    CType(dat(p + 3), UInteger) * 256 * 256 * 256 + _
                    CType(dat(p + 2), UInteger) * 256 * 256 + _
                    CType(dat(p + 1), UInteger) * 256 + _
                    CType(dat(p + 0), UInteger)
                ' ファイルINDEX(...)
                p += 4
                Dim nextIndex As UInteger = _
                    CType(dat(p + 3), UInteger) * 256 * 256 * 256 + _
                    CType(dat(p + 2), UInteger) * 256 * 256 + _
                    CType(dat(p + 1), UInteger) * 256 + _
                    CType(dat(p + 0), UInteger)
                ' INFOファイルのファイルやフォルダ部分のサイズ(280or800)
                p += 4
                Dim recSize As UInteger = _
                    CType(dat(p + 3), UInteger) * 256 * 256 * 256 + _
                    CType(dat(p + 2), UInteger) * 256 * 256 + _
                    CType(dat(p + 1), UInteger) * 256 + _
                    CType(dat(p + 0), UInteger)
                ' ゴミ箱のディスクサイズ(...)
                p += 4
                Dim allDiskSize As UInteger = _
                    CType(dat(p + 3), UInteger) * 256 * 256 * 256 + _
                    CType(dat(p + 2), UInteger) * 256 * 256 + _
                    CType(dat(p + 1), UInteger) * 256 + _
                    CType(dat(p + 0), UInteger)
                p += 4

                ' INFOファイル(ファイルやフォルダ部分)解析
                Dim pd As Integer = p
                'For hs As Integer = pd To dat.Length - recSize Step recSize
                For hs As Integer = dat.Length - recSize To pd Step -recSize
                    p = hs

                    ' 元の場所PATH(ショート、SHIFT-JIS)
                    Dim dat2 As Byte() = New Byte(259) {}
                    Array.Copy(dat, p, dat2, 0, dat2.Length)
                    Dim orgPath As String = _
                        System.Text.Encoding.GetEncoding("SHIFT-JIS").GetString(dat2)
                    If orgPath.IndexOf(Chr(0)) = 0 Then
                        orgPath = inf.Substring(0, 1) & orgPath.Substring(1)
                    End If
                    If orgPath.IndexOf(Chr(0)) > 0 Then
                        orgPath = orgPath.Substring(0, orgPath.IndexOf(Chr(0)))
                    End If
                    p += dat2.Length

                    ' ファイルやフォルダINDEX
                    Dim index As UInteger = _
                        CType(dat(p + 3), UInteger) * 256 * 256 * 256 + _
                        CType(dat(p + 2), UInteger) * 256 * 256 + _
                        CType(dat(p + 1), UInteger) * 256 + _
                        CType(dat(p + 0), UInteger)
                    p += 4

                    ' ドライブ番号(C=2、D=3...)
                    Dim driveNumber As UInteger = _
                        CType(dat(p + 3), UInteger) * 256 * 256 * 256 + _
                        CType(dat(p + 2), UInteger) * 256 * 256 + _
                        CType(dat(p + 1), UInteger) * 256 + _
                        CType(dat(p + 0), UInteger)
                    p += 4

                    ' 削除日時
                    Dim deletedDt As Long = _
                        CType(dat(p + 7), Long) * 256 * 256 * 256 * 256 * 256 * 256 * 256 + _
                        CType(dat(p + 6), Long) * 256 * 256 * 256 * 256 * 256 * 256 + _
                        CType(dat(p + 5), Long) * 256 * 256 * 256 * 256 * 256 + _
                        CType(dat(p + 4), Long) * 256 * 256 * 256 * 256 + _
                        CType(dat(p + 3), Long) * 256 * 256 * 256 + _
                        CType(dat(p + 2), Long) * 256 * 256 + _
                        CType(dat(p + 1), Long) * 256 + _
                        CType(dat(p + 0), Long)
                    p += 8

                    ' ファイルやフォルダのディスクサイズ
                    Dim pathDiskSize As UInteger = _
                        CType(dat(p + 3), UInteger) * 256 * 256 * 256 + _
                        CType(dat(p + 2), UInteger) * 256 * 256 + _
                        CType(dat(p + 1), UInteger) * 256 + _
                        CType(dat(p + 0), UInteger)
                    p += 4

                    ' 元の場所PATH(ロング、UNICODE)
                    If recSize - (p - hs) > 0 Then
                        ReDim dat2(recSize - (p - hs) - 1)
                        Array.Copy(dat, p, dat2, 0, dat2.Length)
                        orgPath = System.Text.Encoding.GetEncoding("UNICODE").GetString(dat2)
                        If orgPath.IndexOf(Chr(0)) = 0 Then
                            orgPath = inf.Substring(0, 1) & orgPath.Substring(1)
                        End If
                        If orgPath.IndexOf(Chr(0)) > 0 Then
                            orgPath = orgPath.Substring(0, orgPath.IndexOf(Chr(0)))
                        End If
                    End If

                    ' INFOファイル内のINDEXとごみ箱内のファイル名が一致するかチェック
                    Dim rfn2 As String = "D" & inf.Substring(0, 1) & index
                    If rfn.ToLower = rfn2.ToLower Then
                        ' 一致した場合は、元の場所PATHを取得
                        ReDim Preserve rtnAry(1, UBound(rtnAry, 2) + 1)
                        rtnAry(0, UBound(rtnAry, 2)) = rpt
                        rtnAry(1, UBound(rtnAry, 2)) = orgPath
                        Exit For
                    End If
                Next
            Next

        Catch ex As Exception
            Throw ex
        Finally
            If br Is Nothing = False Then br.Close()
            If sr Is Nothing = False Then sr.Close()
        End Try
        Return rtnAry
    End Function

    ''' <summary>
    ''' ごみ箱の中のファイルやフォルダの一覧(配列)を取得
    ''' </summary>
    ''' <returns>ごみ箱の中の一覧(配列</returns>
    ''' <remarks>INFOファイルが無いOSの場合(WindowsVista(Win7/Win8)以降)</remarks>
    Public Function GetRecyclerList2() As String(,)
        Dim rtnAry As String(,) = New String(1, -1) {}

        ' Shell32の宣言
        Dim shl As New ShellClass()

        ' ゴミ箱フォルダの情報取得
        Dim fol As Folder = shl.NameSpace(10)

        For Each FolderItem As FolderItem In fol.Items()
            ' ゴミ箱内のファイルやフォルダ毎の処理

            ' ごみ箱内のPATHを取得
            ReDim Preserve rtnAry(1, UBound(rtnAry, 2) + 1)
            Dim rpt As String = FolderItem.Path

            ' 元の場所のPATHを取得
            Dim opt As String = fol.GetDetailsOf(FolderItem, 1)
            If opt.Substring(opt.Length - 1, 1) <> "\" Then opt = opt & "\"
            opt = opt & fol.GetDetailsOf(FolderItem, 0)
            If Path.GetExtension(opt) <> Path.GetExtension(rpt) Then
                opt = opt & Path.GetExtension(rpt)
            End If
            rtnAry(0, UBound(rtnAry, 2)) = rpt
            rtnAry(1, UBound(rtnAry, 2)) = opt

            ' 名前
            System.Diagnostics.Debug.WriteLine("名前:" & fol.GetDetailsOf(FolderItem, 0))

            ' 元の場所
            System.Diagnostics.Debug.WriteLine("元の場所:" & fol.GetDetailsOf(FolderItem, 1))

            ' 削除した日
            System.Diagnostics.Debug.WriteLine("削除した日:" & fol.GetDetailsOf(FolderItem, 2))

            ' サイズ
            System.Diagnostics.Debug.WriteLine("サイズ:" & fol.GetDetailsOf(FolderItem, 3))

            ' 種類
            System.Diagnostics.Debug.WriteLine("種類:" & fol.GetDetailsOf(FolderItem, 4))

            ' 更新日時
            System.Diagnostics.Debug.WriteLine("更新日時:" & fol.GetDetailsOf(FolderItem, 5))

            ' 作成日時
            System.Diagnostics.Debug.WriteLine("作成日時:" & fol.GetDetailsOf(FolderItem, 6))
        Next

        Return rtnAry
    End Function
End Module

★フォームモジュール(Form1.vb)
    Private Sub Button1_Click( _
            ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        ' フォルダ内のファイルやフォルダの一覧(配列)取得
        Dim flist As String(,) = GetRecyclerList()

        ' INFOファイルが無いOSの場合(WindowsVista以降(Win7/Win8))はGetRecyclerList2
        'Dim flist As String(,) = GetRecyclerList2()


        ' ファイルやフォルダの一覧(配列)を出力
        For i As Integer = 0 To UBound(flist, 2)
            System.Diagnostics.Debug.WriteLine(flist(0, i) & "," & flist(1, i))
        Next
    End Sub