开发者

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 co开发者_JAVA技巧mbinations 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)
{
}


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.


It is not possible to specify alternate credentials when connecting to the local WMI service.

Internally, the ManagementScope.Connect() method uses the ConnectServerWmi function, which is a wrapper around the IWbemLocator::ConnectServer method. That documentation states...

Do not specify strUser, strPassword, or strAuthority when making a connection to a local namespace. For more information, see Connecting to WMI on a Remote Computer.

If you follow that link you'll find it says...

If you were trying to access a different account, you would need to supply additional credentials. (Note that trying to access WMI locally with credentials different than your current account is not permitted.)

So, there is simply no way to do this through the WMI API. A workaround I had success with is to use impersonation, as in the accepted answer. The documentation for the WindowsIdentity.Impersonate() method provides a good, robust example of this.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜