Is there a canonical way to test to see if the process has administrative privileges on a machine?
I\'m going to be starting a long running process, and much later
There are 4 possible Methods - I prefer:
(new WindowsPrincipal(WindowsIdentity.GetCurrent())).IsInRole(WindowsBuiltInRole.Administrator);
Here is code to give you a list of all the relevant claim data for your current user's Identity.
NOTE: there is a big difference beween the claims list that is returned between WindowsPrincipal.Current.Claims and (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();
Using the .NET Framework 4.5, it seems to be easier to check if a user is in the administrators group:
WindowsPrincipal principal = WindowsPrincipal.Current;
bool canBeAdmin = principal.Claims.Any((c) => c.Value == "S-1-5-32-544");
The following is tested to work in .NET Core 3 on Windows 10 and Ubuntu Linux:
[DllImport("libc")]
public static extern uint getuid(); // Only used on Linux but causes no issues on Windows
static bool RunningAsAdmin()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
using var identity = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
else return getuid() == 0;
}
It returns true
when UAC is in effect (Windows) or when the application is running as superuser on Linux (e.g. sudo myapp
).
If anyone has the opportunity to test on MacOS, please share your findings.
Starting with Wadih M's code, I've got some additional P/Invoke code to try and handle the case of when UAC is on.
http://www.davidmoore.info/blog/2011/06/20/how-to-check-if-the-current-user-is-an-administrator-even-if-uac-is-on/
First, we’ll need some code to support the GetTokenInformation API call:
[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
}
Then, the actual code to detect if the user is an Administrator (returning true if they are, otherwise 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);
}
Other answers leveraging the IsInRole method only return true if the user is running with an elevated token, as others have commented. Here is a potential alternative for checking just for local Administrators group membership in both a standard and elevated context:
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;
Tried Erwin's code but it didn't compile.
Got it to work like this:
[DllImport("shell32.dll")] public static extern bool IsUserAnAdmin();