C# 检测是否以管理员身份运行,是否具有提升的权限?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1220213/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Detect if running as Administrator with or without elevated privileges?
提问by MiffTheFox
I have an application that needs to detect whether or not it is running with elevated privileges or not. I currently have code set up like this:
我有一个应用程序需要检测它是否以提升的权限运行。我目前的代码设置如下:
static bool IsAdministrator()
{
WindowsIdentity identity = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(identity);
return principal.IsInRole (WindowsBuiltInRole.Administrator);
}
This works to detect if a user is an administrator or not, but doesn't work if running as an administrator without elevation. (For example in vshost.exe).
这可以检测用户是否是管理员,但如果以管理员身份运行而没有提升,则不起作用。(例如在 vshost.exe 中)。
How can I determine whether or not elevation is [already in force or] possible?
我如何确定海拔是否 [已经生效或] 可能?
回答by Preet Sangha
The CodePlex project UAChelperhas code that checks on elevation in UserAccountControl.cpp UserAccountControl::IsUserAdmin
, that checks if UAC is enabled and then checks if process is elevated.
在CodePlex项目UAChelper有代码,在UserAccountControl.cpp海拔检查UserAccountControl::IsUserAdmin
,即检查是否启用UAC,然后检查进程是否升高。
bool UserAccountControl::IsCurrentProcessElevated::get()
{
return GetProcessTokenElevationType() == TokenElevationTypeFull; //elevated
}
from the 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);
}
}
回答by Anders
Using TokenElevationType
would work, but if you PInvoke CheckTokenMembership()
against the admin group SID, your code would also work when UAC is off and on 2000/XP/2003 and will also handle deny SID's.
使用TokenElevationType
会起作用,但是如果您CheckTokenMembership()
针对管理员组 SID 进行PInvoke ,则您的代码在 UAC 关闭和 2000/XP/2003 时也可以工作,并且还将处理拒绝 SID。
There is also a IsUserAnAdmin()
function that does the CheckTokenMembership
check for you, but MSDN says it might not be there forever
还有一个IsUserAnAdmin()
功能可以CheckTokenMembership
为您进行检查,但 MSDN 说它可能不会永远存在
回答by Steven
Try this out:
试试这个:
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;
}
}
}
}
回答by Scott Chamberlain
Here is a modified version of this answerto include things like the proper disposing of resources and handling of Domain Administrators.
这是此答案的修改版本,其中包括正确处置资源和处理域管理员等内容。
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;
}
}
}
}
回答by Rafael
In .net Framwork 4.5 I found another method that works for me. In relation to the following script that can be found here here(in German)
在 .net 框架 4.5 中,我找到了另一种适合我的方法。关于可以在此处找到的以下脚本(德语)
rem --- Admintest.bat ---
whoami /groups | find "S-1-5-32-544" > nul
if errorlevel 1 goto ende
echo Benutzer %username% ist lokaler Administrator.
:ende
In C# it looks like this:
在 C# 中,它看起来像这样:
private bool IsAdmin
{
get
{
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.Contains("S-1-5-32-544"));
if (c != null)
return true;
}
return false;
}
}
But in .net < 4.5 the WindowsPrincipal
class does not contain the UserClaims
property
and I found no way to get this information.
但是在 .net < 4.5 中,WindowsPrincipal
该类不包含该UserClaims
属性,我发现无法获取此信息。
回答by Grzegorz D?browski
I think there is one more issue. I checked solutions provided by you and have to say that in the installation of Windows 7 and logged on as an admin the check does not work. Windows never returns information that process runs in an elevated mode. So the sequence:
我认为还有一个问题。我检查了您提供的解决方案,不得不说在安装 Windows 7 并以管理员身份登录时,检查不起作用。Windows 从不返回进程以提升模式运行的信息。所以顺序:
if (IsUacEnabled)
return IsProcessInElevatedMode();
return IsUserAdmin();
does not returns true when logged as an Administrator but the process has all privileges to perform system operations (e.g. stop system services). The working sequence is:
以管理员身份登录时不返回真,但该进程拥有执行系统操作的所有权限(例如停止系统服务)。工作顺序是:
if (IsUserAdmin())
return true;
if (IsUacEnabled)
return IsProcessInElevatedMode();
return false;
You should first check if the process is run in Administrator context. Additional info:
您应该首先检查该进程是否在管理员上下文中运行。附加信息:
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
All of that methods has been described in previous posts.
所有这些方法都在之前的帖子中进行了描述。
回答by Jeppe Stig Nielsen
(new answer sixyears after the question was asked)
(提出问题六年后的新答案)
Disclaimer: This is just something that happened to work on my particular OS with my particular settings with my particular user:
免责声明:这只是在我的特定操作系统上使用我的特定用户的特定设置发生的事情:
using System.Security.Principal;
// ...
static bool IsElevated
{
get
{
return WindowsIdentity.GetCurrent().Owner
.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid);
}
}
So when I run this "Run as administrator", the property get
accessor returns true
. When running normally (even if my user "is" administrator, just not running this particular application "as administrator"), it returns false
.
所以当我运行这个“以管理员身份运行”时,属性get
访问器返回true
. 正常运行时(即使我的用户“是”管理员,只是没有“以管理员身份”运行这个特定的应用程序),它会返回false
.
This seems much simpler than many other answers.
这似乎比许多其他答案简单得多。
I have no idea if there are cases where this fails.
我不知道是否有失败的情况。
PS! This also seems OK:
附注!这似乎也可以:
static bool IsElevated
{
get
{
var id = WindowsIdentity.GetCurrent();
return id.Owner != id.User;
}
}
回答by Soroush Falahati
Using UACHelpernuget package: https://www.nuget.org/packages/UACHelper/
使用UACHelpernuget 包:https://www.nuget.org/packages/UACHelper/
if (UACHelper.IsElevated)
// something
else
// something else
There are a lot of other properties that can be used to detect if the user is, in fact, an administrator, or if the process is running under UAC virtualization, or if the desktop owner is the process owner. (Run as from limited account)
还有许多其他属性可用于检测用户是否实际上是管理员,或者进程是否在 UAC 虚拟化下运行,或者桌面所有者是否是进程所有者。(从受限帐户运行)
Check the read me for more information.
查看自述以获取更多信息。
回答by John Smith
This Answerhas a few problems. First, it doesn't get any System processes that run as Admin (for example under NT-Authority/SYSTEM). The code example below fixes all problems (detects, LocalAdmins, DomainAdmins, and LocalSystemAdmins)
这个答案有几个问题。首先,它没有任何以管理员身份运行的系统进程(例如在 NT-Authority/SYSTEM 下)。下面的代码示例修复了所有问题(检测、LocalAdmins、DomainAdmins 和 LocalSystemAdmins)
If you just want the current Process, replace pHandle
with Process.GetCurrentProcess().Handle
如果您只想要当前进程,请替换pHandle
为Process.GetCurrentProcess().Handle
NOTE: You must have certain privileges to run it. (Every AdminProcess has them but needs to active them first, Services have them activated by default)
注意:您必须具有某些权限才能运行它。(每个 AdminProcess 都有它们,但需要先激活它们,Services 默认激活它们)
internal static bool IsProcessElevatedEx(this IntPtr pHandle) {
var token = IntPtr.Zero;
if (!OpenProcessToken(pHandle, MAXIMUM_ALLOWED, ref token))
throw new Win32Exception(Marshal.GetLastWin32Error(), "OpenProcessToken failed");
WindowsIdentity identity = new WindowsIdentity(token);
WindowsPrincipal principal = new WindowsPrincipal(identity);
bool result = principal.IsInRole(WindowsBuiltInRole.Administrator)
|| principal.IsInRole(0x200); //Domain Administrator
CloseHandle(token);
return result;
}