C# 在.NET/C中#测试进程是否具有管理权限
是否有一种规范的方法来测试进程在计算机上是否具有管理权限 我将开始一个长时间运行的进程,在进程生命周期的稍后,它将尝试一些需要管理员权限的事情C# 在.NET/C中#测试进程是否具有管理权限,c#,.net,windows,security,C#,.net,Windows,Security,是否有一种规范的方法来测试进程在计算机上是否具有管理权限 我将开始一个长时间运行的进程,在进程生命周期的稍后,它将尝试一些需要管理员权限的事情 我希望能够提前测试进程是否具有这些权限,而不是稍后进行测试。这将检查用户是否在本地管理员组中(假设您没有检查域管理员权限) Use可以将WMI与类似的东西一起使用,以确定该帐户是否是管理员,以及您想知道的关于该帐户的任何其他信息 using System; using System.Management; using System.Windows.For
我希望能够提前测试进程是否具有这些权限,而不是稍后进行测试。这将检查用户是否在本地管理员组中(假设您没有检查域管理员权限)
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);
}
}
}
}
为了使入门更容易,请下载
您还可以在计算机/网络上使用它访问active directory(LDAP)或其他任何内容如果您想确保您的解决方案在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;
}
从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
}
[DllImport(“advapi32.dll”,SetLastError=true)]
静态外部bool GetTokenInformation(IntPtr tokenHandle、TokenInformationClass TokenInformationClass、IntPtr tokenInformation、int tokenInformationLength、out int returnLength);
///
///传递给以指定什么
///有关要返回的令牌的信息。
///
枚举令牌信息类
{
令牌用户=1,
令牌组,
代币特权,
代币所有人,
TokenPrimaryGroup,
代币,
代币来源,
令牌类型,
令牌模拟级别,
统计数字,,
受限制的小岛屿发展中国家,
TokenSessionId,
令牌组和特权,
TokenSessionReference,
沙博森特,
这项政策,
象征起源,
标记提升类型,
TokenLinkedToken,
象征性的提升,
有限制,,
令牌访问信息,
允许令牌虚拟化,
已启用令牌虚拟化,
TokenIntegrityLevel,
令牌访问,
TokenMandatoryPolicy,
TokenLogonSid,
MaxTokenInfoClass
}
///
///用户令牌的提升类型。
///
枚举标记提升类型
{
TokenElevationTypeDefault=1,
TokenElevationTypeFull,
TokenElevationTypeLimited
}
然后,实际代码用于检测用户是否是管理员(如果是,则返回true,否则返回false)
var identity=WindowsIdentity.GetCurrent();
如果(identity==null)抛出新的InvalidOperationException(“无法获取当前用户标识”);
var principal=新的WindowsPrincipal(标识);
//检查此用户是否具有管理员角色。如果有,请立即返回。
//如果UAC处于打开状态,并且进程没有提升,那么实际上会返回false。
if(principal.IsInRole(WindowsBuiltInRole.Administrator))返回true;
//如果我们没有在Vista以后的版本中运行,我们就不必担心检查UAC。
if(Environment.OSVersion.PlatformID.Win32NT | | Environment.OSVersion.Version.Major<6)
{
//操作系统不支持UAC;正在跳过高程检查。
返回false;
}
int-tokendefingth=Marshal.SizeOf(typeof(int));
IntPtr tokenInformation=Marshal.AllocHGlobal(令牌长度);
尝试
{
var-token=identity.token;
var result=GetTokenInformation(令牌,令牌信息类。令牌提升类型,令牌信息,令牌长度,输出令牌长度);
如果(!结果)
{
var exception=Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error());
抛出新的InvalidOperationException(“无法获取令牌信息”,异常);
}
var-elevationType=(TokenElevationType)Marshal.ReadInt32(tokenInformation);
开关(升降式)
{
大小写TokenElevationType.TokenElevationType默认值:
//TokenElevationTypeDefault-用户未使用分割令牌,因此无法提升。
返回false;
大小写TokenElevationType.TokenElevationTypeFull:
//TokenElevationTypeFull-用户有一个拆分令牌,并且进程正在提升运行。假设他们是管理员。
返回true;
案例TokenElevationType.TokenElevationTypeLimited:
//TokenElevationTypeLimited-用户有一个拆分令牌,但进程没有运行提升。假设他们是管理员。
返回true;
违约:
//未知的令牌提升类型。
返回false;
}
}
最后
{
if(tokenInformation!=IntPtr.Zero)Marshal.FreeHGlobal(tokenInformation);
}
关于:
using System.Runtime.InteropServices;
internal static class Useful {
[DllImport("shell32.dll", EntryPoint = "IsUserAnAdmin")]
public static extern bool IsUserAnAdministrator();
}
尝试了欧文的代码,但没有编译 让它像这样工作:
[DllImport("shell32.dll")] public static extern bool IsUserAnAdmin();
使用.NET Framework 4.5,检查用户是否在administrators组中似乎更容易:
WindowsPrincipal principal = WindowsPrincipal.Current;
bool canBeAdmin = principal.Claims.Any((c) => c.Value == "S-1-5-32-544");
有4种可能的方法-我更喜欢:
(new WindowsPrincipal(WindowsIdentity.GetCurrent())).IsInRole(WindowsBuiltInRole.Administrator);
以下代码为您提供当前用户身份的所有相关索赔数据的列表
注意:在WindowsPrincipal.Current.claims和(新WindowsPrincipal(WindowsIdentity.GetCurrent())之间返回的索赔列表之间存在很大差异
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();
其他使用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;
在Windows 10和Ubuntu Linux上的.NET Core 3中测试了以下各项:
[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;
[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;
}