J'ai une application qui doit détecter si elle s'exécute ou non avec des privilèges élevés. J'ai actuellement le code mis en place comme ceci:
static bool IsAdministrator()
{
WindowsIdentity identity = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(identity);
return principal.IsInRole (WindowsBuiltInRole.Administrator);
}
Cela fonctionne pour détecter si un utilisateur est un administrateur ou non, mais ne fonctionne pas s'il est exécuté en tant qu'administrateur sans élévation. (Par exemple, dans vshost.exe).
Comment puis-je déterminer si l'élévation est [déjà en vigueur ou] possible ?
Essayez ceci:
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;
}
}
}
}
(nouvelle réponse six ans après que la question a été posée)
Clause de non-responsabilité: il s’agit simplement de quelque chose qui fonctionne sur mon système d’exploitation particulier avec mes paramètres particuliers avec mon utilisateur particulier:
using System.Security.Principal;
// ...
static bool IsElevated
{
get
{
return WindowsIdentity.GetCurrent().Owner
.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid);
}
}
Ainsi, lorsque j'exécute ce "Exécuter en tant qu'administrateur", la propriété get
accessor renvoie true
. Lors d'une exécution normale (même si mon utilisateur "est" administrateur, cette application particulière n'est pas exécutée "en tant qu'administrateur"), il renvoie false
.
Cela semble beaucoup plus simple que beaucoup d'autres réponses.
Je ne sais pas s'il y a des cas où cela échoue.
PS! Cela semble aussi OK:
static bool IsElevated
{
get
{
var id = WindowsIdentity.GetCurrent();
return id.Owner != id.User;
}
}
Voici une version modifiée de cette réponse pour inclure des éléments tels que l’élimination appropriée des ressources et le traitement des administrateurs de domaine.
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;
}
}
}
}
Le projet CodePlex UAChelper a un code qui vérifie l'élévation dans UserAccountControl.cpp UserAccountControl::IsUserAdmin
, qui vérifie si le contrôle de compte d'utilisateur est activé, puis le processus est élevé.
bool UserAccountControl::IsCurrentProcessElevated::get()
{
return GetProcessTokenElevationType() == TokenElevationTypeFull; //elevated
}
de la fonction:
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);
}
}
Dans .net Framwork 4.5, j’ai trouvé une autre méthode qui marche pour moi . En ce qui concerne le script suivant, disponible ici ici (en allemand)
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 #, cela ressemble à ceci:
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;
}
}
Mais dans .net <4.5, la classe WindowsPrincipal
ne contient pas la propriété UserClaims
Je n’ai trouvé aucun moyen d’obtenir cette information.
Utiliser TokenElevationType
fonctionnerait, mais si vous PInvoke CheckTokenMembership()
par rapport au SID du groupe d’administrateurs, votre code fonctionnerait également lorsque le contrôle de compte d'utilisateur est désactivé et sous 2000/XP/2003 et traitera également le refus des SID.
Il existe également une fonction IsUserAnAdmin()
qui effectue la vérification CheckTokenMembership
pour vous, mais MSDN indique qu'elle risque de ne pas être là pour toujours.
Utilisation de UACHelper nuget package: https://www.nuget.org/packages/UACHelper/
if (UACHelper.IsElevated)
// something
else
// something else
De nombreuses autres propriétés peuvent être utilisées pour détecter si l'utilisateur est en fait un administrateur, ou si le processus est exécuté sous la virtualisation du contrôle de compte d'utilisateur, ou si le propriétaire du bureau est le propriétaire du processus. (Exécuter à partir d'un compte limité)
Vérifiez la lecture moi pour plus d'informations.
Cette réponse a quelques problèmes. Premièrement, aucun processus système s'exécutant en tant qu'administrateur (par exemple, sous NT-Authority/SYSTEM). L'exemple de code ci-dessous résout tous les problèmes (détecte LocalAdmins, DomainAdmins et LocalSystemAdmins).
Si vous voulez seulement le processus en cours, remplacez pHandle
par Process.GetCurrentProcess().Handle
REMARQUE: vous devez disposer de certains privilèges pour l'exécuter. (Chaque AdminProcess les a mais doit d'abord les activer, les services les ont activés par défaut)
internal static bool IsProcessElevatedEx(this IntPtr pHandle) {
var token = IntPtr.Zero;
if (!OpenProcessToken(pHandle, MAXIMUM_ALLOWED, ref token))
throw new Win32Exception(Marshal.GetLastWin32Error(), "OpenProcessToken failed");
WindowsIdentity identity = new WindowsIdentity(token);
WindowsPrincipal principal = new WindowsPrincipal(identity);
bool result = principal.IsInRole(WindowsBuiltInRole.Administrator)
|| principal.IsInRole(0x200); //Domain Administrator
CloseHandle(token);
return result;
}
Je pense qu'il y a un autre problème. J'ai vérifié les solutions fournies par vous et je dois dire que lors de l'installation de Windows 7 et connecté en tant qu'administrateur, la vérification ne fonctionne pas. Windows ne renvoie jamais d'informations selon lesquelles le processus s'exécute en mode élevé. Donc la séquence:
if (IsUacEnabled)
return IsProcessInElevatedMode();
return IsUserAdmin();
ne renvoie pas la valeur true lorsqu'il est connecté en tant qu'administrateur, mais le processus dispose de tous les privilèges pour effectuer des opérations système (par exemple, arrêter les services système) .
if (IsUserAdmin())
return true;
if (IsUacEnabled)
return IsProcessInElevatedMode();
return false;
Vous devez d’abord vérifier si le processus est exécuté dans le contexte Administrateur . Informations supplémentaires:
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
Toutes ces méthodes ont été décrites dans les précédents articles.