В .NET/С# тесте, если процесс имеет административные привилегии
Есть ли канонический способ проверить, имеет ли процесс административные привилегии на машине?
Я собираюсь начать длительный процесс, и намного позже в процессе "на всю жизнь" он попытается выполнить некоторые действия, требующие прав администратора.
Я бы хотел пройти тест, если процесс имеет эти права, а не позже.
Ответы
Ответ 1
Это проверит, находится ли пользователь в локальной группе администраторов (при условии, что вы не проверяете права доступа к домену)
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;
}
Ответ 2
Начиная с кода 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);
}
Ответ 3
Если вы хотите, чтобы ваше решение работало в 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;
}
Ответ 4
Используя .NET Framework 4.5, кажется, что проще проверить, находится ли пользователь в группе администраторов:
WindowsPrincipal principal = WindowsPrincipal.Current;
bool canBeAdmin = principal.Claims.Any((c) => c.Value == "S-1-5-32-544");
Ответ 5
Пробовал код Erwin, но он не компилировался.
Чтобы это работало следующим образом:
[DllImport("shell32.dll")] public static extern bool IsUserAnAdmin();
Ответ 6
Использование может использовать 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) или что-либо еще на вашем компьютере/сети
Ответ 7
Другие ответы, использующие метод 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;
Ответ 8
Как насчет:
using System.Runtime.InteropServices;
internal static class Useful {
[DllImport("shell32.dll", EntryPoint = "IsUserAnAdmin")]
public static extern bool IsUserAnAdministrator();
}
Ответ 9
Есть 4 возможных метода - я предпочитаю:
(new WindowsPrincipal(WindowsIdentity.GetCurrent())).IsInRole(WindowsBuiltInRole.Administrator);
Вот код, чтобы предоставить вам список всех соответствующих данных претензии для вашего текущего идентификатора пользователя.
ПРИМЕЧАНИЕ. существует большая разница между списком претензий, который возвращается между WindowsPrincipal.Current.Claims и (новый 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();