Solved

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

Posted on 2004-04-27
11
272 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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
Thanks for your suggestions. I will let you know how I get on when I'm back in work next week.

Thanks,

Wolfy
0
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 
LVL 37

Expert Comment

by:gregoryyoung
Comment Utility
How did this work out ?
0
 
LVL 2

Author Comment

by:WolfyUK
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
btw: you also dispose the same image twice here
             tempBitmap.Dispose()
            inputImage.Dispose()
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

It’s quite interesting for me as I worked with Excel using vb.net for some time. Here are some topics which I know want to share with others whom this might help. First of all if you are working with Excel then you need to Download the Following …
Parsing a CSV file is a task that we are confronted with regularly, and although there are a vast number of means to do this, as a newbie, the field can be confusing and the tools can seem complex. A simple solution to parsing a customized CSV fi…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

762 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

12 Experts available now in Live!

Get 1:1 Help Now