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.
Solution 1:
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.
Solution 2:
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.
Solution 3:
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"
Solution 4:
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.
Solution 5:
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.