Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

programatically recycle pool from asp.net application in same pool

Tags:

asp.net

iis

Have an ASP.net web app which works fine for a few days, but then randomly throws some database connection string exception and as a result 0 records are listed in a table (should show hundreds). I've spent many weeks debugging, memory is fine, the database exists and it's fixed by doing anything which would cause the application to recycle. It takes many days of waiting to even reproduce.

So I was thinking since I know there should never be 0 records, how can I force the application pool running the web app to recycle (when I get this database exception or 0 records). At least this way the web site will work for the next user and I don't have to manually restart it.

like image 258
Tuviah Avatar asked Feb 28 '23 03:02

Tuviah


2 Answers

I've never been entirely comfortable with this solution because of the complexity, but also because the security requirements are unclear (and if you have to grant rights to the application user for this, that's not only yet another configuration step, but also a security risk, and it seems like letting the application user have rights to recycle the application pool indiscriminately, especially over the network, could be leveraged in a DOS attack).

In my limited situation where I've found critical conditions that I was able to resolve with a restart and detect during execution but was not yet able to prevent through more palatable code changes, and after much research, I went through several other solutions (OK--hacks) to get this done. 1. Throw an unhandled exception on a newly spawned thread, 2. Environment.Exit(), and 3. System.Web.HttpRuntime.UnloadAppDomain(). These have the rather nasty side-effect of terminating all in-progress requests, which is admittedly a terrible hack, but is tolerable in some cases (like where the condition discovered prevents proper handling of the vast majority of requests anyway).

The distaste for this hack has remained with me for years until I recently stumbled across this little gem that is much simpler and avoids WMI entirely:

System.Web.Hosting.HostingEnvironment.InitiateShutdown();

My testing has shown that it does exactly what I needed, and I believe it's what you wanted as well. According to the documentation, it's been around since .NET 2.0, but I never came across it in my research until a couple of days ago.

like image 134
James Avatar answered Apr 28 '23 12:04

James


Hi in this article you can find relevant code to restart application pool from Asp.net

Restart IIS application pool from ASP.NET page

using System;
using System.Web;
using System.Web.UI;
using System.Management;
using System.DirectoryServices;
using System.Web.UI.WebControls;

public partial class iis : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Response.Write(System.Environment.MachineName);
        status();
    }

    protected void status()
    {
        string appPoolName = "dev.somesite.com";
        string appPoolPath = @"IIS://" + System.Environment.MachineName + "/W3SVC/AppPools/" + appPoolName;
        int intStatus = 0;
        try
        {
            DirectoryEntry w3svc = new DirectoryEntry(appPoolPath);
            intStatus = (int)w3svc.InvokeGet("AppPoolState");
            switch (intStatus)
            {
                case 2:
                    lblStatus.Text = "Running";
                    break;
                case 4:
                    lblStatus.Text = "Stopped";
                    break;
                default:
                    lblStatus.Text = "Unknown";
                    break;
            }
        }
        catch (Exception ex)
        {
            Response.Write(ex.ToString());
        }
    }
    protected void stopAppPool(object sender, EventArgs e)
    {
        Button btn = (Button)sender;
        string appPoolName = btn.CommandArgument;
        string appPoolPath = @"IIS://" + System.Environment.MachineName + "/W3SVC/AppPools/" + appPoolName;
        try
        {
            DirectoryEntry w3svc = new DirectoryEntry(appPoolPath);
            w3svc.Invoke("Stop", null);
            status();
        }
        catch (Exception ex)
        {
            Response.Write(ex.ToString());
        }
    }

    protected void startAppPool(object sender, EventArgs e)
    {
        Button btn = (Button)sender;
        string appPoolName = btn.CommandArgument;
        string appPoolPath = @"IIS://" + System.Environment.MachineName + "/W3SVC/AppPools/" + appPoolName;
        try
        {
            DirectoryEntry w3svc = new DirectoryEntry(appPoolPath);
            w3svc.Invoke("Start", null);
            status();
        }
        catch (Exception ex)
        {
            Response.Write(ex.ToString());
        }
    }
}
like image 36
Tarik Avatar answered Apr 28 '23 14:04

Tarik