У меня проблемы с использованием олицетворения для удаления PerformanceCounterCategory с веб-сайта MVC. У меня есть статический класс, и при запуске приложения он проверяет, существует ли PerformanceCounterCategory и содержит ли он правильные счетчики. Если нет, он удаляет категорию и создает ее снова с необходимыми счетчиками.
Он отлично работает при работе под встроенным веб-сервером Cassini, но при попытке запустить его через IIS7 (Vista) выдается следующая ошибка:
Доступ запрещен
Описание:
Произошло необработанное исключение во время выполнения текущего веб-запроса. Пожалуйста, просмотрите трассировку стека для получения дополнительной информации об ошибке и о том, где она возникла в коде.
Сведения об исключении:
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);