有没有一种规范的方法可以测试进程是否在机器上拥有管理员权限?
我将启动一个长时间运行的进程,该进程的生命周期后期将尝试一些需要管理员权限的操作。
我想事先测试进程是否具有这些权限,而不是后来再测试。
这将检查用户是否在本地管理员组中(假设您不是检查域管理员权限)
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;
}
从Wadih M的代码开始,我有一些额外的P/Invoke代码来尝试处理UAC打开的情况。
首先,我们需要一些支持GetTokenInformation API调用的代码:
[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);
}
如果你想确保你的解决方案在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;
}
尝试了Erwin的代码,但它无法编译。
我按照以下方式使其工作:
[DllImport("shell32.dll")] public static extern bool IsUserAnAdmin();
使用.NET Framework 4.5,似乎更容易检查用户是否属于管理员组:
WindowsPrincipal principal = WindowsPrincipal.Current;
bool canBeAdmin = principal.Claims.Any((c) => c.Value == "S-1-5-32-544");
[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;
}
当UAC生效时(Windows)或应用程序在Linux上以超级用户身份运行(例如sudo myapp
)时,它返回true
。
如果有人有机会在MacOS上测试,请分享您的发现。
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;
你可以使用类似以下的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)或计算机/网络上的其他任何内容。
有4种可能的方法 - 我更喜欢:
(new WindowsPrincipal(WindowsIdentity.GetCurrent())).IsInRole(WindowsBuiltInRole.Administrator);
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();
WindowsPrincipal
和new WindowsPrincipal
之间的区别以及原因,则这可能会更有用。 - Harry Johnston这个怎么样:
using System.Runtime.InteropServices;
internal static class Useful {
[DllImport("shell32.dll", EntryPoint = "IsUserAnAdmin")]
public static extern bool IsUserAnAdministrator();
}
principal.IsInRole(WindowsBuiltInRole.Administrator)
将返回 false,它仅在您是提升的管理员时返回 true。 - Scott Chamberlain