Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

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

Posted on 2004-04-27
11
Medium Priority
?
296 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 3
  • 2
11 Comments
 
LVL 37

Assisted Solution

by:gregoryyoung
gregoryyoung earned 612 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 720 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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
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
 
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

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

Question has a verified solution.

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

Well, all of us have seen the multiple EXCEL.EXE's in task manager that won't die even if you call the .close, .dispose methods. Try this method to kill any excels in memory. You can copy the kill function to create a check function and replace the …
Introduction As chip makers focus on adding processor cores over increasing clock speed, developers need to utilize the features of modern CPUs.  One of the ways we can do this is by implementing parallel algorithms in our software.   One recent…
In this video, Percona Solution Engineer Rick Golba discuss how (and why) you implement high availability in a database environment. To discuss how Percona Consulting can help with your design and architecture needs for your database and infrastr…
In response to a need for security and privacy, and to continue fostering an environment members can turn to for support, solutions, and education, Experts Exchange has created anonymous question capabilities. This new feature is available to our Pr…
Suggested Courses

610 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