我在使用模拟从 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 命令时引发错误。
更新
为了回应大卫的回答,我尝试了以下方法:
- 创建了一个名为 PerfMonUser 的新本地用户
- 将此用户添加到“性能监视器用户”组
修改了代码,现在显示为:
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);