2010-03-26 212 views
1

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

它在内置的Web服务器卡西尼运行时工作正常,但是当我试图通过IIS7(Vista)的运行它,我得到以下错误:

Access is denied
Description:
An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details:
System.ComponentModel.Win32Exception: Access is denied

我使用的代码:

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

该错误是当加工塑料抛出ng会尝试执行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); 

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

Exception Details: System.ComponentModel.Win32Exception: Access is denied

...就行了:

PerformanceCounterCategory.Delete(PerfCategory); 

回答

2

这是因为PerformanceCounterCategory.Delete需要你有两种管理员权限或者成为性能监视器用户组的成员。详情请参阅MSDN

默认情况下,Cassini在NT AUTHORITY \ SYSTEM用户帐户下运行,显然是Admin。但IIS在有限的用户帐户下运行,因此它无法访问PerformanceCounter调用。您需要让您的“用户”用户成为Performance Monitor Users或Administrator的成员。

+0

你说过你试图将用户添加为性能监视器组的成员。您是否尝试将该用户添加为管理员?这应该是你的下一步。如果这有效,那么你知道模拟工作正常,你只需要编辑权限。 – sngregory 2012-02-18 08:41:43