Вопрос по c#, windows, .net – В .NET / C # тест, если процесс имеет административные привилегии

49

Есть ли канонический способ проверить, есть ли у процесса административные привилегии на компьютере?

Я собираюсь начать длительный процесс, и гораздо позже, в процессе ». В течение жизни он попытается сделать некоторые вещи, требующие прав администратора.

Я хотел бы иметь возможность протестировать заранее, если процесс обладает этими правами, а не позже.

Какая версия ОС? John Saunders

Ваш Ответ

9   ответов
2

Попробовал код Эрвина, но он не скомпилировался.

Получил это работать так:

[DllImport("shell32.dll")] public static extern bool IsUserAnAdmin();
Выглядит как & quot; Конец поддержки клиента: Windows Vista & quot; часть была удалена из статьи, хотя она все еще намекает на возможное [устаревание].
+1: этоcanonical way в соответствии с просьбой ОП.
конечно нужноusing System.Runtime.InteropServices;
-1: страница MSDN для IsUserAnAdminlink говорится: «Конец поддержки клиента: Windows Vista». Эта функция может быть недоступна для будущих версий Windows, поэтому она определенно не является «канонической». путь.
Для меня это сработало как победитель - у кого-нибудь есть идея, как на самом деле выглядит код внутри функции IsUserAnAdmin?
27

Начиная с кода Wadih M, у меня есть некоторый дополнительный код P / Invoke, чтобы попытаться обработать случай, когда UAC включен.

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

Во-первых, нам понадобится некоторый код для поддержки вызова 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
}

Затем фактический код для определения, является ли пользователь администратором (возвращает true, если они есть, в противном случае - 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);
}
Это наиболее полный ответ, в котором рассматриваются проблемы, при которых вызов IsInRole (WindowsBuiltInRole.Administrator) возвращает значение false, поскольку UAC блокирует. Подтверждено для правильной работы на Windows 8.
отлично работает на Vista - спасибо!
Это отличный ответ, но не на этот вопрос!
0

Есть 4 возможных метода - я предпочитаю:

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

Ниже приведен код, который предоставит вам список всех соответствующих данных претензии для вашего текущего пользователя.

NOTE: существует большая разница между списком заявок, который возвращается междуWindowsPrincipal.Current. Требования и(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();
@HarryJohnston спасибо за отзыв. Я не знаю, почему сейчас, почему? (как и у вас, у меня нет доступа к внутренним компонентам Microsoft), я только что обнаружил «что», что очевидно из запуска эксперимента. Удачи тебе.
Возможно, это было бы более полезно, если бы вы указали, что на самом деле означает каждый из этих результатов, и в чем разница междуWindowsPrincipal а такжеnew WindowsPrincipal и почему.
2

Другие ответы, использующие метод IsInRole, возвращают true, только если пользователь работает с маркером с повышенными правами, как прокомментировали другие. Вот потенциальная альтернатива проверки только на членство в локальной группе администраторов как в стандартном, так и в расширенном контексте:

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;
должен быть ответ
1

Использование может использовать WMI с чем-то вроде этого, чтобы выяснить, является ли учетная запись администратором, и почти все, что вы хотите знать об этой учетной записи

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);
            }
        }
    }
}

Чтобы было легче начать загрузкуWMI Creator

Вы также можете использовать его для доступа к активному каталогу (LDAP) или к чему-либо еще на вашем компьютере / сети.

На моем четырехъядерном процессоре i7 машина зависла на 7 секунд, пока не вернулся звонок.
76

Это проверит, находится ли пользователь в локальной группе администраторов (при условии, что вы не проверяете права администратора домена)

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;
}
Это определит, находится ли пользователь в группе «BUILTIN \ Администраторы», но покажет ли он, повышен ли пользователь в Vista?
@Jared: он также скрывает любые серьезные ошибки, которые могут произойти в этом блоке. Это должно быть удалено.
Я проверил это на Windows Server 2008 с включенным UAC. Это работает так: повышенный администратор - & gt; правда, администратор без повышенных прав - & gt; false, стандартный пользователь - & gt; ложный
Это не будет работать в Vista, если UAC включен. Причина в том, что UAC создает «разделенный токен» для пользователей с привилегиями администратора и разделенным токеном явно исключает все роли администратора (включая такие вещи, как «администратор домена»).
@Jacob Proffitt Если вы не администраторprincipal.IsInRole(WindowsBuiltInRole.Administrator); вернет false, он вернет true, только если вы являетесь администратором с повышенными правами.
3

Используя .NET Framework 4.5, кажется, проще проверить, находится ли пользователь в группе администраторов:

WindowsPrincipal principal = WindowsPrincipal.Current;
bool canBeAdmin = principal.Claims.Any((c) => c.Value == "S-1-5-32-544");
Обратите внимание - существует большая разница между списком утверждений, который возвращается между WindowsPrincipal.Current.Claims и (new WindowsPrincipal (WindowsIdentity.GetCurrent ())). Заявки см. В моем ответе ниже
17

Если вы хотите убедиться, что ваше решение работает в Vista UAC и имеет .Net Framework 3.5 или выше, вы можете использовать пространство имен System.DirectoryServices.AccountManagement. Ваш код будет выглядеть примерно так:

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;
}
ПОЖАЛУЙСТА, не делайте жестких кодов администраторов (уверен, что это локализуемая строка, а не известная строка BUILTIN \ ADministrators)
В соответствии со страницей MSDN вы можете использовать SID, который, как я считаю, является "S-1-5-32-544".msdn.microsoft.com/en-us/library/bb359434.aspx
это покажет, если пользователь повышен в Vista?
Так что бы ты использовал, Рубен?
Этоshould, Я не проверял его на аккаунте встроенных администраторов. Мое приложение тестировалось по домену.theruntime.com/blogs/jacob/archive/2009/02/13/…
0

Как насчет:

using System.Runtime.InteropServices;

internal static class Useful {
    [DllImport("shell32.dll", EntryPoint = "IsUserAnAdmin")]
    public static extern bool IsUserAnAdministrator();
}
Это не поддерживается за пределами Vista в соответствии с документами API:msdn.microsoft.com/en-us/library/windows/desktop/…

Похожие вопросы