Solved

'Process cannot access the file' IOException upon attempted file deletion

Posted on 2004-04-27
11
281 Views
Last Modified: 2012-08-13
Hello,

Extremely irritatingly, I'm having problems trying to delete a file that has previously had work done upon it through GDI+. I make sure that any references to the file are correctly disposed of, but I still receive a "The process cannot access the file because it is being used by another process" error when attempting its deletion.

A summary of the code is below:

        Dim fullPath As String = "..." ' path to input file

        If File.Exists(Server.MapPath(fullPath)) Then
            Dim inputImage As Image = Image.FromFile(Server.MapPath(fullPath))
            Dim originalWidth As Integer = inputImage.Width
            Dim originalHeight As Integer = inputImage.Height
            Dim originalFormat As Imaging.ImageFormat = inputImage.RawFormat
            Dim tempBitmap As Bitmap

            ' crop left-hand side of image
            If Request.QueryString("cropleft") <> "" Then
                If Request.QueryString("cropleft") > 0 Then
                    Dim cropLeft As Integer = Request.QueryString("cropleft")

                    ' define new width of preview
                    originalWidth = originalWidth - cropLeft

                    ' define new image size
                    tempBitmap = New Bitmap(inputImage.Width - cropLeft, inputImage.Height)
                    Dim g As Graphics = Graphics.FromImage(tempBitmap)

                    ' overloaded definition #27:
                    g.DrawImage(inputImage, New Rectangle(0, 0, tempBitmap.Width, tempBitmap.Height), cropLeft, 0, tempBitmap.Width, tempBitmap.Height, GraphicsUnit.Pixel)
                    g.Dispose()

                    ' reassign input image
                    inputImage = tempBitmap
                End If
            End If

            ' this cropping is repeated for the other dimensions
            ' here...

            ' define the output in the given dimensions
            Dim outputImage As New Bitmap(inputImage, originalWidth, originalHeight)
 
            ' rotate the image if requested
            If Request.QueryString("rotate") <> "" Then
                Dim flipType As RotateFlipType
                Select Case Request.QueryString("rotate")
                    Case "left"
                        flipType = RotateFlipType.Rotate270FlipNone
                    Case "right"
                        flipType = RotateFlipType.Rotate90FlipNone
                End Select

                If flipType > 0 Then
                    outputImage.RotateFlip(flipType)
                End If
            End If

            ' save back to temp file
            Dim newPath As String = "..." ' original path again
            outputImage.Save(newPath & ".temp", originalFormat)

            ' tidy up  
            tempBitmap.Dispose()
            inputImage.Dispose()
            outputImage.Dispose()

            ' wait a bit because file is not released rightaway
            Dim thenTicks As Long = Now.AddSeconds(10).Ticks  ' I have even put this wait up to 30+ seconds but it makes no difference...
                                                              ' Surely I don't need a looping try/catch until this passes?
            While Now.Ticks < thenTicks
                Dim spin As String = "spinning"
            End While

            ' overwrite old file with the new
            Dim fi As New FileInfo(newPath)
            fi.MoveTo(newPath & ".old") ' this fails with the Exception mentioned above
            ' fi.Delete fails, as well as CopyTo below, with the 'overwrite file' boolean as True


            ' don't even get as far as below due to exception, so update file
            fi = New FileInfo(newPath & ".temp")
            fi.CopyTo(newPath)
            fi.Delete()

       End If

Can anyone see any obvious problems with this? I had similar problems in a separate part of the Application at an earlier date, but the wait of ten seconds for files to be released did the job. However, GDI+ was not being used in the latter situation, just IO.

Thanks in advance,

Wolfy
0
Comment
Question by:WolfyUK
  • 6
  • 3
  • 2
11 Comments
 
LVL 37

Assisted Solution

by:gregoryyoung
gregoryyoung earned 153 total points
ID: 10932266
inputimage is coming from Image.FromFile()

image.FromFile will retain a lock until it is disposed ...

inputImage = tempBitmap is being reassigned and as such not disposed.
0
 
LVL 2

Expert Comment

by:Jeffr0
ID: 10932386
Hi.  I just took your code and altered it to work on my machine-- just changed the file paths and added a couple of variables.

When I run it, it does the modifications to Picture.bmp... saves it as NewVersion.bmp... and then renames the new file to NewVersion.bmp.old.  This works with no errors with or without the timer.


        Dim fullPath As String = "C:\Picture.bmp"

        If File.Exists(fullPath) Then
            Dim inputImage As Image = Image.FromFile(fullPath)
            Dim originalWidth As Integer = inputImage.Width
            Dim originalHeight As Integer = inputImage.Height
            Dim originalFormat As Imaging.ImageFormat = inputImage.RawFormat
            Dim tempBitmap As Bitmap

            Dim CropLeft As Integer = 25
            Dim Rotate As String = "left"

            ' crop left-hand side of image

            If CropLeft > 0 Then
                ' define new width of preview
                originalWidth = originalWidth - CropLeft

                ' define new image size
                tempBitmap = New Bitmap(inputImage.Width - CropLeft, inputImage.Height)
                Dim g As Graphics = Graphics.FromImage(tempBitmap)

                ' overloaded definition #27:
                g.DrawImage(inputImage, New Rectangle(0, 0, tempBitmap.Width, tempBitmap.Height), CropLeft, 0, tempBitmap.Width, tempBitmap.Height, GraphicsUnit.Pixel)
                g.Dispose()

                ' reassign input image
                inputImage = tempBitmap
            End If


            ' this cropping is repeated for the other dimensions
            ' here...

            ' define the output in the given dimensions
            Dim outputImage As New Bitmap(inputImage, originalWidth, originalHeight)

            ' rotate the image if requested
            If Rotate <> "" Then
                Dim flipType As RotateFlipType
                Select Case Rotate
                    Case "left"
                        flipType = RotateFlipType.Rotate270FlipNone
                    Case "right"
                        flipType = RotateFlipType.Rotate90FlipNone
                End Select

                If flipType > 0 Then
                    outputImage.RotateFlip(flipType)
                End If
            End If

            ' save back to temp file
            Dim newPath As String = "C:\NewVersion.bmp" ' original path again
            outputImage.Save(newPath, originalFormat)

            ' tidy up  
            tempBitmap.Dispose()
            inputImage.Dispose()
            outputImage.Dispose()

            '' wait a bit because file is not released rightaway
            'Dim thenTicks As Long = Now.AddSeconds(10).Ticks  ' I have even put this wait up to 30+ seconds but it makes no difference...
            '' Surely I don't need a looping try/catch until this passes?
            'While Now.Ticks < thenTicks
            '    Dim spin As String = "spinning"
            'End While

            ' overwrite old file with the new
            Dim fi As New FileInfo(newPath)
            fi.MoveTo(newPath & ".old") ' this fails with the Exception mentioned above
0
 
LVL 2

Accepted Solution

by:
Jeffr0 earned 180 total points
ID: 10932741
It may be that the Garbage Collection is not running right away on your box.

In the code after the .Dispose() calls, add this line.

GC.Collect()

That may ensure that the objects are actually disposed during your "spinning" loop.
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 10932762
or just actually dispose the reference you are sending out to never never land before you do such ...

0
 
LVL 2

Author Comment

by:WolfyUK
ID: 10933296
Thanks for your suggestions. I will let you know how I get on when I'm back in work next week.

Thanks,

Wolfy
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 37

Expert Comment

by:gregoryyoung
ID: 11002229
How did this work out ?
0
 
LVL 2

Author Comment

by:WolfyUK
ID: 11003832
Only just got back into work!

The problem definitely lied within the disposal of objects. The only way I could fix it was by disposing of each inputImage within the 'cropping' sections before reassigning it as the tempBitmap, as well as keeping the spin delay and GC.Collect().

Thanks for your help, I'll split the points.

Wolfy
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 11003884
nooooooooooooooooooooooo


I just did this here ......

GC.Collect is evil here ...

you are losing your reference (thus not disposing it)

                ' overloaded definition #27:
                g.DrawImage(inputImage, New Rectangle(0, 0, tempBitmap.Width, tempBitmap.Height), CropLeft, 0, tempBitmap.Width, tempBitmap.Height, GraphicsUnit.Pixel)
                g.Dispose()

***********************************
                inputImage = tempBitmap
***********************************
            End If


            ' this cropping is repeated for the other dimensions
            ' here...

            ' define the output in the given dimensions
            Dim outputImage As New Bitmap(inputImage, originalWidth, originalHeight)


try disposing it before you toss the reference.
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 11003891
in above code you called inputimage = image.fromfile() which locks the file till disposed ... here you are throwing away the reference and forcing the garbage collector to dispose it.
0
 
LVL 2

Author Comment

by:WolfyUK
ID: 11012769
Sorry if I wasn't clear enough, but I did add inputImage.Dispose()s before each inputImage = tempBitmap, but this would only work alongside the GC.Collect() and spin delay.
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 11015903
btw: you also dispose the same image twice here
             tempBitmap.Dispose()
            inputImage.Dispose()
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

1.0 - Introduction Converting Visual Basic 6.0 (VB6) to Visual Basic 2008+ (VB.NET). If ever there was a subject full of murkiness and bad decisions, it is this one!   The first problem seems to be that people considering this task of converting…
The ECB site provides FX rates for major currencies since its inception in 1999 in the form of an XML feed. The files have the following format (reducted for brevity) (CODE) There are three files available HERE (http://www.ecb.europa.eu/stats/exch…
This Micro Tutorial will teach you how to censor certain areas of your screen. The example in this video will show a little boy's face being blurred. This will be demonstrated using Adobe Premiere Pro CS6.
This Micro Tutorial demonstrates using Microsoft Excel pivot tables, how to reverse engineer competitors' marketing strategies through backlinks.

863 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now