NonSoft

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

 サンプルソース
<このサンプルの概要>
ごみ箱の中のファイルやフォルダの一覧を取得するサンプルです。
ShellClassで一覧を取得し、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)

関連情報
古いごみ削除ツール(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
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()

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