从ASP中重新启动App Pool.NET通过WMI问题

本文关键字:NET 通过 WMI 问题 Pool App ASP 重新启动 | 更新日期: 2023-09-27 18:06:48

我一直在尝试创建一个c# ASP。. NET页面,它位于Windows Server 2003 IIS 6服务器上,当(远程)调用时,重新启动/回收服务器上的特定应用程序池。

我运气不太好,有人知道我哪里出错了吗?我尝试了许多组合,并尝试直接从服务器运行,但无济于事。

当我不传递凭据时,我得到错误…

访问被拒绝

…当我传递它们时,我得到了错误…

用户凭据不能用于本地连接

我也试过用匿名帐户提升权限,只是为了测试,但再次不起作用。我想达到的目标有可能实现吗?

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

从ASP中重新启动App Pool.NET通过WMI问题

本地WMI连接不能使用用户名/密码选项。默认情况下,本地WMI连接使用登录用户的凭据(在您的情况下是您网站的应用程序池的身份)。我认为你有两个选择使用WMI从你的网站:

  • 第一个选项:授予应用程序池的身份足够的权限来使用WMI(回收应用程序池)

  • 第二个选项:使用模拟

下面是一个例子:

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

希望有帮助。

连接到本地WMI服务时无法指定备用凭据。

在内部,ManagementScope.Connect()方法使用ConnectServerWmi函数,该函数是IWbemLocator::ConnectServer方法的包装器。

当连接到本地命名空间时,不要指定strUserstrPasswordstrAuthority。有关详细信息,请参见在远程计算机上连接到WMI。

如果你点击链接,你会发现上面写着…

如果您试图访问不同的帐户,则需要提供额外的凭据。(请注意,不允许使用与当前帐户不同的凭据访问本地WMI。)

所以,根本没有办法通过WMI API做到这一点。我成功的一个解决方法是使用模拟,就像在接受的答案中一样。WindowsIdentity.Impersonate()方法的文档提供了一个很好的健壮示例。