c# .net windows-vista uac user-accounts

c# - ¿Detecta si se está ejecutando como administrador con o sin privilegios elevados?



.net windows-vista (7)

Tengo una aplicación que necesita detectar si se está ejecutando o no con privilegios elevados o no. Actualmente tengo un código configurado de esta manera:

static bool IsAdministrator() { WindowsIdentity identity = WindowsIdentity.GetCurrent(); WindowsPrincipal principal = new WindowsPrincipal(identity); return principal.IsInRole (WindowsBuiltInRole.Administrator); }

Esto funciona para detectar si un usuario es administrador o no, pero no funciona si se ejecuta como administrador sin elevación. (Por ejemplo en vshost.exe).

¿Cómo puedo determinar si la elevación [ya está en vigencia o] es posible ?


(nueva respuesta seis años después de que se hizo la pregunta)

Descargo de responsabilidad: Esto es solo algo que sucedió en mi sistema operativo particular con mi configuración particular con mi usuario particular:

using System.Security.Principal; // ... static bool IsElevated { get { return WindowsIdentity.GetCurrent().Owner .IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid); } }

Entonces, cuando ejecuto este "Ejecutar como administrador", la propiedad get acceso o devuelve true . Cuando se ejecuta normalmente (incluso si mi usuario "es" administrador, simplemente no ejecuta esta aplicación en particular "como administrador"), devuelve false .

Esto parece mucho más simple que muchas otras respuestas.

No tengo idea si hay casos donde esto falla.

¡PD! Esto también parece estar bien:

static bool IsElevated { get { var id = WindowsIdentity.GetCurrent(); return id.Owner != id.User; } }


Aquí hay una versión modificada de esta respuesta para incluir cosas como la eliminación adecuada de los recursos y el manejo de los Administradores de Dominio.

public static class UacHelper { private const string uacRegistryKey = "Software//Microsoft//Windows//CurrentVersion//Policies//System"; private const string uacRegistryValue = "EnableLUA"; private static uint STANDARD_RIGHTS_READ = 0x00020000; private static uint TOKEN_QUERY = 0x0008; private static uint TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY); [DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle); [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool CloseHandle(IntPtr hObject); [DllImport("advapi32.dll", SetLastError = true)] public static extern bool GetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, IntPtr TokenInformation, uint TokenInformationLength, out uint ReturnLength); public enum TOKEN_INFORMATION_CLASS { TokenUser = 1, TokenGroups, TokenPrivileges, TokenOwner, TokenPrimaryGroup, TokenDefaultDacl, TokenSource, TokenType, TokenImpersonationLevel, TokenStatistics, TokenRestrictedSids, TokenSessionId, TokenGroupsAndPrivileges, TokenSessionReference, TokenSandBoxInert, TokenAuditPolicy, TokenOrigin, TokenElevationType, TokenLinkedToken, TokenElevation, TokenHasRestrictions, TokenAccessInformation, TokenVirtualizationAllowed, TokenVirtualizationEnabled, TokenIntegrityLevel, TokenUIAccess, TokenMandatoryPolicy, TokenLogonSid, MaxTokenInfoClass } public enum TOKEN_ELEVATION_TYPE { TokenElevationTypeDefault = 1, TokenElevationTypeFull, TokenElevationTypeLimited } public static bool IsUacEnabled { get { using (RegistryKey uacKey = Registry.LocalMachine.OpenSubKey(uacRegistryKey, false)) { bool result = uacKey.GetValue(uacRegistryValue).Equals(1); return result; } } } public static bool IsProcessElevated { get { if (IsUacEnabled) { IntPtr tokenHandle = IntPtr.Zero; if (!OpenProcessToken(Process.GetCurrentProcess().Handle, TOKEN_READ, out tokenHandle)) { throw new ApplicationException("Could not get process token. Win32 Error Code: " + Marshal.GetLastWin32Error()); } try { TOKEN_ELEVATION_TYPE elevationResult = TOKEN_ELEVATION_TYPE.TokenElevationTypeDefault; int elevationResultSize = Marshal.SizeOf(typeof(TOKEN_ELEVATION_TYPE)); uint returnedSize = 0; IntPtr elevationTypePtr = Marshal.AllocHGlobal(elevationResultSize); try { bool success = GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenElevationType, elevationTypePtr, (uint) elevationResultSize, out returnedSize); if (success) { elevationResult = (TOKEN_ELEVATION_TYPE) Marshal.ReadInt32(elevationTypePtr); bool isProcessAdmin = elevationResult == TOKEN_ELEVATION_TYPE.TokenElevationTypeFull; return isProcessAdmin; } else { throw new ApplicationException("Unable to determine the current elevation."); } } finally { if (elevationTypePtr != IntPtr.Zero) Marshal.FreeHGlobal(elevationTypePtr); } } finally { if (tokenHandle != IntPtr.Zero) CloseHandle(tokenHandle); } } else { WindowsIdentity identity = WindowsIdentity.GetCurrent(); WindowsPrincipal principal = new WindowsPrincipal(identity); bool result = principal.IsInRole(WindowsBuiltInRole.Administrator) || principal.IsInRole(0x200); //Domain Administrator return result; } } } }


Creo que hay un problema más. Revisé las soluciones proporcionadas por usted y tengo que decir que en la instalación de Windows 7 y que inicié sesión como administrador, el cheque no funciona. Windows nunca devuelve información que el proceso se ejecuta en un modo elevado. Entonces la secuencia:

if (IsUacEnabled) return IsProcessInElevatedMode(); return IsUserAdmin();

no devuelve verdadero cuando se registra como un administrador, pero el proceso tiene todos los privilegios para realizar operaciones del sistema (por ejemplo, detener los servicios del sistema). La secuencia de trabajo es:

if (IsUserAdmin()) return true; if (IsUacEnabled) return IsProcessInElevatedMode(); return false;

Primero debe verificar si el proceso se ejecuta en el contexto del Administrador. Información adicional:

IsUacEnabled() - checks if the UAC has been enabled in the system (Windows) IsProcessInElevatedMode() - checks if the process is run in an elevated mode IsUserAdmin() - checks if the current user has an Administrtor role

Todos esos métodos se han descrito en publicaciones anteriores.


El proyecto CodePlex UAChelper tiene un código que verifica la elevación en UserAccountControl.cpp UserAccountControl::IsUserAdmin , que verifica si UAC está habilitado y luego verifica si el proceso está elevado.

bool UserAccountControl::IsCurrentProcessElevated::get() { return GetProcessTokenElevationType() == TokenElevationTypeFull; //elevated }

de la función:

int UserAccountControl::GetProcessTokenElevationType() { HANDLE hToken; try { if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) throw gcnew Win32Exception(GetLastError()); TOKEN_ELEVATION_TYPE elevationType; DWORD dwSize; if (!GetTokenInformation(hToken, TokenElevationType, &elevationType, sizeof(elevationType), &dwSize)) throw gcnew Win32Exception(GetLastError()); return elevationType; } finally { CloseHandle(hToken); } }


En .net Framwork 4.5 encontré otro método que funciona para mí. En relación con el siguiente script que se puede encontrar aquí here (en alemán)

rem --- Admintest.bat --- whoami /groups | find "S-1-5-32-544" > nul if errorlevel 1 goto ende echo Benutzer %username% ist lokaler Administrator. :ende

En C # se ve así:

private bool IsAdmin { get { WindowsIdentity identity = WindowsIdentity.GetCurrent(); if (identity != null) { WindowsPrincipal principal = new WindowsPrincipal(identity); List<Claim> list = new List<Claim>(principal.UserClaims); Claim c = list.Find(p => p.Value.Contains("S-1-5-32-544")); if (c != null) return true; } return false; } }

Pero en .net <4.5, la clase WindowsPrincipal no contiene la propiedad UserClaims y no encontré la forma de obtener esta información.


Probar esto:

using Microsoft.Win32; using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Security.Principal; public static class UacHelper { private const string uacRegistryKey = "Software//Microsoft//Windows//CurrentVersion//Policies//System"; private const string uacRegistryValue = "EnableLUA"; private static uint STANDARD_RIGHTS_READ = 0x00020000; private static uint TOKEN_QUERY = 0x0008; private static uint TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY); [DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle); [DllImport("advapi32.dll", SetLastError = true)] public static extern bool GetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, IntPtr TokenInformation, uint TokenInformationLength, out uint ReturnLength); public enum TOKEN_INFORMATION_CLASS { TokenUser = 1, TokenGroups, TokenPrivileges, TokenOwner, TokenPrimaryGroup, TokenDefaultDacl, TokenSource, TokenType, TokenImpersonationLevel, TokenStatistics, TokenRestrictedSids, TokenSessionId, TokenGroupsAndPrivileges, TokenSessionReference, TokenSandBoxInert, TokenAuditPolicy, TokenOrigin, TokenElevationType, TokenLinkedToken, TokenElevation, TokenHasRestrictions, TokenAccessInformation, TokenVirtualizationAllowed, TokenVirtualizationEnabled, TokenIntegrityLevel, TokenUIAccess, TokenMandatoryPolicy, TokenLogonSid, MaxTokenInfoClass } public enum TOKEN_ELEVATION_TYPE { TokenElevationTypeDefault = 1, TokenElevationTypeFull, TokenElevationTypeLimited } public static bool IsUacEnabled { get { RegistryKey uacKey = Registry.LocalMachine.OpenSubKey(uacRegistryKey, false); bool result = uacKey.GetValue(uacRegistryValue).Equals(1); return result; } } public static bool IsProcessElevated { get { if (IsUacEnabled) { IntPtr tokenHandle; if (!OpenProcessToken(Process.GetCurrentProcess().Handle, TOKEN_READ, out tokenHandle)) { throw new ApplicationException("Could not get process token. Win32 Error Code: " + Marshal.GetLastWin32Error()); } TOKEN_ELEVATION_TYPE elevationResult = TOKEN_ELEVATION_TYPE.TokenElevationTypeDefault; int elevationResultSize = Marshal.SizeOf((int)elevationResult); uint returnedSize = 0; IntPtr elevationTypePtr = Marshal.AllocHGlobal(elevationResultSize); bool success = GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenElevationType, elevationTypePtr, (uint)elevationResultSize, out returnedSize); if (success) { elevationResult = (TOKEN_ELEVATION_TYPE)Marshal.ReadInt32(elevationTypePtr); bool isProcessAdmin = elevationResult == TOKEN_ELEVATION_TYPE.TokenElevationTypeFull; return isProcessAdmin; } else { throw new ApplicationException("Unable to determine the current elevation."); } } else { WindowsIdentity identity = WindowsIdentity.GetCurrent(); WindowsPrincipal principal = new WindowsPrincipal(identity); bool result = principal.IsInRole(WindowsBuiltInRole.Administrator); return result; } } } }


Usar TokenElevationType funcionaría, pero si PInvoca CheckTokenMembership() contra el SID del grupo de administración, tu código también funcionaría cuando UAC esté apagado y en 2000 / XP / 2003 y también manejará deny SID.

También hay una función IsUserAnAdmin() que hace la comprobación CheckTokenMembership por usted, pero MSDN dice que podría no estar allí para siempre.