web-dev-qa-db-fra.com

En test .NET/C # si le processus a des privilèges d’administrateur

Existe-t-il un moyen canonique de vérifier si le processus a des privilèges d’administrateur sur une machine? 

Je vais commencer un processus long, et beaucoup plus tard dans la vie du processus, il va essayer certaines choses qui nécessitent des privilèges d'administrateur.

J'aimerais pouvoir vérifier si le processus dispose de ces droits plutôt que plus tard.

49
Clinton Pierce

Cela vérifiera si l'utilisateur est dans le groupe Administrateurs local (en supposant que vous ne vérifiez pas les autorisations d'administrateur de domaine)

using System.Security.Principal;

public bool IsUserAdministrator()
{
    //bool value to hold our return value
    bool isAdmin;
    WindowsIdentity user = null;
    try
    {
        //get the currently logged in user
        user = WindowsIdentity.GetCurrent();
        WindowsPrincipal principal = new WindowsPrincipal(user);
        isAdmin = principal.IsInRole(WindowsBuiltInRole.Administrator);
    }
    catch (UnauthorizedAccessException ex)
    {
        isAdmin = false;
    }
    catch (Exception ex)
    {
        isAdmin = false;
    }
    finally
    {
        if (user != null)
            user.Dispose();
    }
    return isAdmin;
}
76
Wadih M.

En commençant par le code de Wadih M, j'ai un code supplémentaire P/Invoke pour essayer de gérer le cas où le contrôle de compte d'utilisateur est activé.

http://www.davidmoore.info/blog/2011/06/20/how-to-check-if-the-current-user-is-an-administrator-even-if-uac-is-on/

Tout d’abord, nous aurons besoin de code pour prendre en charge l’appel d’API GetTokenInformation:

[DllImport("advapi32.dll", SetLastError = true)]
static extern bool GetTokenInformation(IntPtr tokenHandle, TokenInformationClass tokenInformationClass, IntPtr tokenInformation, int tokenInformationLength, out int returnLength);

/// <summary>
/// Passed to <see cref="GetTokenInformation"/> to specify what
/// information about the token to return.
/// </summary>
enum TokenInformationClass
{
     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
}

/// <summary>
/// The elevation type for a user token.
/// </summary>
enum TokenElevationType
{
    TokenElevationTypeDefault = 1,
    TokenElevationTypeFull,
    TokenElevationTypeLimited
}

Ensuite, le code à détecter si l’utilisateur est un administrateur (renvoie true s’ils le sont, sinon false).

var identity = WindowsIdentity.GetCurrent();
if (identity == null) throw new InvalidOperationException("Couldn't get the current user identity");
var principal = new WindowsPrincipal(identity);

// Check if this user has the Administrator role. If they do, return immediately.
// If UAC is on, and the process is not elevated, then this will actually return false.
if (principal.IsInRole(WindowsBuiltInRole.Administrator)) return true;

// If we're not running in Vista onwards, we don't have to worry about checking for UAC.
if (Environment.OSVersion.Platform != PlatformID.Win32NT || Environment.OSVersion.Version.Major < 6)
{
     // Operating system does not support UAC; skipping elevation check.
     return false;
}

int tokenInfLength = Marshal.SizeOf(typeof(int));
IntPtr tokenInformation = Marshal.AllocHGlobal(tokenInfLength);

try
{
    var token = identity.Token;
    var result = GetTokenInformation(token, TokenInformationClass.TokenElevationType, tokenInformation, tokenInfLength, out tokenInfLength);

    if (!result)
    {
        var exception = Marshal.GetExceptionForHR( Marshal.GetHRForLastWin32Error() );
        throw new InvalidOperationException("Couldn't get token information", exception);
    }

    var elevationType = (TokenElevationType)Marshal.ReadInt32(tokenInformation);

    switch (elevationType)
    {
        case TokenElevationType.TokenElevationTypeDefault:
            // TokenElevationTypeDefault - User is not using a split token, so they cannot elevate.
            return false;
        case TokenElevationType.TokenElevationTypeFull:
            // TokenElevationTypeFull - User has a split token, and the process is running elevated. Assuming they're an administrator.
            return true;
        case TokenElevationType.TokenElevationTypeLimited:
            // TokenElevationTypeLimited - User has a split token, but the process is not running elevated. Assuming they're an administrator.
            return true;
        default:
            // Unknown token elevation type.
            return false;
     }
}
finally
{    
    if (tokenInformation != IntPtr.Zero) Marshal.FreeHGlobal(tokenInformation);
}
27
David Moore

Si vous voulez vous assurer que votre solution fonctionne dans Vista UAC et que vous avez .Net Framework 3.5 ou une version supérieure, vous souhaiterez peut-être utiliser l'espace de noms System.DirectoryServices.AccountManagement. Votre code ressemblerait à quelque chose comme:

bool isAllowed = false;
using (PrincipalContext pc = new PrincipalContext(ContextType.Machine, null))
{
    UserPrincipal up = UserPrincipal.Current;
    GroupPrincipal gp = GroupPrincipal.FindByIdentity(pc, "Administrators");
    if (up.IsMemberOf(gp))
        isAllowed = true;
}
17
Jacob Proffitt

À l'aide de .NET Framework 4.5, il semble plus facile de vérifier si un utilisateur appartient au groupe des administrateurs:

WindowsPrincipal principal = WindowsPrincipal.Current;
bool canBeAdmin = principal.Claims.Any((c) => c.Value == "S-1-5-32-544");
3
Jens

J'ai essayé le code d'Erwin mais il n'a pas compilé.

Je dois réussir comme ça:

[DllImport("Shell32.dll")] public static extern bool IsUserAnAdmin();
2
Alex G.

D'autres réponses utilisant la méthode IsInRole ne renvoient true que si l'utilisateur s'exécute avec un jeton élevé, comme d'autres l'ont commenté. Voici une alternative potentielle pour vérifier uniquement l'appartenance au groupe d'administrateurs locaux dans un contexte standard et élevé:

bool isAdmin = false;
using (var user = WindowsIdentity.GetCurrent())
{
    var principal = new WindowsPrincipal(user);
    // Check for token claim with well-known Administrators group SID
    const string LOCAL_ADMININSTRATORS_GROUP_SID = "S-1-5-32-544";
    if (principal.Claims.SingleOrDefault(x => x.Value == LOCAL_ADMININSTRATORS_GROUP_SID) != null)
    {
        isAdmin = true;
    }
}

return isAdmin;
2
Noah Stahl

Utilisation peut utiliser WMI avec quelque chose comme ceci pour savoir si le compte est un administrateur et à peu près tout ce que vous voulez savoir sur ce compte.

using System;
using System.Management;
using System.Windows.Forms;

namespace WMISample
{
    public class MyWMIQuery
    {
        public static void Main()
        {
            try
            {
                ManagementObjectSearcher searcher = 
                    new ManagementObjectSearcher("root\\CIMV2", 
                    "SELECT * FROM Win32_UserAccount"); 

                foreach (ManagementObject queryObj in searcher.Get())
                {
                    Console.WriteLine("-----------------------------------");
                    Console.WriteLine("Win32_UserAccount instance");
                    Console.WriteLine("-----------------------------------");
                    Console.WriteLine("AccountType: {0}", queryObj["AccountType"]);
                    Console.WriteLine("FullName: {0}", queryObj["FullName"]);
                    Console.WriteLine("Name: {0}", queryObj["Name"]);
                }
            }
            catch (ManagementException e)
            {
                MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
            }
        }
    }
}

Pour faciliter le téléchargement, téléchargez WMI Creator

vous pouvez également l'utiliser pour accéder à Active Directory (LDAP) ou à tout autre élément de votre ordinateur/réseau 

1
Bob The Janitor

Il y a 4 méthodes possibles - je préfère:

(new WindowsPrincipal(WindowsIdentity.GetCurrent())).IsInRole(WindowsBuiltInRole.Administrator);

Voici le code pour vous donner une liste de toutes les données de réclamation pertinentes pour l'identité de votre utilisateur actuel.

REMARQUE: il existe une grande différence entre la liste des revendications renvoyée entre WindowsPrincipal.Current .Claims et (new WindowsPrincipal (WindowsIdentity.GetCurrent ())) .Claims 

Console.WriteLine("press the ENTER key to start listing user claims:");
Console.ReadLine();

Console.WriteLine("---------------------");
Console.WriteLine("---------------------");
bool canBeAdmin = (new WindowsPrincipal(WindowsIdentity.GetCurrent())).IsInRole(WindowsBuiltInRole.Administrator);
Console.WriteLine("GetCurrent IsInRole: canBeAdmin:{0}", canBeAdmin);

Console.WriteLine("---------------------");
Console.WriteLine("---------------------");
canBeAdmin = (new WindowsPrincipal(WindowsIdentity.GetCurrent())).Claims.Any((c) => c.Value == "S-1-5-32-544");
Console.WriteLine("GetCurrent Claim: canBeAdmin?:{0}", canBeAdmin);

Console.WriteLine("---------------------");
Console.WriteLine("---------------------");
canBeAdmin = (new WindowsPrincipal(WindowsIdentity.GetCurrent())).IsInRole("Administrator");
Console.WriteLine("GetCurrent IsInRole \"Administrator\": canBeAdmin?:{0}", canBeAdmin);

Console.WriteLine("---------------------");
Console.WriteLine("---------------------");
canBeAdmin = (new WindowsPrincipal(WindowsIdentity.GetCurrent())).IsInRole("Admin");
Console.WriteLine("GetCurrent IsInRole \"Admin\": canBeAdmin?:{0}", canBeAdmin);

Console.WriteLine("---------------------");
Console.WriteLine("---------------------");
canBeAdmin = WindowsPrincipal.Current.IsInRole("Admin");
Console.WriteLine("Current IsInRole \"Admin\": canBeAdmin:{0}", canBeAdmin);


Console.WriteLine("---------------------");
Console.WriteLine("---------------------");
canBeAdmin = WindowsPrincipal.Current.IsInRole("Administrator");
Console.WriteLine("Current IsInRole \"Administrator\": canBeAdmin:{0}", canBeAdmin);

Console.WriteLine("---------------------");
Console.WriteLine("---------------------");
canBeAdmin = WindowsPrincipal.Current.Claims.Any((c) => c.Value == "S-1-5-32-544");
Console.WriteLine("Current Claim: canBeAdmin?:{0}", canBeAdmin);

Console.WriteLine("---------------------");
Console.WriteLine("---------------------");
Console.WriteLine("WindowsPrincipal Claims:");
Console.WriteLine("---------------------");

var propertyCount = 0;
foreach (var claim in WindowsPrincipal.Current.Claims)
{
    Console.WriteLine("{0}", propertyCount++);
    Console.WriteLine("{0}", claim.ToString());
    Console.WriteLine("Issuer:{0}", claim.Issuer);
    Console.WriteLine("Subject:{0}", claim.Subject);
    Console.WriteLine("Type:{0}", claim.Type);
    Console.WriteLine("Value:{0}", claim.Value);
    Console.WriteLine("ValueType:{0}", claim.ValueType);
}

Console.WriteLine("---------------------");
Console.WriteLine("---------------------");
Console.WriteLine("WindowsPrincipal Identities Claims");
Console.WriteLine("---------------------");

propertyCount = 0;
foreach (var identity in WindowsPrincipal.Current.Identities)
{
    int subPropertyCount = 0;
    foreach (var claim in identity.Claims)
    {
        Console.WriteLine("{0} {1}", propertyCount, subPropertyCount++);
        Console.WriteLine("{0}", claim.ToString());
        Console.WriteLine("Issuer:{0}", claim.Issuer);
        Console.WriteLine("Subject:{0}", claim.Subject);
        Console.WriteLine("Type:{0}", claim.Type);
        Console.WriteLine("Value:{0}", claim.Value);
        Console.WriteLine("ValueType:{0}", claim.ValueType);
    }
    Console.WriteLine();
    propertyCount++;
}

Console.WriteLine("---------------------");
Console.WriteLine("---------------------");
Console.WriteLine("Principal Id Claims");
Console.WriteLine("---------------------");

var p = new WindowsPrincipal(WindowsIdentity.GetCurrent());
foreach (var claim in (new WindowsPrincipal(WindowsIdentity.GetCurrent())).Claims)
{
    Console.WriteLine("{0}", propertyCount++);
    Console.WriteLine("{0}", claim.ToString());
    Console.WriteLine("Issuer:{0}", claim.Issuer);
    Console.WriteLine("Subject:{0}", claim.Subject);
    Console.WriteLine("Type:{0}", claim.Type);
    Console.WriteLine("Value:{0}", claim.Value);
    Console.WriteLine("ValueType:{0}", claim.ValueType);
}

Console.WriteLine("press the ENTER key to end");
Console.ReadLine();
0
OzBob

Qu'en est-il de:

using System.Runtime.InteropServices;

internal static class Useful {
    [DllImport("Shell32.dll", EntryPoint = "IsUserAnAdmin")]
    public static extern bool IsUserAnAdministrator();
}
0
Erwin Mayer