代码之家  ›  专栏  ›  技术社区  ›  Clinton Pierce

在.NET/C中#测试进程是否具有管理权限

  •  49
  • Clinton Pierce  · 技术社区  · 16 年前

    是否有一种规范的方法来测试进程在计算机上是否具有管理权限?

    我将开始一个长时间运行的进程,在进程生命周期的稍后,它将尝试一些需要管理员权限的事情。

    我希望能够提前测试流程是否拥有这些权限,而不是稍后。

    9 回复  |  直到 10 年前
        1
  •  76
  •   Polynomial    9 年前

    这将检查用户是否在本地管理员组中(假设您没有检查域管理员权限)

    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
  •  27
  •   David Moore    10 年前

    从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/

    首先,我们需要一些代码来支持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);
    }
    
        3
  •  17
  •   Jacob Proffitt    16 年前

    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
  •  3
  •   Jens    11 年前

    尝试了欧文的代码,但没有编译。

    [DllImport("shell32.dll")] public static extern bool IsUserAnAdmin();
    
        5
  •  2
  •   Alex G.    12 年前

    使用.NET Framework 4.5,检查用户是否在administrators组中似乎更容易:

    WindowsPrincipal principal = WindowsPrincipal.Current;
    bool canBeAdmin = principal.Claims.Any((c) => c.Value == "S-1-5-32-544");
    
        6
  •  2
  •   Noah Stahl    9 年前

    其他使用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;
    
        7
  •  1
  •   Bob The Janitor    16 年前

    Use可以将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

    您还可以在访问active directory(LDAP)或计算机/网络上的任何其他内容时使用此选项

        8
  •  0
  •   Erwin Mayer    12 年前

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

    它回来了 true 当UAC生效时(Windows)或当应用程序在Linux上以超级用户身份运行时(例如。 sudo myapp ).

    如果有人有机会在MacOS上测试,请分享您的发现。

        9
  •  0
  •   Shayan Toqraee Aria Buckles    8 年前

    那么:

    using System.Runtime.InteropServices;
    
    internal static class Useful {
        [DllImport("shell32.dll", EntryPoint = "IsUserAnAdmin")]
        public static extern bool IsUserAnAdministrator();
    }