检测是否以pipe理员身份运行,是否具有提升的权限?
我有一个应用程序,需要检测是否运行与提升特权或不。 我目前有这样的代码设置:
static bool IsAdministrator() { WindowsIdentity identity = WindowsIdentity.GetCurrent(); WindowsPrincipal principal = new WindowsPrincipal(identity); return principal.IsInRole (WindowsBuiltInRole.Administrator); }
这用于检测用户是否是pipe理员,但是如果以pipe理员身份运行,则不起作用。 (例如在vshost.exe中)。
我怎样才能确定提升是否[已经生效或可能] ?
试试这个:
using Microsoft.Win32; using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Security.Principal; public static class UacHelper { private const string uacRegistryKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System"; private const string uacRegistryValue = "EnableLUA"; private static uint STANDARD_RIGHTS_READ = 0x00020000; private static uint TOKEN_QUERY = 0x0008; private static uint TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY); [DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle); [DllImport("advapi32.dll", SetLastError = true)] public static extern bool GetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, IntPtr TokenInformation, uint TokenInformationLength, out uint ReturnLength); public enum TOKEN_INFORMATION_CLASS { 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 } public enum TOKEN_ELEVATION_TYPE { TokenElevationTypeDefault = 1, TokenElevationTypeFull, TokenElevationTypeLimited } public static bool IsUacEnabled { get { RegistryKey uacKey = Registry.LocalMachine.OpenSubKey(uacRegistryKey, false); bool result = uacKey.GetValue(uacRegistryValue).Equals(1); return result; } } public static bool IsProcessElevated { get { if (IsUacEnabled) { IntPtr tokenHandle; if (!OpenProcessToken(Process.GetCurrentProcess().Handle, TOKEN_READ, out tokenHandle)) { throw new ApplicationException("Could not get process token. Win32 Error Code: " + Marshal.GetLastWin32Error()); } TOKEN_ELEVATION_TYPE elevationResult = TOKEN_ELEVATION_TYPE.TokenElevationTypeDefault; int elevationResultSize = Marshal.SizeOf((int)elevationResult); uint returnedSize = 0; IntPtr elevationTypePtr = Marshal.AllocHGlobal(elevationResultSize); bool success = GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenElevationType, elevationTypePtr, (uint)elevationResultSize, out returnedSize); if (success) { elevationResult = (TOKEN_ELEVATION_TYPE)Marshal.ReadInt32(elevationTypePtr); bool isProcessAdmin = elevationResult == TOKEN_ELEVATION_TYPE.TokenElevationTypeFull; return isProcessAdmin; } else { throw new ApplicationException("Unable to determine the current elevation."); } } else { WindowsIdentity identity = WindowsIdentity.GetCurrent(); WindowsPrincipal principal = new WindowsPrincipal(identity); bool result = principal.IsInRole(WindowsBuiltInRole.Administrator); return result; } } } }
(问题提出六年后的新答案)
免责声明:这只是发生在我的特定的操作系统上,与我的特定用户的特定设置:
using System.Security.Principal; // ... static bool IsElevated { get { return WindowsIdentity.GetCurrent().Owner .IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid); } }
所以当我运行这个“以pipe理员身份运行”时,属性get
访问器返回true
。 当正常运行时(即使我的用户“是”pipe理员,只是没有以pipe理员身份运行这个特定的应用程序),它返回false
。
这似乎比许多其他答案更简单。
我不知道是否有这种情况失败。
PS! 这也似乎确定:
static bool IsElevated { get { var id = WindowsIdentity.GetCurrent(); return id.Owner != id.User; } }
CodePlex项目UAChelper具有检查UserAccountControl.cpp中的高程的代码UserAccountControl::IsUserAdmin
,该代码检查UAC是否启用,然后检查进程是否boost。
bool UserAccountControl::IsCurrentProcessElevated::get() { return GetProcessTokenElevationType() == TokenElevationTypeFull; //elevated }
从function:
int UserAccountControl::GetProcessTokenElevationType() { HANDLE hToken; try { if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) throw gcnew Win32Exception(GetLastError()); TOKEN_ELEVATION_TYPE elevationType; DWORD dwSize; if (!GetTokenInformation(hToken, TokenElevationType, &elevationType, sizeof(elevationType), &dwSize)) throw gcnew Win32Exception(GetLastError()); return elevationType; } finally { CloseHandle(hToken); } }
这里是这个答案的修改版本,包括正确处理资源和处理域pipe理员的事情。
public static class UacHelper { private const string uacRegistryKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System"; private const string uacRegistryValue = "EnableLUA"; private static uint STANDARD_RIGHTS_READ = 0x00020000; private static uint TOKEN_QUERY = 0x0008; private static uint TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY); [DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle); [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool CloseHandle(IntPtr hObject); [DllImport("advapi32.dll", SetLastError = true)] public static extern bool GetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, IntPtr TokenInformation, uint TokenInformationLength, out uint ReturnLength); public enum TOKEN_INFORMATION_CLASS { 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 } public enum TOKEN_ELEVATION_TYPE { TokenElevationTypeDefault = 1, TokenElevationTypeFull, TokenElevationTypeLimited } public static bool IsUacEnabled { get { using (RegistryKey uacKey = Registry.LocalMachine.OpenSubKey(uacRegistryKey, false)) { bool result = uacKey.GetValue(uacRegistryValue).Equals(1); return result; } } } public static bool IsProcessElevated { get { if (IsUacEnabled) { IntPtr tokenHandle = IntPtr.Zero; if (!OpenProcessToken(Process.GetCurrentProcess().Handle, TOKEN_READ, out tokenHandle)) { throw new ApplicationException("Could not get process token. Win32 Error Code: " + Marshal.GetLastWin32Error()); } try { TOKEN_ELEVATION_TYPE elevationResult = TOKEN_ELEVATION_TYPE.TokenElevationTypeDefault; int elevationResultSize = Marshal.SizeOf(typeof(TOKEN_ELEVATION_TYPE)); uint returnedSize = 0; IntPtr elevationTypePtr = Marshal.AllocHGlobal(elevationResultSize); try { bool success = GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenElevationType, elevationTypePtr, (uint) elevationResultSize, out returnedSize); if (success) { elevationResult = (TOKEN_ELEVATION_TYPE) Marshal.ReadInt32(elevationTypePtr); bool isProcessAdmin = elevationResult == TOKEN_ELEVATION_TYPE.TokenElevationTypeFull; return isProcessAdmin; } else { throw new ApplicationException("Unable to determine the current elevation."); } } finally { if (elevationTypePtr != IntPtr.Zero) Marshal.FreeHGlobal(elevationTypePtr); } } finally { if (tokenHandle != IntPtr.Zero) CloseHandle(tokenHandle); } } else { WindowsIdentity identity = WindowsIdentity.GetCurrent(); WindowsPrincipal principal = new WindowsPrincipal(identity); bool result = principal.IsInRole(WindowsBuiltInRole.Administrator) || principal.IsInRole(0x200); //Domain Administrator return result; } } } }
使用TokenElevationType
可以工作,但是如果您对pipe理组SID使用PInvoke CheckTokenMembership()
,那么当UAC处于closures状态并在2000 / XP / 2003上时,您的代码也将工作,并且还将处理拒绝的SID。
还有一个IsUserAnAdmin()
函数为您执行CheckTokenMembership
检查,但MSDN表示它可能不会永远在那里
在.net Framwork 4.5中,我find了另一种适用于我的方法。 关于这里可以find的以下脚本(用德语)
rem --- Admintest.bat --- whoami /groups | find "S-1-5-32-544" > nul if errorlevel 1 goto ende echo Benutzer %username% ist lokaler Administrator. :ende
在C#中,它看起来像这样:
private bool IsAdmin() { WindowsIdentity identity = WindowsIdentity.GetCurrent(); if (identity != null) { WindowsPrincipal principal = new WindowsPrincipal(identity); List<Claim> list = new List<Claim>(principal.UserClaims); Claim c = list.Find(p => p.Value.Equals("S-1-5-32-544")); if (c != null) return true; } return false; }
但是在.net <4.5 WindowsPrincipal
类不包含UserClaims
属性,我发现没有办法得到这个信息。
我认为还有一个问题。 我查了你提供的解决scheme,不得不说,在安装Windows 7和作为pipe理员login检查不起作用。 Windows从不返回进程在提升模式下运行的信息。 所以序列:
if (IsUacEnabled) return IsProcessInElevatedMode(); return IsUserAdmin();
以pipe理员身份login时不会返回true,但该进程拥有执行系统操作(例如,停止系统服务)的所有权限。 工作顺序是:
if (IsUserAdmin()) return true; if (IsUacEnabled) return IsProcessInElevatedMode(); return false;
您应该首先检查进程是否在pipe理员上下文中运行。 附加信息:
IsUacEnabled() - checks if the UAC has been enabled in the system (Windows) IsProcessInElevatedMode() - checks if the process is run in an elevated mode IsUserAdmin() - checks if the current user has an Administrtor role
所有这些方法已经在之前的文章中描述过了。