Restart App Pool from ASP.NET via WMI Problems

坚强是说给别人听的谎言 提交于 2020-02-22 06:11:47

问题


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)
{
}

回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/7204099/restart-app-pool-from-asp-net-via-wmi-problems

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!