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
Solved

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

Posted on 2004-04-27
11
287 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
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
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

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

This article explains how to create and use a custom WaterMark textbox class.  The custom WaterMark textbox class allows you to set the WaterMark Background Color and WaterMark text at design time.   IMAGE OF WATERMARKS STEPS Create VB …
Since .Net 2.0, Visual Basic has made it easy to create a splash screen and set it via the "Splash Screen" drop down in the Project Properties.  A splash screen set in this manner is automatically created, displayed and closed by the framework itsel…
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…

856 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