1

我在使用模拟从 MVC 网站中删除 PerformanceCounterCategory 时遇到问题。我有一个静态类,当应用程序启动时,它会检查 PerformanceCounterCategory 是否存在,以及它是否包含正确的计数器。如果没有,它会删除该类别并使用所需的计数器再次创建它。

在内置的网络服务器 Cassini 下运行时它工作正常,但是当我尝试通过 IIS7(Vista)运行它时,我收到以下错误:

访问被拒绝
说明:
在执行当前 Web 请求期间发生未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。
异常详细信息:
System.ComponentModel.Win32Exception:访问被拒绝

我对代码的使用:

var username = "user";
var password = "password";
var domain = "tempuri.org";

WindowsImpersonationContext impersonationContext;

// if impersonation fails - return
if (!ImpersonateValidUser(username, password, domain, out impersonationContext))
{
    throw new AuthenticationException("Impersonation failed");
}

PerformanceCounterCategory.Delete(PerfCategory);
UndoImpersonation(impersonationContext);

MS文章中的模拟代码...

private static bool ImpersonateValidUser(string username, string password, 
    string domain, out WindowsImpersonationContext impersonationContext)
{
    const int LOGON32_LOGON_INTERACTIVE = 2;
    const int LOGON32_PROVIDER_DEFAULT = 0;
    WindowsIdentity tempWindowsIdentity;
    var token = IntPtr.Zero;
    var tokenDuplicate = IntPtr.Zero;

    if (RevertToSelf())
    {
        if (LogonUserA(username, domain, password, 
             LOGON32_LOGON_INTERACTIVE, 
             LOGON32_PROVIDER_DEFAULT, ref token) != 0)
        {
            if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
            {
                tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                impersonationContext = tempWindowsIdentity.Impersonate();

                if (impersonationContext != null)
                {
                    CloseHandle(token);
                    CloseHandle(tokenDuplicate);
                    return true;
                }
            }
        }
    }

    if (token != IntPtr.Zero)
        CloseHandle(token);
    if (tokenDuplicate != IntPtr.Zero)
        CloseHandle(tokenDuplicate);

    impersonationContext = null;
    return false;
}



[DllImport("advapi32.dll")]
public static extern int LogonUserA(String lpszUserName, String lpszDomain, 
    String lpszPassword, int dwLogonType, int dwLogonProvider, 
    ref IntPtr phToken);

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DuplicateToken(IntPtr hToken, int impersonationLevel, 
    ref IntPtr hNewToken);

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool RevertToSelf();

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);

处理尝试执行 PerformanceCounterCategory.Delete 命令时引发错误。

更新
为了回应大卫的回答,我尝试了以下方法:

  1. 创建了一个名为 PerfMonUser 的新本地用户
  2. 将此用户添加到“性能监视器用户”组

修改了代码,现在显示为:

var username = "PerfMonUser";
var password = "password";
var domain = Environment.MachineName;

WindowsImpersonationContext impersonationContext;

// if impersonation fails - return
if (!ImpersonateValidUser(username, password, domain, out impersonationContext))
{
    throw new AuthenticationException("Impersonation failed");
}

PerformanceCounterCategory.Delete(PerfCategory);
UndoImpersonation(impersonationContext);

...但我仍然收到错误:

异常详细信息:System.ComponentModel.Win32Exception:访问被拒绝

...在线上:

PerformanceCounterCategory.Delete(PerfCategory);
4

1 回答 1

2

This is because PerformanceCounterCategory.Delete requires you to have either Administrator privileges or be a member of the Performance Monitor Users group. See MSDN for details.

Cassini runs under the NT AUTHORITY\SYSTEM user account by default, which is obviously Admin. IIS however runs under a limited user account, so it won't have access to PerformanceCounter calls. You'll need to make your "user" user either a member of Performance Monitor Users or an Administrator.

于 2010-03-26T05:57:51.423 回答