Search code examples
c#wmiiis-6restartapplication-pool

Restart App Pool from ASP.NET via WMI Problems


I've been trying to create a C# ASP.NET page which sits on a Windows Server 2003 IIS 6 server and when called (remotely), restarts/recycles a specific application pool on the server.

I've not been having much luck, does anyone know where I'm going wrong? I've tried many combinations and tried running direct from server but to no-avail.

When I don't pass the credentials over I get the error...

Access is denied

...and when I do pass them I get the error...

User credentials cannot be used for local connections

I've also tried elevating permissions with the anon account just to test but again it wouldn't work. Is this possible what I'm trying to achieve?

try
{
    ManagementScope scope = new ManagementScope("root\\MicrosoftIISv2");
    scope.Path.Server = "servername";
    scope.Path.Path = "\\\\servername\\root\\MicrosoftIISv2";
    scope.Path.NamespacePath = "root\\MicrosoftIISv2";
    scope.Options.Username = "domain\\user";
    scope.Options.Password = "password";
    scope.Options.Authentication = AuthenticationLevel.Default;
    scope.Options.Impersonation = ImpersonationLevel.Impersonate;
    scope.Options.EnablePrivileges = true;
    scope.Connect();

    ManagementObject appPool = new ManagementObject(scope, new ManagementPath("IIsApplicationPool.Name='W3SVC/AppPools/AppPoolName'"), null);
    appPool.InvokeMethod("Recycle", null, null);
}
catch (System.Exception ex)
{
}

Solution

  • You can't use the username/password option for local WMI connections. By default for local WMI connections the credentials of the logged on user are used (in your case the Identity of the application pool of your website). I think you have two options using WMI from your website:

    • First option: Grant the identity of your application pool enough permissions to use WMI (recycle applications pools).

    • Second option: Use impersonation.

    Here is an example:

    public class _Default : Page
    {
      [DllImport("advapi32.dll", SetLastError = true)]
      static extern bool LogonUser(string principal, string authority,string password, uint logonType, uint logonProvider, out IntPtr token);
    
      [DllImport("kernel32.dll", SetLastError = true)]
      static extern bool CloseHandle(IntPtr handle); 
    
      protected void OnClick(object sender, EventArgs e)
      {
        IntPtr token = IntPtr.Zero;
        WindowsImpersonationContext impUser = null;
    
        try
        {        
          bool result = LogonUser("administrator", "contoso",
                                "P@$$W0rd", 3, 0, out token);
          if (result)
          {
            WindowsIdentity wid = new WindowsIdentity(token);
            impUser = wid.Impersonate();
    
            try
            {
              ManagementScope scope = new ManagementScope("root\\MicrosoftIISv2");
              scope.Path.Server = "srvcontoso";
              scope.Path.Path = "\\\\srvcontoso\\root\\MicrosoftIISv2";
              scope.Path.NamespacePath = "root\\MicrosoftIISv2";
    
              scope.Connect();
    
              ManagementObject appPool = new ManagementObject(scope, new ManagementPath("IIsApplicationPool.Name='W3SVC/AppPools/DefaultAppPool'"), null);
              appPool.InvokeMethod("Recycle", null, null);
             }
             catch (System.Exception ex)
             {
             } 
           }
        }
        catch
        {        
        }
        finally
        {         
          if (impUser  != null)
            impUser .Undo();
    
          if (token != IntPtr.Zero)
            CloseHandle(token);
        }                 
      }
    }    
    

    Hope, this helps.