# How to get IIS7 to release a locked file?

During our production builds, a very large (10 megabyte) static content file in the root directory will sometimes be locked by IIS and cannot be deleted by the clean task. This is presumably because it is being actively served to one or more clients at the time.

The build process stops the website before cleaning via

c:\Windows\System32\inetsrv\appcmd.exe stop site http://oursite.com


However, this does not release the file - we have to restart IIS to get the process to relinquish its lock.

appcmd.exe allows you to take IIS down completely; we do not want to do this!

Are there any other ways to get IIS to let go of a locked file, without restarting IIS? Simply stopping and starting the individual website is definitely not working to release the file lock.

-
10 meg static content file? Is it a background music mp3 file, the elevator version for "Girl From Ipanema?" ;-) –  splattne May 10 '09 at 8:00
Serious question now: does this static file change from build to build or is it just a file that will never change? –  splattne May 10 '09 at 8:02
Just a crazy thought, but I wonder what would happen if you enabled Shadow Copies on this folder? –  Richard West May 10 '09 at 13:14
This is your sitemap.xml right ? –  Dave Cheney May 10 '09 at 13:21
Yeah, it was our sitemap.xml, but now we just have a MVC route to it and cache the sucker in memory. No more locking! –  Jarrod Dixon Jun 12 '09 at 8:01

There are tools, such as Sysinternal's Process Explorer, that can find and forcibly close file handles, however the state and behaviour of the application (both yours and, in this case, IIS) after doing this is undefined. Some won't care, some will error and others will crash hard.

The correct solution is to take the outage and allow IIS to cleanly release locks and clean up after itself to preserve server stability. If this is not possible, you can either create another site on the same box, or set up a new box with the new content, and move the domain name/IP across to "promote" the new content to production.

-
+1 for process explorer, it may give you some insight into being able to solve the problem if you can see what thread is holding the file handle open –  Nick Kavadias May 10 '09 at 14:50

I'm not sure if you mean the compilation of aspx files in temporary assemblies. We are using ASP.NET deployment projects, which precompile all aspx/ascx files beforehand.

While copying the binary files from the "publish" to the "bin" folder, we temporary enable a app_offline.htm file which is removed after all assemblies are copied (just a few seconds). This way I never experienced file locks.

EDIT:

You could try to recycle the app pool using appcmd.exe, instead of stopping the web site:

C:\Windows\System32\inetsrv\appcmd.exe recycle apppool "My App Pool Name"

-
No, it's just a static content file in the root directory - updating the question with that info! –  Jarrod Dixon May 10 '09 at 7:14
I guess you're using the app_offline.htm during the exection of your build job? –  splattne May 10 '09 at 7:22
I think we've tried recycling manually to no avail, but we'll try it again next time there's a lock (app pools are for .NET, right? probably won't help here). And we used to have the app_offline.htm file created, but it didn't help with the locking - which is why we moved to taking the individual site down. –  Jarrod Dixon May 10 '09 at 8:02
I'm afraid you're right. I'll test this on one of our servers and come back to you. –  splattne May 10 '09 at 8:27
I can't reproduce it (IIS 7 on Windows Server 2008). I copied a 30 MB zip file to the server, started a browser download and could delete it. I thought, maybe it's related to compression, so I renamed it to .xml. Same result: I still could delete it while the remote browser was downloading it. :( –  splattne May 10 '09 at 12:30

Sure, stop the IIS service. Maybe I'm not understanding something, sorry.

-
If you're stopping the IIS service, you'll take down all web sites... –  splattne May 10 '09 at 7:52
That is the one thing we really want to avoid, as we don't want our CruiseControl.NET site coming down - we click that "Refresh Status" button like madmen during a build to check for success! –  Jarrod Dixon May 10 '09 at 8:03
Ok, how about building somewhere else first, then deploying over the static file instead of doing everything on that server? –  Mark Allen May 11 '09 at 3:11
isn't that the issue here? Nobody said the file was being modified by software on the server itself. –  FlavorScape Aug 9 '12 at 1:28

note: not an expert on windows file locking semantics

Jarrod, are you able to rename the file out of the way. You may also be able to create your new file with a temporary extension, and then rename it over the current file.

If windows file locking semantics work similar to POSIX ones the readers that hold a current read lock on the file, should still continue to serve the old file until they close their read streams, while new readers will open the new file.

-
No, we're not able to do anything to the file until IIS is restarted. –  Jarrod Dixon May 11 '09 at 6:14

Process Monitor should help you with your investigation, here's an example from Mark's blog (the guy that wrote the tool) on how to find the file handle.

You may want to try this Unlocker tool to automate your unlocking at a file handle level.

-
Cool, I've never used Process Monitor; but every workstation I use immediately gets Process Explorer! technet.microsoft.com/en-us/sysinternals/bb896653.aspx –  Jarrod Dixon May 12 '09 at 3:51

Not the answer, but a workaround idea in case there is no way to "unlock" that file without restarting IIS server:

What if you build/deploy to an new empty folder and change the website's home directory to that folder? You have to create an new folder name though or switch between two names.

I don't know in which folder that file belongs. If it doesn't have to be in the root folder, you could put it in a newly created folder and create a virtual directory pointing to that folder. So you can keep your standard home directory for the application.

-

I use a little tool called "Handle" to do this.

You basically pass it the name of the file that's locked and it tells you what processes are using it:

handle c:\weird.file
Something.exe pid: 1000 100: C:\weird.file
Something.exe pid: 1000 101: C:\weird.file


Then you pass it the -c switch to make it close the handle:

handle.exe -c 101 -p 1000 -y
handle.exe -c 100 -p 1000 -y


You might struggle to work that in to a build script without a wrapper program to parse the output but hopefully this will help.

-
The mighty Mark Russinovich to the rescue - I'll check this out, but Handle's dire warning of program instability when forcibly closing a handle makes me nervous. –  Jarrod Dixon May 12 '09 at 3:47
Hopefully any instability will be limited to the AppPool in question. If that's the case, then you can just do a restart of the AppPool after you've released the lock. –  Simon Johnson May 12 '09 at 7:37
@ Jarrod: any luck? Could you post any results, up into your original post, please? i'd love to see what is happening here, behind the scenes. –  Pure.Krome May 13 '09 at 5:14
can I use handle.exe for get processes that lock a folder ?any sample ? –  Kiquenet Aug 11 '12 at 14:50

I'm trying this out now: Apparently there could be issues with file locking if you have indexing activated on the directory. http://www.richard-banks.org/2008/04/how-to-fix-problems-with-locked-files.html

This is IIS 6.0 but since this seems to be related to the OS and not IIS it might be the root cause.

-

I had the same problem. Now I switched to MSDeploy (Web Deploy), and now I can update the web site reliably without stopping anything. In fact this step is scripted in our automated build tool and it happens all the time without any problems. And it's fast, too.

-