Avoid IISRESET in ASP.NET applications (added bonus: ASPRESET)

I'm always a bit worried when I work with developers or system admins that still think you should "throw in an IISRESET just in case" when deploying ASP.NET applications. Cargo cult server administration at its worst ("Not sure why, but it always seems to help if I throw in an IISRESET after pushing code. If that don't get it, a reboot will!").

This is very rarely necessary now, and it's terrible to take all websites on a server offline "just in case". It was often needed back in the ASP / COM days (you needed to free the reference to COM objects to allow overwriting the files), but ASP.NET code runs under the ASP.NET worker process and runs with side-by-side support, which completely obviates the IISRESET step. Copy the files and go!

If your changes include files which will restart the web application (such as DLL's or the web.config file), the site will automatically restart. You're done.

If, on the other hand, you've edited other files which don't cause a website restart (such as .config files referenced from web.config, etc.) you'll have to trigger the site to reload manually. There are at least 4 ways to force an ASP.NET website to recycle:

  1. Edit web.config - open it in notepad, add a space, remove the space, and save. The change to the file timestamp will cause the site to reload.

  2. "Touch" the file to change the file timestamp. I wrote a reg file that adds a "right click / Touch" menu item a while ago for just this purpose. There are other more advanced Touch utilities such as the one Scott Hanselman mentions here.

  3. Kill ASPNET worker process manually. Don't be scared - it will automatically restart on the next request.1 It will dump the current requests (and possibly session state if you're inproc), but so will all of these. The ASPNET worker process is a cockroach; it keeps coming back. You just bring up the task manager, go to the Processes tab, find your ASP.NET worker process (aspnet_wp.exe for XP and W2K, w3wp.exe for W2K3 and Vista), right-click it and select "End Process". It will restart on the next request to an ASP.NET page.

  4. A new one - ASPRESET. All the above methods are more work than Start / Run / IISRESET, which means people will be more likely to fall back to their old habits and run that IISRESET. The following code (compiled and saved as ASPRESET.exe and saved in a folder in your path) will kill the ASP.NET worker process and restart it immediately by requesting a phony page with a .ASPX extention. That's expecially handy if you build ASP.NET in Visual Studio as non-web projects, since you need a running process to attach to when you debug. I keep the compiled executable in a

I built this in SnippetCompiler, but it will work just fine in Visual Studio 2003 and 2005 as well.

using System;
using System.Diagnostics;
using System.Net;

public class AspReset
{
 
public static void Main()
 {
  KillAspNetProcess();
  StartAspNetProcess();
 }
 
 
private static void KillAspNetProcess()
 {
  
string processName = "aspnet_wp";
  System.OperatingSystem os = System.Environment.OSVersion;

  
//Longhorn and Windows Server 2003 use w3wp.exe
  
if((os.Version.Major == 5 && os.Version.Minor > 1) || os.Version.Major ==6)
   processName = "w3wp";
   
  
foreach(Process process in Process.GetProcessesByName(processName))
  {
   Console.WriteLine("Killing ASP.NET worker process (Process ID:" + process.Id + ")");
   process.Kill();
  }
 }

 
private static void StartAspNetProcess()
 {
  
try
  
{
   
string phonyURL = "http://localhost/directory/does/not/exist/" 
    + Guid.NewGuid().ToString() 
    + "/start.aspx";
   WebClient myWebClient = 
new WebClient();
   
byte[] myDataBuffer = myWebClient.DownloadData(phonyURL);
  }
  
catch(System.Net.WebException)
  {
   Console.WriteLine("ASP.NET worker process restarted.");
  }
  
catch(Exception ex)
  {
   Console.WriteLine(ex.ToString());
  }
 }
}

1Caveat: Killing a process is a bit more risky than restarting the application by touching web.config, since it prevents ASP.NET from shutting down gracefully. If you've got non-transactional work going on (a really bad idea), you could theoretically leave things in a bad state. Any decent database system  shouldn't have any problems - I'm talking about code which edits text file, etc. I've never had a problem with this, and I've been merciless to aspnet_wp for the past 3 years, but this is primarily something I use in my dev and stage environments. If your site can't handle a loss of power, you just might want to fix that...

I considered a phony edit to machine.config, which would have the same effect as editing all web.config files on the system, but I feel like that's higher risk than just killing ASP.NET worker process, since messing up machine.config will bring the server down until you fix it.

Of course, none of this is required with VS 2005 projects running under Cassini.

UPDATE:  For another reason to avoid  IISRESET, see Ken Robertson's post:  IISReset corrupting the IIS metabase

32 Comments

  • cool, I was looking for something like this.

  • Iam using win server 2k3 (sp1).
    The os.Version.Minor is '2' (Major = 5) , is it coz of the service pack or some other reason?

  • You forget the best and easiest way of all as of v2.0 -- just place a file named app_offline.htm in the web application root folder. This will take the asp.net process offline and it will serve up the static contents of that htm file in the meantime -- a perfect way to let people know the site is being updated and will be back online very soon.

  • I think you should make it clearer that these different solutions do different things, and people need to be aware of which is appropriate.
    E.g.
    - touching web.config will only recycle the relevant application domain. The worker process will continue running, as will any ASP.NET applications other than the one you are recycling. In many cases the best approach as it has least impact on other applications and their users.
    - W23K+ has a worker process per application pool. Killing the right worker process recycles the application pool but leaves other application pools running.
    - Your ASPRESET is more heavy-handed - almost as much as IISRESET - as it recycles all worker processes for all application pools.
    - Your StartAspNetProcess will not necessarily restart all worker processes for all application pools.

  • > ... to modify the code to request a non-existant page in each app pool if needed ...

    You should also take a look at the admin scripts provided with IIS - e.g. IISApp.vbs

  • can we reset an application domain with code.like find a list of application domains started and reset the one you want ? Can we write c# code fo r this? I was planning of providing some kind of utility for this?

  • just wanted to provide some details for my blog post, you also got one comment earlier.
    thats an small tool i wrote, where you can reset your stuff easier and faster. theres also the code in there that you want, a.m.

  • hi chris,i downloaded the tool on your site,well need to test this on windows 2003 server currently i'm on xp.

    How do i get a list of application domains? is that possible? I just need to reset one domain not the pool,the application domain.

  • > I've updated the code to use w3wp for 5.2 and above.
    If you want to be really bulletproof, you need to note that W2K3 can run in IIS 5.0 Isolation mode, in which case you'll have aspnet_wp.exe rather than w3wp.

  • nice posting -- excellent discussion -- and best of all is the graphic!

  • If we referenced external .config files and if we change them on fly i think the worker process should not start. If i am wrong please correct me.

  • If we referenced external .config files and if we change them on fly i think the worker process should not start. If i am wrong please correct me.

  • Girish -
    That's correct. You need to touch the web.config file to cause external .config files to be read.

  • I appreciate the article. I have 2 questions.

    (1) How can your EXE solution be implemented in a shared hosting environment from a secured admin page?

    (2) I have had situations with the "locking" of *.MDF files and *.LDF files for SQL Server 2005 Express and making a change to Web.config did not "unlock" these files. In short, I wanted to delete the current *.MDF and *.LDF files that were deployed to my shared host and then upload new ones. Unfortunately, when this "locking" occurs, the target file cannot be renamed, deleted, or moved in any way. It has to "time out" (I think). Very annoying. I had tried editing Web.config, saving changes, and then trying to delete the old *.MDF but that did not work. To you-- I ask: why didn't changing Web.config work and what is the alternative to waiting for a timeout?

    If you have a moment, please comment.

    Thanks again for a great article.

    Thank you.

    --Mark Kamoski

  • Can't you just use WMI to recycle the web site's AppPool:

    strComputer = "."
    Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\MicrosoftIISv2")
    Set colItems = objWMIService.ExecQuery( _
    "SELECT * FROM IIsWebVirtualDirSetting WHERE Name = 'W3SVC/1/ROOT'",,48)

    Dim AppPoolID
    For Each objItem in colItems
    AppPoolID = objItem.AppPoolId
    Next


    Set objShare = objWMIService.Get("IIsApplicationPool.Name='" & AppPoolID & "'")

    ' no InParameters to define

    ' Execute the method and obtain the return status.
    ' The OutParameters object in objOutParams
    ' is created by the provider.
    Set objOutParams = objWMIService.ExecMethod("IIsApplicationPool.Name='" & AppPoolID & "'", "Recycle")


    ' No outParams

  • 1. Edit web.config - open it in notepad, add a space, remove the space, and save. The change to the file timestamp will cause the site to reload.

    You do not need to change the file contents in order to recylce the site, all you need to do is open the web.config file and just save and close, it changes the time stamp. IIS lloks for the web.cofig time stamp.

    More over, this also has a negative side effect, if there are any open sessions (browse windows using this "site") all of them gets killed/trashed, right after you save the web.config file.

  • Have any of you tried using the Microsoft hotfix solution for the w3wp.exe memory 'leak' issue?

  • Ok...so why bother with all the trouble if you can just use c:\>Net Stop "World Wide Web Publishing Service" to stop the aspnet_wp.exe and then use Net Start "World Wide Web Publishing Service" to start the service. This basically does the restart of aspnet_wp.exe.

  • In our environment we have an extensive class library that is shared among many ASP.NET apps. The modules are all kept at version 1.0.0.0, and updated in the GAC as necessary. The reason being, the only changes we make are changes we specifically want to propagate across our entire website. A great way to centralize information. But the problem is that stuff updated in the GAC doesn't trigger any refresh, so we still have to do an iisreset for the changes to propagate.

    So is there a way around that? Why can't ASP.NET apps monitor their references for changes just as they do with their own DLL files?

  • as josh indicated above, I think the "safest" reset is to create a file in the bin directory then delete it.

    As well as allowing current requests to finish (and leaving the other asp.net sites unaffected) it retains the timestamp on the web.config file so you can see when you last actually changed it (which, let's face it, is what file timestamps are for)

    Why MS didn't provide a UI to do restart an individual web app is anyone's guess.

  • I use this method (inside ASP.NET applications):

    protected void btnCacheReset_Click(object sender, EventArgs e)
    {
    string webConfigPath = Server.MapPath("~/Web.config");
    System.IO.File.SetLastWriteTime(webConfigPath, DateTime.Now);
    Session.Abandon();
    Response.Redirect("~/Default.aspx");
    }

    Regards,
    Andrea.

  • Andrea you rock. This is so simple and does exactly what it needs to.

  • Hi,
    I'm trying to do iisreset remotely on our servers. I'll like to know if it is possible to user your asPReset techniques remotely???

  • Is stopping the application pool the same as killing the worker process? This would seem more graceful.

  • To recycle (ala stop-start the app pool), just go to IIS Manager, open the Application Pools node (top of the three listed), select the node that represents your web app, Right-Click > Recycle, your done - no code, no iisreset.

  • post-build event
    cscript c:\windows\system32\iisapp.vbs /a "MyAppPool" /r

  • Absolutely incorrect. IISRESET does the same as web.config edit, etc. AppDomain is gracefully unloaded. Process kill immediately kills the process and does not allow any handlers (such as AppDomain.Unload) to run and all data is lost.

  • IIS 6 App Pool recycling does very big troubles if worker process consumed a lot of memory. Some unpredictable issues appeared in our application after IIS recycling, so we disabled automatic recycling (which is on by default) and never used manual recycling. IISRESET always works fine without any troubles.

  • Andrea,
    Thanks a lot. I was searching for a solution for quite a long time. I hope your code bit will help to solve my problem.

    Regards,
    Smitha

  • Glad to see, there are no more those issues today: Usually, if you install the system by default, everything will work out OK out of the box - so no more Voodoo-admin-power is needed :-)
    (it took some time to convince my collegue to skip IISRESET before every deploy, but he got it, finally)

  • You wouldna1aft beviele it but Ia1afve wasted all day digging for some articles about this. Youa1afre a lifesaver, it was an excellent read and has helped me out to no end. Cheers, Heyaa1admy very first comment on your site. ,I have been reading your blog for a while and thought I would completely pop in and drop a friendly note. . It is great stuff indeed. I also wanted to ask..is there a way to subscribe to your site via email?

  • I saw this really good post today and reateld content i think Intrigued by your blog and just thought I would help with a new perspective - while you take a year off, you may want to work on building strong network. There are statistics showing referrals' amount to about 25% of company hiring sources while onl

Comments have been disabled for this content.