通过 WMI 从 ASP.NET 重新启动应用程序池问题

发布于 2024-12-01 16:43:03 字数 1155 浏览 1 评论 0原文

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

我运气不太好,有人知道我哪里出了问题吗?我尝试了很多组合并尝试直接从服务器运行但没有成功。

当我不传递凭据时,我收到错误......

访问被拒绝

...当我通过它们时,我收到错误...

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

我也尝试使用匿名帐户提升权限只是为了测试,但同样行不通。这可能是我想要实现的目标吗?

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

简单爱 2024-12-08 16:43:03

您不能对本地 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);
    }                 
  }
}    

希望,这有帮助。

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.

A君 2024-12-08 16:43:03

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

内部ManagementScope.Connect() 方法 使用 ConnectServerWmi 函数,它是一个包装器围绕 IWbemLocator::ConnectServer 方法。该文件指出...

与本地命名空间建立连接时,请勿指定 strUserstrPasswordstrAuthority。有关详细信息,请参阅连接到 WMI在远程计算机上

如果您点击该链接,您会发现它说...

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

因此,根本无法通过 WMI API 来执行此操作。我成功的解决方法是使用模拟,如已接受的答案中所示。 WindowsIdentity.Impersonate() 的文档 方法提供了一个很好的、健壮的例子。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文