我确实解决了!!!
解释
我意识到我需要的是会话 ID(环境)以某种方式获取登录用户名(上下文的所有者)。
获取会话 ID 非常简单:
int session = System.Diagnostics.Process.GetCurrentProcess().SessionId;
到这个时候,我的目标是让用户名链接到这个会话,然后我发现了这个
从 SessionID 获取 Windows 用户名
现在,使用用户名,我认为很容易检查该用户名是否属于管理员组。我错了。我发现需要使用 wmi 和 pinvoke 的最简单方法。
主要问题是,为了进行查询,我必须知道当前操作系统中管理员组的名称,即取决于语言。
解决方案是这样的:
http://www.pinvoke.net/default.aspx/advapi32.lookupaccountsid
我调整了代码,将所有部分放在一起,就是这样。
总结一下,我找到了 sessionid,找到了链接到 session 的用户名,找到了 OS Administrators 组名,并做了一些 Wmi 查询来检查用户是否是管理员。
这个解决方案对我来说很好,但我必须说运行速度很慢。
如果有人可以改进此代码,或者如果它对其他人有用,我就把它留在这里。
只要记住添加对 System.Management 的引用即可;我使用了 Visual Studio C# Express 2010。该项目是一个 Windows 窗体应用程序。
快乐编码!!!
//Make sure to add a reference to System.Management;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Management;
using System.Security.Principal;
using System.Collections;
using System.Runtime.InteropServices;
namespace RealUSer
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//Getting the session id
int session = System.Diagnostics.Process.GetCurrentProcess().SessionId;
//Getting the username related to the session id
string user = GetUsernameBySessionId(session, false);
try
{
//Cheching if the user belongs to the local admin group using wmi
if (CheckAdminRights(user))
{
MessageBox.Show("The logged in User "+user+" is an Admin");
}
else
{
MessageBox.Show("The logged in User " + user + " is not an Admin");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
/// <summary>
/// This method checks if the context user, belongs to the local administrators group
/// </summary>
/// <param name="username"></param>
/// <returns></returns>
public bool CheckAdminRights(string username)
{
bool result = false;
List<string> admins = new List<string>();
//SelectQuery query = new SelectQuery("Select AccountType from Win32_UserAccount where Name=\"" + username + "\"");
SelectQuery query = new SelectQuery("SELECT * FROM win32_group WHERE Name=\"" + getAdministratorGroupName() + "\"");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
ManagementObjectCollection OC = searcher.Get();
IEnumerator enumerator = OC.GetEnumerator();
enumerator.MoveNext();
ManagementObject O = (ManagementObject)enumerator.Current;
ManagementObjectCollection adminusers = O.GetRelated("Win32_UserAccount");
foreach (ManagementObject envVar in adminusers)
{
admins.Add(envVar["Name"].ToString());
//Console.WriteLine("Username : {0}", envVar["Name"]);
//foreach (PropertyData pd in envVar.Properties)
// Console.WriteLine(string.Format(" {0,20}: {1}", pd.Name, pd.Value));
}
if (admins.Contains(username))
result = true;
return result;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///This code will find the administrators group name, independent of the OS language using the LookupAccountSid function with the BUILTIN\Administrators sid
#region
const int NO_ERROR = 0;
const int ERROR_INSUFFICIENT_BUFFER = 122;
enum SID_NAME_USE
{
SidTypeUser = 1,
SidTypeGroup,
SidTypeDomain,
SidTypeAlias,
SidTypeWellKnownGroup,
SidTypeDeletedAccount,
SidTypeInvalid,
SidTypeUnknown,
SidTypeComputer
}
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool LookupAccountSid(
string lpSystemName,
[MarshalAs(UnmanagedType.LPArray)] byte[] Sid,
StringBuilder lpName,
ref uint cchName,
StringBuilder ReferencedDomainName,
ref uint cchReferencedDomainName,
out SID_NAME_USE peUse);
public string getAdministratorGroupName()
{
String result = "";
StringBuilder name = new StringBuilder();
uint cchName = (uint)name.Capacity;
StringBuilder referencedDomainName = new StringBuilder();
uint cchReferencedDomainName = (uint)referencedDomainName.Capacity;
SID_NAME_USE sidUse;
// Sid for BUILTIN\Administrators
byte[] Sid = new byte[] { 1, 2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2 };
int err = NO_ERROR;
if (!LookupAccountSid(null, Sid, name, ref cchName, referencedDomainName, ref cchReferencedDomainName, out sidUse))
{
err = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
if (err == ERROR_INSUFFICIENT_BUFFER)
{
name.EnsureCapacity((int)cchName);
referencedDomainName.EnsureCapacity((int)cchReferencedDomainName);
err = NO_ERROR;
if (!LookupAccountSid(null, Sid, name, ref cchName, referencedDomainName, ref cchReferencedDomainName, out sidUse))
err = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
}
}
if (err == 0)
{
result = name.ToString();
}
return result;
}
#endregion
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void Form1_Load(object sender, EventArgs e)
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///This code will retrieve user name given the session id
#region
[DllImport("Wtsapi32.dll")]
private static extern bool WTSQuerySessionInformation(IntPtr hServer, int sessionId, WTS_INFO_CLASS wtsInfoClass, out System.IntPtr ppBuffer, out int pBytesReturned);
[DllImport("Wtsapi32.dll")]
private static extern void WTSFreeMemory(IntPtr pointer);
public static string GetUsernameBySessionId(int sessionId, bool prependDomain)
{
IntPtr buffer;
int strLen;
string username = "SYSTEM";
if (WTSQuerySessionInformation(IntPtr.Zero, sessionId, WTS_INFO_CLASS.WTSUserName, out buffer, out strLen) && strLen > 1)
{
username = Marshal.PtrToStringAnsi(buffer);
WTSFreeMemory(buffer);
if (prependDomain)
{
if (WTSQuerySessionInformation(IntPtr.Zero, sessionId, WTS_INFO_CLASS.WTSDomainName, out buffer, out strLen) && strLen > 1)
{
username = Marshal.PtrToStringAnsi(buffer) + "\\" + username;
WTSFreeMemory(buffer);
}
}
}
return username;
}
public enum WTS_INFO_CLASS
{
WTSInitialProgram,
WTSApplicationName,
WTSWorkingDirectory,
WTSOEMId,
WTSSessionId,
WTSUserName,
WTSWinStationName,
WTSDomainName,
WTSConnectState,
WTSClientBuildNumber,
WTSClientName,
WTSClientDirectory,
WTSClientProductId,
WTSClientHardwareId,
WTSClientAddress,
WTSClientDisplay,
WTSClientProtocolType
}
#endregion
}
}