1

I am creating a console app that will delete pictures from a directory every 30 minutes. Problem is that its being populated by files every minute or so. So if I go and delete files in that directory then it may cause an error trying to delete a file thats being created just then or opened.

I currently have this code to copy the files to another directory and then delete them from the source directory.

Dim f() As String = Directory.GetFiles(sourceDir)

    For i As Integer = 0 To UBound(f)
        'Check file date here in IF statement FIRST...

        File.Copy(f(i), destDir & f(i).Replace(sourceDir, ""))

        If File.Exists(f(i)) = True Then
              File.Delete(f(i))
        End If

        Debug.Print(f(i) & " to >>> " & destDir & f(i).Replace(sourceDir, ""))
    Next

How can I use:

File.GetCreationTime(f(i))

in an IF statement checking IF the currently file its on is newer than 30 seconds ago?

OR

Is there a way of only populating:

 Dim f() As String = Directory.GetFiles(sourceDir)

with only those files that are more than 30 seconds old?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
StealthRT
  • 10,108
  • 40
  • 183
  • 342

2 Answers2

2

There isn't a reliable way to detect if a file is locked or not. Even if you did find out (it is technically possible), it could be locked before you tried to delete it. There are other reasons a delete may fail. In your case, I don't think it matters what the reason was.

The only way is to put the call to delete in a try/catch and trap IOException, and then retry if you want.

You need to use a FileInfo object to get the CreatedTime and compare to Now. You can also use LastAccessTime or LastWriteTime, but since these are all new files being written then, you don't need to.

Private Sub DeleteFiles()
    Dim files = From f In Directory.GetFiles("c:\temp")
                Let fi = New FileInfo(f) 
                Where fi.Exists AndAlso fi.CreationTime <= DateTime.Now.AddSeconds(-30)

    For Each f In files
        Try
            f.Delete()
        Catch ex As Exception
            If TypeOf ex Is IOException AndAlso IsFileLocked(ex) Then
                ' do something? 
            End If
            'otherwise we just ignore it.  we will pick it up on the next pass
        End Try
    Next   
End Sub

Private Shared Function IsFileLocked(exception As Exception) As Boolean
    Dim errorCode As Integer = Marshal.GetHRForException(exception) And ((1 << 16) - 1)
    Return errorCode = 32 OrElse errorCode = 33
End Function

IsFileLocked function lifted from this other thread on SO

Community
  • 1
  • 1
Andrew
  • 8,322
  • 2
  • 47
  • 70
1
Dim NewFileDate As DateTime = DateTime.Now.AddSeconds(-30)
' get the list of all files in FileDir
Dim PicFiles As List(Of String) = System.IO.Directory.GetFiles("C:\", "*.txt").ToList()
' filter the list to only include files older than NewFileDate
Dim OutputList As List(Of String) = PicFiles.Where(Function(x) System.IO.File.GetCreationTime(x) < NewFileDate).ToList()
' delete files in the list
For Each PicFile As String In OutputList
    'wrap this next line in a Try-Catch if you find there is file locking.
    System.IO.File.Delete(PicFile)
Next

Obviously targeting .Net 3.5 or 4.0

Jeremy Thompson
  • 61,933
  • 36
  • 195
  • 321
  • I have an overload on line **PicFiles.Where(Function(x) System.IO.File.GetCreationTime(x) < NewFileDate).ToList()** the error is **Overload resolution failed because no accessible 'Where' can be called with these arguments: Extension method 'Public Function Where(predicate As System.Func(Of String, Integer, Boolean)) As System.Collections.Generic.IEnumerable(Of String)' defined in 'System.Linq.Enumerable':.** – StealthRT Apr 20 '12 at 04:14
  • What does **NewFileDate** need to be? – StealthRT Apr 20 '12 at 04:20
  • Dim NewFileDate As DateTime = DateTime.Now.AddSeconds(-30) – Jeremy Thompson Apr 20 '12 at 04:22